From b21e7fec19094e08f109b78b6c118d5469858503 Mon Sep 17 00:00:00 2001 From: Kenneth Lausdahl Date: Thu, 10 Nov 2022 11:21:06 +0100 Subject: [PATCH 01/54] adding fmi3 support - in progress --- ast/src/main/resources/mabl.astv2 | 4 + ast/src/main/resources/mabl.astv2.tostring | 6 +- .../DefaultExternalValueFactory.java | 31 + .../maestro/interpreter/Fmi3Interpreter.java | 1046 +++++++++++++++++ .../maestro/interpreter/values/ByteValue.java | 48 + .../interpreter/values/FloatValue.java | 68 ++ .../maestro/interpreter/values/LongValue.java | 45 + .../interpreter/values/ShortValue.java | 48 + .../interpreter/values/fmi/Fmu3Value.java | 13 + .../org/intocps/maestro/Fmi3ModuleTest.java | 16 + .../org/intocps/maestro/parser/MablLexer.g4 | 4 + .../org/intocps/maestro/parser/MablParser.g4 | 4 + .../parser/ParseTree2AstConverter.java | 20 + pom.xml | 2 +- .../maestro/typechecker/TypeChecker.java | 2 +- .../org/intocps/maestro/typechecker/FMI3.mabl | 300 +++++ .../maestro/typechecker/ModuleTest.java | 67 ++ 17 files changed, 1721 insertions(+), 3 deletions(-) create mode 100644 interpreter/src/main/java/org/intocps/maestro/interpreter/Fmi3Interpreter.java create mode 100644 interpreter/src/main/java/org/intocps/maestro/interpreter/values/ByteValue.java create mode 100644 interpreter/src/main/java/org/intocps/maestro/interpreter/values/FloatValue.java create mode 100644 interpreter/src/main/java/org/intocps/maestro/interpreter/values/LongValue.java create mode 100644 interpreter/src/main/java/org/intocps/maestro/interpreter/values/ShortValue.java create mode 100644 interpreter/src/main/java/org/intocps/maestro/interpreter/values/fmi/Fmu3Value.java create mode 100644 maestro/src/test/java/org/intocps/maestro/Fmi3ModuleTest.java create mode 100644 typechecker/src/main/resources/org/intocps/maestro/typechecker/FMI3.mabl create mode 100644 typechecker/src/test/java/org/intocps/maestro/typechecker/ModuleTest.java diff --git a/ast/src/main/resources/mabl.astv2 b/ast/src/main/resources/mabl.astv2 index fb9c96089..ecb10d78b 100644 --- a/ast/src/main/resources/mabl.astv2 +++ b/ast/src/main/resources/mabl.astv2 @@ -169,4 +169,8 @@ type = {real} | {int} | {uInt} + | {float} + | {short} + | {byte} + | {long} ; diff --git a/ast/src/main/resources/mabl.astv2.tostring b/ast/src/main/resources/mabl.astv2.tostring index f0caf93e0..03bea683c 100644 --- a/ast/src/main/resources/mabl.astv2.tostring +++ b/ast/src/main/resources/mabl.astv2.tostring @@ -88,4 +88,8 @@ import java.util.stream.Collectors; %type->#primitive->string="string" %type->#primitive->#numeric->real="real" %type->#primitive->#numeric->int="int" -%type->#primitive->#numeric->uInt="uint" \ No newline at end of file +%type->#primitive->#numeric->uInt="uint" +%type->#primitive->#numeric->long="long" +%type->#primitive->#numeric->short="short" +%type->#primitive->#numeric->float="float" +%type->#primitive->#numeric->byte="byte" \ No newline at end of file diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/DefaultExternalValueFactory.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/DefaultExternalValueFactory.java index 0cd9b1660..4bb0e5ddc 100644 --- a/interpreter/src/main/java/org/intocps/maestro/interpreter/DefaultExternalValueFactory.java +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/DefaultExternalValueFactory.java @@ -11,6 +11,7 @@ import org.intocps.maestro.interpreter.values.csv.CsvDataWriter; import org.intocps.maestro.interpreter.values.datawriter.DataWriterValue; import org.intocps.maestro.interpreter.values.derivativeestimator.DerivativeEstimatorValue; +import org.intocps.maestro.interpreter.values.fmi.Fmu3Value; import org.intocps.maestro.interpreter.values.fmi.FmuValue; import org.intocps.maestro.interpreter.values.modeltransition.ModelTransitionValue; import org.intocps.maestro.interpreter.values.simulationcontrol.SimulationControlValue; @@ -374,6 +375,36 @@ public Either instantiate(List args) { } } + @IValueLifecycleHandler.ValueLifecycle(name = "FMI3") + public static class Fmi3LifecycleHandler extends BaseLifecycleHandler { + final private File workingDirectory; + + public Fmi3LifecycleHandler(File workingDirectory) { + this.workingDirectory = workingDirectory; + } + + @Override + public void destroy(Value value) { + if (value instanceof Fmu3Value) { + Fmu3Value fmuVal = (Fmu3Value) value; + FunctionValue unloadFunction = (FunctionValue) fmuVal.lookup("unload"); + unloadFunction.evaluate(Collections.emptyList()); + } + } + + @Override + public Either instantiate(List args) { + String guid = ((StringValue) args.get(0)).getValue(); + String path = ((StringValue) args.get(1)).getValue(); + try { + path = (new URI(path)).getRawPath(); + } catch (URISyntaxException e) { + return Either.left(new AnalysisException("The path passed to load is not a URI", e)); + } + return Either.right(new Fmi3Interpreter(workingDirectory).createFmiValue(path, guid)); + } + } + @IValueLifecycleHandler.ValueLifecycle(name = "JFMI2") public static class JFmi2LifecycleHandler extends BaseLifecycleHandler { final private File workingDirectory; diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/Fmi3Interpreter.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/Fmi3Interpreter.java new file mode 100644 index 000000000..2a37bb5fc --- /dev/null +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/Fmi3Interpreter.java @@ -0,0 +1,1046 @@ +package org.intocps.maestro.interpreter; + +import org.apache.commons.lang3.ArrayUtils; +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.core.Layout; +import org.apache.logging.log4j.core.impl.Log4jLogEvent; +import org.apache.logging.log4j.core.layout.PatternLayout; +import org.apache.logging.log4j.message.ParameterizedMessage; +import org.intocps.fmi.*; +import org.intocps.fmi.jnifmuapi.fmi3.FmuResult; +import org.intocps.fmi.jnifmuapi.fmi3.*; +import org.intocps.maestro.interpreter.values.*; +import org.intocps.maestro.interpreter.values.fmi.Fmu3Value; +import org.intocps.maestro.interpreter.values.fmi.FmuComponentStateValue; +import org.intocps.maestro.interpreter.values.fmi.FmuComponentValue; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.*; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.stream.Collectors; + +import static org.intocps.maestro.interpreter.Fmi2Interpreter.*; + +public class Fmi3Interpreter { + final static Logger logger = LoggerFactory.getLogger(Interpreter.class); + private final File workingDirectory; + + public Fmi3Interpreter(File workingDirectory) { + + this.workingDirectory = workingDirectory; + } + + public static Map createFmuMembers(File workingDirectory, String guid, IFmi3Fmu fmu) { + Map functions = new HashMap<>(); + + /* + * + * FMI3Instance instantiateCoSimulation(string instanceName, string instantiationToken, string resourceLocation, bool visible, bool loggingOn, + bool eventModeUsed, bool earlyReturnAllowed, uint[] requiredIntermediateVariables); //, ILogMessageCallback logMessage,IIntermediateUpdateCallback intermediateUpdate + +FMI2Component instantiateCoSimulationWrapAsFmi2(string instanceName, string instantiationToken, string resourceLocation, bool visible, bool loggingOn, + bool eventModeUsed, bool earlyReturnAllowed, uint[] requiredIntermediateVariables);//, ILogMessageCallback logMessage,IIntermediateUpdateCallback intermediateUpdate + + * + * */ + + + functions.put("instantiateCoSimulation", new FunctionValue.ExternalFunctionValue(fargs -> { + + Fmi2Interpreter.checkArgLength(fargs, 3); + + String name = Fmi2Interpreter.getString(fargs.get(0)); + boolean visible = Fmi2Interpreter.getBool(fargs.get(1)); + boolean logginOn = Fmi2Interpreter.getBool(fargs.get(2)); + + try { + + long startInstantiateTime = System.nanoTime(); + + logger.debug(String.format("Loading native FMU. GUID: %s, NAME: %s", "" + guid, "" + name)); + + BufferedOutputStream fmuLogOutputStream = + workingDirectory == null ? null : new BufferedOutputStream(new FileOutputStream(new File(workingDirectory, name + ".log"))); + + final String formatter = "{} {} {} {}"; + String pattern = "%d{ISO8601} %-5p - %m%n"; + + Layout layout = PatternLayout.newBuilder().withPattern(pattern).withCharset(StandardCharsets.UTF_8).build();// + boolean eventModeUsed = false; + boolean earlyReturnAllowed = false; + long[] requiredIntermediateVariables = new long[0]; + IFmi3Instance instance = + fmu.instantiateCoSimulation(name, guid, visible, logginOn, eventModeUsed, earlyReturnAllowed, requiredIntermediateVariables, + (instanceName, status, category, message) -> { + logger.info("NATIVE: instance: '{}', status: '{}', category: '{}', message: {}", instanceName, status, category, + message); + { + + if (fmuLogOutputStream == null) { + return; + } + + Log4jLogEvent.Builder builder = Log4jLogEvent.newBuilder() + .setMessage(new ParameterizedMessage(formatter, category, status, instanceName, message)); + + + switch (status) { + case OK: + case Discard: + builder.setLevel(Level.INFO); + break; + case Error: + case Fatal: + builder.setLevel(Level.ERROR); + case Warning: + builder.setLevel(Level.WARN); + break; + default: + builder.setLevel(Level.TRACE); + break; + } + + try { + Log4jLogEvent event = builder.build(); + fmuLogOutputStream.write(layout.toByteArray(event)); + } catch (IOException e) { + e.printStackTrace(); + } + } + }, + (instanceEnvironment, intermediateUpdateTime, clocksTicked, intermediateVariableSetRequested, intermediateVariableGetAllowed, intermediateStepFinished, canReturnEarly) -> new IIntermediateUpdateCallback.IntermediateUpdateResponse( + false, intermediateUpdateTime)); + + + if (instance == null) { + logger.debug("Instance instantiate failed"); + return new NullValue(); + } + long stopInstantiateTime = System.nanoTime(); + System.out.println("Interpretation instantiate took: " + (stopInstantiateTime - startInstantiateTime)); + + return getFmuInstanceValue(fmuLogOutputStream, instance); + + + } catch (IOException e) { + e.printStackTrace(); + } + + return null; + })); + + + functions.put("freeInstance", new FunctionValue.ExternalFunctionValue(fargs -> { + + fargs = fargs.stream().map(Value::deref).collect(Collectors.toList()); + + logger.debug("freeInstance"); + + if (fargs.size() != 1) { + throw new InterpreterException("Too few arguments"); + } + + if (!(fargs.get(0) instanceof FmuComponentValue)) { + throw new InterpreterException("Argument must be an external module reference"); + } + + FmuComponentValue component = (FmuComponentValue) fargs.get(0); + + try { + OutputStream loggerOutputStream = component.getFmuLoggerOutputStream(); + if (loggerOutputStream != null) { + loggerOutputStream.close(); + } + component.getModule().freeInstance(); + } catch (IOException | FmuInvocationException e) { + e.printStackTrace(); + } + + + return new VoidValue(); + })); + + functions.put("unload", new FunctionValue.ExternalFunctionValue(fargs -> { + fargs = fargs.stream().map(Value::deref).collect(Collectors.toList()); + + logger.debug("unload"); + + if (fargs.size() != 0) { + throw new InterpreterException("Too many arguments"); + } + + try { + fmu.unLoad(); + } catch (FmuInvocationException e) { + e.printStackTrace(); + } + + return new VoidValue(); + })); + return functions; + } + + private static Value getFmuInstanceValue(BufferedOutputStream fmuLogOutputStream, IFmi3Instance instance) throws NoSuchMethodException { + + //populate component functions + + + Map componentMembers = new HashMap<>(createGetSetMembers(instance)); + + //void methods + componentMembers.put("freeInstance", new FunctionValue.ExternalFunctionValue(fcargs -> { + + checkArgLength(fcargs, 0); + try { + instance.freeInstance(); + return new VoidValue(); + } catch (FmuInvocationException e) { + throw new InterpreterException(e); + } + + })); + + String[] voidStatusMethods = + new String[]{"exitInitializationMode", "enterEventMode", "terminate", "reset", "enterConfigurationMode", "exitConfigurationMode", + "evaluateDiscreteStates", "enterContinuousTimeMode", "enterStepMode"}; + + for (String methodName : voidStatusMethods) { + Method method = componentMembers.getClass().getMethod(methodName); + + componentMembers.put(methodName, new FunctionValue.ExternalFunctionValue(fcargs -> { + + checkArgLength(fcargs, 0); + + + try { + Fmi3Status res = (Fmi3Status) method.invoke(instance); + return status2IntValue(res); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new InterpreterException(e); + } + })); + + } + + // componentMembers.put("setDebugLogging", new FunctionValue.ExternalFunctionValue(fcargs -> { + // + // checkArgLength(fcargs, 3); + // + // boolean debugLogginOn = getBool(fcargs.get(0)); + // List categories = getArrayValue(fcargs.get(2), StringValue.class); + // + // try { + // Fmi3Status res = instance.setDebugLogging(debugLogginOn, categories.stream().map(StringValue::getValue).toArray(String[]::new)); + // return status2IntValue(res); + // } catch (FmuInvocationException e) { + // throw new InterpreterException(e); + // } + // })); + + + /* + +int setDebugLogging(bool loggingOn, string categories[]); +int enterInitializationMode(bool toleranceDefined, real tolerance, real startTime, bool stopTimeDefined, + +int getBinary(uint valueReferences[], int nValueReferences, byte values[][], int nValues); +int setBinary(uint valueReferences[], int nValueReferences, long sizes[], byte array_name[][], int nValues); +int getNumberOfVariableDependencies(uint valueReference, out int nDependencies); +int getVariableDependencies(uint dependent, int elementIndicesOfDependent[], uint independents[], +int getFMUState(out FMUS3tate FMUState); +int setFMUState(FMUS3tate FMUState); +int freeFMUState(out FMUS3tate FMUState); +int getDirectionalDerivative(uint unknowns[], int nUnknowns, uint knowns[], int nKnowns, real seed[], int nSeed, +int getAdjointDerivative(uint unknowns[], int nUnknowns, uint knowns[], int nKnowns, real seed[], int nSeed, +int getClock(uint valueReferences[], int nValueReferences, bool values[]); +int setClock(uint valueReferences[], int nValueReferences, bool values[]); +int getIntervalDecimal(uint valueReferences[], int nValueReferences, real intervals[], +int getIntervalFraction(uint valueReferences[], int nValueReferences, uint intervalCounters[], uint resolutions[], +int getShiftDecimal(uint valueReferences[], int nValueReferences, real shifts[]); +int getShiftFraction(uint valueReferences[], int nValueReferences, uint shiftCounters[], uint resolutions[]); +int setIntervalDecimal(uint valueReferences[], int nValueReferences, real interval[]); +int setIntervalFraction(uint valueReferences[], int nValueReferences, uint intervalCounter[], uint resolution[]); +int setShiftDecimal(uint valueReferences[], int nValueReferences, real shifts[]); +int setShiftFraction(uint valueReferences[], int nValueReferences, uint counters[], uint resolutions[]); +int updateDiscreteStates(bool[] discreteStatesNeedUpdate, bool[] terminateSimulation, +int completedIntegratorStep(bool nosetFMUStatePriorToCurrentPoint, bool[] enterEventMode, +int setTime(real time); +int setContinuousStates(real continuousStates[], int nContinuousStates); +int getContinuousStateDerivatives(real derivatives[], int nContinuousStates); +int getEventIndicators(real eventIndicators[], int nEventIndicators); +int getContinuousStates(real continuousStates[], int nContinuousStates); +int getNominalsOfContinuousStates(real nominals[], int nContinuousStates); +int getNumberOfEventIndicators(int[] nEventIndicators); +int getNumberOfContinuousStates(int[] nContinuousStates); +int getOutputDerivatives(uint valueReferences[], int nValueReferences, int orders[], real values[], int nValues); +int doStep(real currentCommunicationPoint, real communicationStepSize, bool nosetFMUStatePriorToCurrentPoint, +int activateModelPartition(uint clockReference, real activationTime); + + */ + + + componentMembers.put("setDebugLogging", new FunctionValue.ExternalFunctionValue(fcargs -> { + + checkArgLength(fcargs, 3); + + boolean debugLogginOn = getBool(fcargs.get(0)); + // int arraySize = getInteger(fcargs.get(1)); + List categories = getArrayValue(fcargs.get(2), StringValue.class); + + try { + Fmi3Status res = instance.setDebugLogging(debugLogginOn, categories.stream().map(StringValue::getValue).toArray(String[]::new)); + return new IntegerValue(res.value); + } catch (FmuInvocationException e) { + throw new InterpreterException(e); + } + })); + + componentMembers.put("setupExperiment", new FunctionValue.ExternalFunctionValue(fcargs -> { + + checkArgLength(fcargs, 5); + + boolean toleranceDefined = getBool(fcargs.get(0)); + double tolerance = getDouble(fcargs.get(1)); + double startTime = getDouble(fcargs.get(2)); + boolean stopTimeDefined = getBool(fcargs.get(3)); + double stopTime = getDouble(fcargs.get(4)); + try { + Fmi2Status res = instance.setupExperiment(toleranceDefined, tolerance, startTime, stopTimeDefined, stopTime); + return new IntegerValue(res.value); + } catch (FmuInvocationException e) { + throw new InterpreterException(e); + } + })); + componentMembers.put("enterInitializationMode", new FunctionValue.ExternalFunctionValue(fcargs -> { + + checkArgLength(fcargs, 0); + try { + Fmi2Status res = instance.enterInitializationMode(); + return new IntegerValue(res.value); + } catch (FmuInvocationException e) { + throw new InterpreterException(e); + } + + })); + componentMembers.put("exitInitializationMode", new FunctionValue.ExternalFunctionValue(fcargs -> { + checkArgLength(fcargs, 0); + try { + Fmi2Status res = instance.exitInitializationMode(); + return new IntegerValue(res.value); + } catch (FmuInvocationException e) { + throw new InterpreterException(e); + } + })); + componentMembers.put("setReal", new FunctionValue.ExternalFunctionValue(fcargs -> { + checkArgLength(fcargs, 3); + long elementsToUse = getUint(fcargs.get(1)); + long[] scalarValueIndices = + getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) + .toArray(); + double[] values = getArrayValue(fcargs.get(2), Optional.of(elementsToUse), NumericValue.class).stream().limit(elementsToUse) + .mapToDouble(NumericValue::realValue).toArray(); + + try { + Fmi2Status res = instance.setReals(scalarValueIndices, values); + return new IntegerValue(res.value); + } catch (InvalidParameterException | FmiInvalidNativeStateException e) { + throw new InterpreterException(e); + } + + })); + componentMembers.put("getReal", new FunctionValue.ExternalFunctionValue(fcargs -> { + + checkArgLength(fcargs, 3); + + if (!(fcargs.get(2) instanceof UpdatableValue)) { + throw new InterpreterException("value not a reference value"); + } + long elementsToUse = getUint(fcargs.get(1)); + + long[] scalarValueIndices = + getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) + .toArray(); + + + try { + org.intocps.fmi.FmuResult res = instance.getReal(scalarValueIndices); + + if (res.status == Fmi2Status.OK) { + UpdatableValue ref = (UpdatableValue) fcargs.get(2); + + List values = Arrays.stream(ArrayUtils.toObject(res.result)).limit(elementsToUse).map(d -> new RealValue(d)) + .collect(Collectors.toList()); + + ref.setValue(new ArrayValue<>(values)); + } + + + return new IntegerValue(res.status.value); + + } catch (FmuInvocationException e) { + throw new InterpreterException(e); + } + + + })); + componentMembers.put("setInteger", new FunctionValue.ExternalFunctionValue(fcargs -> { + checkArgLength(fcargs, 3); + long elementsToUse = getUint(fcargs.get(1)); + long[] scalarValueIndices = + getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) + .toArray(); + int[] values = + getArrayValue(fcargs.get(2), Optional.of(elementsToUse), IntegerValue.class).stream().mapToInt(IntegerValue::getValue).toArray(); + + try { + Fmi2Status res = instance.setIntegers(scalarValueIndices, values); + return new IntegerValue(res.value); + } catch (InvalidParameterException | FmiInvalidNativeStateException e) { + throw new InterpreterException(e); + } + })); + componentMembers.put("getInteger", new FunctionValue.ExternalFunctionValue(fcargs -> { + + checkArgLength(fcargs, 3); + long elementsToUse = getUint(fcargs.get(1)); + + if (!(fcargs.get(2) instanceof UpdatableValue)) { + throw new InterpreterException("value not a reference value"); + } + + long[] scalarValueIndices = + getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) + .toArray(); + + + try { + org.intocps.fmi.FmuResult res = instance.getInteger(scalarValueIndices); + + if (res.status == Fmi2Status.OK) { + UpdatableValue ref = (UpdatableValue) fcargs.get(2); + + List values = Arrays.stream(ArrayUtils.toObject(res.result)).limit(elementsToUse).map(i -> new IntegerValue(i)) + .collect(Collectors.toList()); + + ref.setValue(new ArrayValue<>(values)); + } + + + return new IntegerValue(res.status.value); + + } catch (FmuInvocationException e) { + throw new InterpreterException(e); + } + + + })); + componentMembers.put("setBoolean", new FunctionValue.ExternalFunctionValue(fcargs -> { + + checkArgLength(fcargs, 3); + long elementsToUse = getUint(fcargs.get(1)); + long[] scalarValueIndices = + getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) + .toArray(); + boolean[] values = ArrayUtils.toPrimitive( + getArrayValue(fcargs.get(2), Optional.of(elementsToUse), BooleanValue.class).stream().map(BooleanValue::getValue) + .collect(Collectors.toList()).toArray(new Boolean[]{})); + + try { + Fmi2Status res = instance.setBooleans(scalarValueIndices, values); + return new IntegerValue(res.value); + } catch (InvalidParameterException | FmiInvalidNativeStateException e) { + throw new InterpreterException(e); + } + })); + componentMembers.put("getBoolean", new FunctionValue.ExternalFunctionValue(fcargs -> { + + checkArgLength(fcargs, 3); + + if (!(fcargs.get(2) instanceof UpdatableValue)) { + throw new InterpreterException("value not a reference value"); + } + + long elementsToUse = getUint(fcargs.get(1)); + + + long[] scalarValueIndices = + getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) + .toArray(); + + + try { + org.intocps.fmi.FmuResult res = instance.getBooleans(scalarValueIndices); + + if (res.status == Fmi2Status.OK) { + UpdatableValue ref = (UpdatableValue) fcargs.get(2); + + List values = + Arrays.stream(ArrayUtils.toObject(res.result)).limit(elementsToUse).map(BooleanValue::new).collect(Collectors.toList()); + + ref.setValue(new ArrayValue<>(values)); + } + + + return new IntegerValue(res.status.value); + + } catch (FmuInvocationException e) { + throw new InterpreterException(e); + } + + })); + componentMembers.put("setString", new FunctionValue.ExternalFunctionValue(fcargs -> { + + checkArgLength(fcargs, 3); + long elementsToUse = getUint(fcargs.get(1)); + + long[] scalarValueIndices = + getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) + .toArray(); + String[] values = getArrayValue(fcargs.get(2), Optional.of(elementsToUse), StringValue.class).stream().map(StringValue::getValue) + .collect(Collectors.toList()).toArray(new String[]{}); + + try { + Fmi2Status res = instance.setStrings(scalarValueIndices, values); + return new IntegerValue(res.value); + } catch (InvalidParameterException | FmiInvalidNativeStateException e) { + throw new InterpreterException(e); + } + + })); + componentMembers.put("getString", new FunctionValue.ExternalFunctionValue(fcargs -> { + + checkArgLength(fcargs, 3); + + if (!(fcargs.get(2) instanceof UpdatableValue)) { + throw new InterpreterException("value not a reference value"); + } + + + long elementsToUse = getUint(fcargs.get(1)); + + + long[] scalarValueIndices = + getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) + .toArray(); + + + try { + org.intocps.fmi.FmuResult res = instance.getStrings(scalarValueIndices); + + if (res.status == Fmi2Status.OK) { + UpdatableValue ref = (UpdatableValue) fcargs.get(2); + + List values = Arrays.stream(res.result).limit(elementsToUse).map(StringValue::new).collect(Collectors.toList()); + + ref.setValue(new ArrayValue<>(values)); + } + + + return new IntegerValue(res.status.value); + + } catch (FmuInvocationException e) { + throw new InterpreterException(e); + } + + + })); + componentMembers.put("doStep", new FunctionValue.ExternalFunctionValue(fcargs -> { + + checkArgLength(fcargs, 3); + + double currentCommunicationPoint = getDouble(fcargs.get(0)); + double communicationStepSize = getDouble(fcargs.get(1)); + boolean noSetFMUStatePriorToCurrentPoint = getBool(fcargs.get(2)); + + try { + Fmi2Status res = instance.doStep(currentCommunicationPoint, communicationStepSize, noSetFMUStatePriorToCurrentPoint); + return new IntegerValue(res.value); + } catch (FmuInvocationException e) { + throw new InterpreterException(e); + } + })); + + componentMembers.put("terminate", new FunctionValue.ExternalFunctionValue(fcargs -> { + checkArgLength(fcargs, 0); + try { + Fmi2Status res = instance.terminate(); + return new IntegerValue(res.value); + } catch (FmuInvocationException e) { + throw new InterpreterException(e); + } + })); + + componentMembers.put("setState", new FunctionValue.ExternalFunctionValue(fcargs -> { + checkArgLength(fcargs, 1); + + Value v = fcargs.get(0).deref(); + + if (v instanceof FmuComponentStateValue) { + try { + FmuComponentStateValue stateValue = (FmuComponentStateValue) v; + Fmi2Status res = instance.setState(stateValue.getModule()); + return new IntegerValue(res.value); + } catch (FmuInvocationException e) { + throw new InterpreterException(e); + } + } + + throw new InterpreterException("Invalid value"); + })); + componentMembers.put("getState", new FunctionValue.ExternalFunctionValue(fcargs -> { + + checkArgLength(fcargs, 1); + + if (!(fcargs.get(0) instanceof UpdatableValue)) { + throw new InterpreterException("value not a reference value"); + } + + + try { + + org.intocps.fmi.FmuResult res = instance.getState(); + + if (res.status == Fmi2Status.OK) { + UpdatableValue ref = (UpdatableValue) fcargs.get(0); + ref.setValue(new FmuComponentStateValue(res.result)); + } + + + return new IntegerValue(res.status.value); + + } catch (FmuInvocationException e) { + throw new InterpreterException(e); + } + + + })); + componentMembers.put("freeState", new FunctionValue.ExternalFunctionValue(fcargs -> { + + checkArgLength(fcargs, 1); + + Value v = fcargs.get(0).deref(); + + if (v instanceof FmuComponentStateValue) { + try { + FmuComponentStateValue stateValue = (FmuComponentStateValue) v; + Fmi2Status res = instance.freeState(stateValue.getModule()); + return new IntegerValue(res.value); + } catch (FmuInvocationException e) { + throw new InterpreterException(e); + } + } + + throw new InterpreterException("Invalid value"); + + + })); + + componentMembers.put("getRealStatus", new FunctionValue.ExternalFunctionValue(fcargs -> { + + checkArgLength(fcargs, 2); + + if (!(fcargs.get(1) instanceof UpdatableValue)) { + throw new InterpreterException("value not a reference value"); + } + + Value kindValue = fcargs.get(0).deref(); + + if (!(kindValue instanceof IntegerValue)) { + throw new InterpreterException("Invalid kind value: " + kindValue); + } + + int kind = ((IntegerValue) kindValue).getValue(); + + Fmi2StatusKind kindEnum = Arrays.stream(Fmi2StatusKind.values()).filter(v -> v.value == kind).findFirst().orElse(null); + + try { + org.intocps.fmi.FmuResult res = instance.getRealStatus(kindEnum); + + if (res.status == Fmi2Status.OK) { + UpdatableValue ref = (UpdatableValue) fcargs.get(1); + + ref.setValue(new RealValue(res.result)); + } + + + return new IntegerValue(res.status.value); + + } catch (FmuInvocationException e) { + throw new InterpreterException(e); + } + + + })); + + componentMembers.put("getRealOutputDerivatives", new FunctionValue.ExternalFunctionValue(fcargs -> { + // int getRealOutputDerivatives(long[] scalarValueIndices, UInt nvr, int[] order, ref double[] derivatives); + checkArgLength(fcargs, 4); + + if (!(fcargs.get(3) instanceof UpdatableValue)) { + throw new InterpreterException("value not a reference value"); + } + + long elementsToUse = getUint(fcargs.get(1)); + + + long[] scalarValueIndices = + getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) + .toArray(); + + int[] orders = + getArrayValue(fcargs.get(2), Optional.of(elementsToUse), NumericValue.class).stream().mapToInt(NumericValue::intValue).toArray(); + + try { + FmuResult res = instance.getRealOutputDerivatives(scalarValueIndices, orders); + + if (res.status == Fmi2Status.OK) { + UpdatableValue ref = (UpdatableValue) fcargs.get(3); + + List values = Arrays.stream(ArrayUtils.toObject(res.result)).limit(elementsToUse).map(d -> new RealValue(d)) + .collect(Collectors.toList()); + + ref.setValue(new ArrayValue<>(values)); + } + + + return new IntegerValue(res.status.value); + + } catch (FmuInvocationException e) { + throw new InterpreterException(e); + } + + + })); + + componentMembers.put("setRealInputDerivatives", new FunctionValue.ExternalFunctionValue(fcargs -> { + // int setRealInputDerivatives(UInt[] scalarValueIndices, UInt nvr, int[] order, ref real[] derivatives); + checkArgLength(fcargs, 4); + long elementsToUse = getUint(fcargs.get(1)); + + + long[] scalarValueIndices = + getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) + .toArray(); + + int[] orders = + getArrayValue(fcargs.get(2), Optional.of(elementsToUse), NumericValue.class).stream().mapToInt(NumericValue::intValue).toArray(); + + double[] values = + getArrayValue(fcargs.get(3), Optional.of(elementsToUse), RealValue.class).stream().mapToDouble(RealValue::getValue).toArray(); + + try { + Fmi2Status res = instance.setRealInputDerivatives(scalarValueIndices, orders, values); + return new IntegerValue(res.value); + } catch (FmuInvocationException e) { + throw new InterpreterException(e); + } + + })); + + + return new FmuComponentValue(componentMembers, component, fmuLogOutputStream); + } + + private static Value status2IntValue(Fmi3Status res) { + switch (res) { + + case OK: + return new IntegerValue(0); + case Warning: + return new IntegerValue(1); + case Discard: + return new IntegerValue(2); + case Error: + return new IntegerValue(3); + case Fatal: + return new IntegerValue(4); + } + return null; + } + + private static Map createGetSetMembers(IFmi3Instance instance) throws NoSuchMethodException { + Map componentMembers = new HashMap<>(); + + Map methodTypeMapping = new HashMap<>() {{ + put("getFloat32", TP.Float); + put("getFloat64", TP.Real); + put("getInt8", TP.Byte); + put("getUInt8", TP.Byte); + put("getInt16", TP.Short); + put("getUInt16", TP.Short); + put("getInt32", TP.Int); + put("getUInt32", TP.Int); + put("getInt64", TP.Long); + put("getUInt64", TP.Long); + put("getBoolean", TP.Bool); + put("getString", TP.String); + put("setFloat32", TP.Float); + put("setFloat64", TP.Real); + put("setInt8", TP.Byte); + put("setUInt8", TP.Byte); + put("setInt16", TP.Short); + put("setUInt16", TP.Short); + put("setInt32", TP.Int); + put("setUInt32", TP.Int); + put("setInt64", TP.Long); + put("setUInt64", TP.Long); + put("setBoolean", TP.Bool); + put("setString", TP.String); + + + }}; + + + for (Map.Entry method : methodTypeMapping.entrySet()) { + if (method.getKey().startsWith("get")) { + + Method m = instance.getClass().getMethod(method.getKey(), long[].class); + + componentMembers.put(method.getKey(), new FunctionValue.ExternalFunctionValue(fcargs -> { + + checkArgLength(fcargs, 3); + + if (!(fcargs.get(2) instanceof UpdatableValue)) { + throw new InterpreterException("value not a reference value"); + } + long elementsToUse = getUint(fcargs.get(1)); + + long[] scalarValueIndices = + getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) + .toArray(); + + + try { + @SuppressWarnings("rawtypes") + FmuResult res = (FmuResult) m.invoke(instance, scalarValueIndices);// instance.getFloat64(scalarValueIndices); + + if (res.status == Fmi3Status.OK) { + UpdatableValue ref = (UpdatableValue) fcargs.get(2); + + List values = null; + switch (method.getValue()) { + + case Bool: + values = Arrays.stream(ArrayUtils.toObject((boolean[]) res.result)).limit(elementsToUse).map(BooleanValue::new) + .collect(Collectors.toList()); + break; + case Byte: + values = Arrays.stream(ArrayUtils.toObject((byte[]) res.result)).limit(elementsToUse).map(ByteValue::new) + .collect(Collectors.toList()); + break; + case Float: + values = Arrays.stream(ArrayUtils.toObject((float[]) res.result)).limit(elementsToUse).map(FloatValue::new) + .collect(Collectors.toList()); + break; + case Int: + values = Arrays.stream(ArrayUtils.toObject((int[]) res.result)).limit(elementsToUse).map(IntegerValue::new) + .collect(Collectors.toList()); + break; + case Long: + values = Arrays.stream(ArrayUtils.toObject((long[]) res.result)).limit(elementsToUse).map(LongValue::new) + .collect(Collectors.toList()); + break; + case Real: + values = Arrays.stream(ArrayUtils.toObject((double[]) res.result)).limit(elementsToUse).map(RealValue::new) + .collect(Collectors.toList()); + break; + case Short: + values = Arrays.stream(ArrayUtils.toObject((short[]) res.result)).limit(elementsToUse).map(ShortValue::new) + .collect(Collectors.toList()); + break; + case String: + values = Arrays.stream((String[]) res.result).limit(elementsToUse).map(StringValue::new) + .collect(Collectors.toList()); + break; + } + + + ref.setValue(new ArrayValue<>(values)); + } + + return status2IntValue(res.status); + + } catch (IllegalAccessException | InvocationTargetException e) { + throw new InterpreterException(e); + } + + + })); + + } else { + + Class argClass = null; + + switch (method.getValue()) { + + case Bool: + argClass = boolean[].class; + break; + case Byte: + argClass = byte[].class; + break; + case Float: + argClass = float[].class; + break; + case Int: + argClass = int[].class; + break; + case Long: + argClass = long[].class; + break; + case Real: + argClass = double[].class; + break; + case Short: + argClass = short[].class; + break; + case String: + argClass = String[].class; + break; + } + + Method m = instance.getClass().getMethod(method.getKey(), argClass); + + componentMembers.put(method.getKey(), new FunctionValue.ExternalFunctionValue(fcargs -> { + checkArgLength(fcargs, 3); + long elementsToUse = getUint(fcargs.get(1)); + long[] scalarValueIndices = + getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) + .toArray(); + + //extract values + Object values = null; + + switch (method.getValue()) { + + case Bool: + values = ArrayUtils.toPrimitive( + getArrayValue(fcargs.get(2), Optional.of(elementsToUse), BooleanValue.class).stream().map(BooleanValue::getValue) + .collect(Collectors.toList()).toArray(new Boolean[]{})); + break; + case Byte: + values = ArrayUtils.toPrimitive( + getArrayValue(fcargs.get(2), Optional.of(elementsToUse), ByteValue.class).stream().map(ByteValue::getValue) + .collect(Collectors.toList()).toArray(new Byte[]{})); + break; + case Float: + values = ArrayUtils.toPrimitive( + getArrayValue(fcargs.get(2), Optional.of(elementsToUse), FloatValue.class).stream().map(FloatValue::getValue) + .collect(Collectors.toList()).toArray(new Float[]{})); + break; + case Int: + values = ArrayUtils.toPrimitive( + getArrayValue(fcargs.get(2), Optional.of(elementsToUse), IntegerValue.class).stream().map(IntegerValue::getValue) + .collect(Collectors.toList()).toArray(new Integer[]{})); + break; + case Long: + values = ArrayUtils.toPrimitive( + getArrayValue(fcargs.get(2), Optional.of(elementsToUse), LongValue.class).stream().map(LongValue::getValue) + .collect(Collectors.toList()).toArray(new Long[]{})); + break; + case Real: + values = getArrayValue(fcargs.get(2), Optional.of(elementsToUse), NumericValue.class).stream().limit(elementsToUse) + .mapToDouble(NumericValue::realValue).toArray(); + break; + case Short: + values = ArrayUtils.toPrimitive( + getArrayValue(fcargs.get(2), Optional.of(elementsToUse), ShortValue.class).stream().map(ShortValue::getValue) + .collect(Collectors.toList()).toArray(new Short[]{})); + break; + case String: + values = getArrayValue(fcargs.get(2), Optional.of(elementsToUse), StringValue.class).stream().map(StringValue::getValue) + .collect(Collectors.toList()).toArray(new String[]{}); + break; + } + + try { + Fmi2Status res = (Fmi2Status) m.invoke(instance, scalarValueIndices, values);// instance.setBoolean().setReals + // (scalarValueIndices, values); + return new IntegerValue(res.value); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new InterpreterException(e); + } + + })); + } + } + + /* +int getFloat32(uint valueReferences[], int nValueReferences, float values[], int nValues); +int getFloat64(uint valueReferences[], int nValueReferences, real values[], int nValues); +int getInt8(uint valueReferences[], int nValueReferences, byte values[], int nValues); +int getUInt8(uint valueReferences[], int nValueReferences, byte values[], int nValues); +int getInt16(uint valueReferences[], int nValueReferences, short values[], int nValues); +int getUInt16(uint valueReferences[], int nValueReferences, short values[], int nValues); +int getInt32(uint valueReferences[], int nValueReferences, int values[], int nValues); +int getUInt32(uint valueReferences[], int nValueReferences, int values[], int nValues); +int getInt64(uint valueReferences[], int nValueReferences, long values[], int nValues); +int getUInt64(uint valueReferences[], int nValueReferences, long values[], int nValues); +int getBoolean(uint valueReferences[], int nValueReferences, bool values[], int nValues); +int getString(uint valueReferences[], int nValueReferences, string values[], int nValues); +int setFloat32(uint valueReferences[], int nValueReferences, float values[], int nValues); +int setFloat64(uint valueReferences[], int nValueReferences, real values[], int nValues); +int setInt8(uint valueReferences[], int nValueReferences, byte values[], int nValues); +int setUInt8(uint valueReferences[], int nValueReferences, byte values[], int nValues); +int setInt16(uint valueReferences[], int nValueReferences, short values[], int nValues); +int setUInt16(uint valueReferences[], int nValueReferences, short values[], int nValues); +int setInt32(uint valueReferences[], int nValueReferences, int values[], int nValues); +int setUInt32(uint valueReferences[], int nValueReferences, int values[], int nValues); +int setInt64(uint valueReferences[], int nValueReferences, long values[], int nValues); +int setUInt64(uint valueReferences[], int nValueReferences, long values[], int nValues); +int setBoolean(uint valueReferences[], int nValueReferences, bool values[], int nValues); +int setString(uint valueReferences[], int nValueReferences, string values[], int nValues); + */ + + + return componentMembers; + + } + + public Value createFmiValue(String path, String guid) { + try { + long startExecTime = System.nanoTime(); + + URI uri = URI.create(path); + if (!uri.isAbsolute()) { + uri = new File(".").toURI().resolve(uri); + } + File file = new File(uri); + + final IFmi3Fmu fmu = new Fmu3(file); + + fmu.load(); + + Map functions = createFmuMembers(workingDirectory, guid, fmu); + + long stopTime = System.nanoTime(); + + System.out.println("Interpretation load took: " + (stopTime - startExecTime)); + return new Fmu3Value(functions, fmu); + + } catch (IOException | FmuInvocationException | FmuMissingLibraryException e) { + + e.printStackTrace(); + return new NullValue(); + } catch (Exception e) { + e.printStackTrace(); + return new NullValue(); + } + } + + private enum TP { + Bool, + Byte, + Float, + Int, + Long, + Real, + Short, + String, + } +} diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/ByteValue.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/ByteValue.java new file mode 100644 index 000000000..1736b9bbe --- /dev/null +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/ByteValue.java @@ -0,0 +1,48 @@ +package org.intocps.maestro.interpreter.values; + +public class ByteValue extends NumericValue { + final byte value; + + public ByteValue(byte value) { + this.value = value; + } + + public byte getValue() { + return value; + } + + @Override + public String toString() { + return "ByteValue{" + "value=" + value + '}'; + } + + @Override + public long longValue() { + return value; + } + + @Override + public int intValue() { + return value; + } + + @Override + public double realValue() { + return value; + } + + @Override + public int compareTo(Value other) { + other = other.deref(); + + if (other instanceof ByteValue) { + ByteValue io = (ByteValue) other; + return Byte.compare(value, io.value); + } else if (other instanceof IntegerValue) { + IntegerValue io = (IntegerValue) other; + return (value < io.value ? -1 : (value == io.value ? 0 : 1)); + } + + return super.compareTo(other); + } +} \ No newline at end of file diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/FloatValue.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/FloatValue.java new file mode 100644 index 000000000..1c6ff27d1 --- /dev/null +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/FloatValue.java @@ -0,0 +1,68 @@ +package org.intocps.maestro.interpreter.values; + +import org.intocps.maestro.interpreter.InterpreterException; + +public class FloatValue extends NumericValue { + final float value; + + public FloatValue(float value) { + this.value = value; + } + + public float getValue() { + return value; + } + + @Override + public String toString() { + return "FloatValue{" + "value=" + value + '}'; + } + + @Override + public long longValue() { + long rounded = Math.round(value); + + if (rounded != value) { + throw new InterpreterException("Value " + value + " is not an integer"); + } + + return rounded; + } + + @Override + public int intValue() { + long rounded = Math.round(value); + + if (rounded != value) { + throw new InterpreterException("Value " + value + " is not an integer"); + } + + if (rounded <= Integer.MAX_VALUE && rounded >= Integer.MIN_VALUE) { + return (int) rounded; // No loss of precision + } else { + throw new InterpreterException("Cannot convert " + rounded + " to int"); + } + } + + @Override + public double realValue() { + return value; + } + + @Override + public int compareTo(Value value) { + + Value other = value.deref(); + + if (other instanceof FloatValue) { + FloatValue ro = (FloatValue) other; + return (int) Math.round(Math.signum(this.value - ro.getValue())); + + } else if (other instanceof IntegerValue) { + IntegerValue ro = (IntegerValue) other; + return (int) Math.round(Math.signum(this.value - ro.getValue())); + } + + return super.compareTo(value); + } +} diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/LongValue.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/LongValue.java new file mode 100644 index 000000000..3b12babb7 --- /dev/null +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/LongValue.java @@ -0,0 +1,45 @@ +package org.intocps.maestro.interpreter.values; + +public class LongValue extends NumericValue { + final long value; + + public LongValue(long value) { + this.value = value; + } + + public long getValue() { + return value; + } + + @Override + public String toString() { + return "LongValue{" + "value=" + value + '}'; + } + + @Override + public long longValue() { + return value; + } + + @Override + public int intValue() { + return Long.valueOf(value).intValue(); + } + + @Override + public double realValue() { + return value; + } + + @Override + public int compareTo(Value other) { + other = other.deref(); + + if (other instanceof LongValue) { + LongValue io = (LongValue) other; + return (value < io.value ? -1 : (value == io.value ? 0 : 1)); + } + + return super.compareTo(other); + } +} diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/ShortValue.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/ShortValue.java new file mode 100644 index 000000000..0bf61a1d4 --- /dev/null +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/ShortValue.java @@ -0,0 +1,48 @@ +package org.intocps.maestro.interpreter.values; + +public class ShortValue extends NumericValue { + final short value; + + public ShortValue(short value) { + this.value = value; + } + + public short getValue() { + return value; + } + + @Override + public String toString() { + return "ShortValue{" + "value=" + value + '}'; + } + + @Override + public long longValue() { + return value; + } + + @Override + public int intValue() { + return value; + } + + @Override + public double realValue() { + return value; + } + + @Override + public int compareTo(Value other) { + other = other.deref(); + + if (other instanceof ShortValue) { + ShortValue io = (ShortValue) other; + return Short.compare(value, io.value); + } else if (other instanceof IntegerValue) { + IntegerValue io = (IntegerValue) other; + return (value < io.value ? -1 : (value == io.value ? 0 : 1)); + } + + return super.compareTo(other); + } +} \ No newline at end of file diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/fmi/Fmu3Value.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/fmi/Fmu3Value.java new file mode 100644 index 000000000..fc94ef4d1 --- /dev/null +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/fmi/Fmu3Value.java @@ -0,0 +1,13 @@ +package org.intocps.maestro.interpreter.values.fmi; + +import org.intocps.fmi.jnifmuapi.fmi3.IFmi3Fmu; +import org.intocps.maestro.interpreter.values.ExternalModuleValue; +import org.intocps.maestro.interpreter.values.Value; + +import java.util.Map; + +public class Fmu3Value extends ExternalModuleValue { + public Fmu3Value(Map members, IFmi3Fmu module) { + super(members, module); + } +} \ No newline at end of file diff --git a/maestro/src/test/java/org/intocps/maestro/Fmi3ModuleTest.java b/maestro/src/test/java/org/intocps/maestro/Fmi3ModuleTest.java new file mode 100644 index 000000000..2542b8b56 --- /dev/null +++ b/maestro/src/test/java/org/intocps/maestro/Fmi3ModuleTest.java @@ -0,0 +1,16 @@ +package org.intocps.maestro; + +import org.junit.jupiter.params.provider.Arguments; + +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.Objects; +import java.util.stream.Stream; + +public class Fmi3ModuleTest extends FullSpecTest { + + private static Stream data() { + return Arrays.stream(Objects.requireNonNull(Paths.get("src", "test", "resources", "fmi3").toFile().listFiles())) + .filter(n -> !n.getName().startsWith(".")).map(f -> Arguments.arguments(f.getName(), f)); + } +} diff --git a/parser/src/main/antlr4/org/intocps/maestro/parser/MablLexer.g4 b/parser/src/main/antlr4/org/intocps/maestro/parser/MablLexer.g4 index c33e1844a..288f569a1 100644 --- a/parser/src/main/antlr4/org/intocps/maestro/parser/MablLexer.g4 +++ b/parser/src/main/antlr4/org/intocps/maestro/parser/MablLexer.g4 @@ -11,6 +11,10 @@ REAL: 'real'; UINT: 'uint'; BOOL: 'bool'; INT: 'int'; +FLOAT: 'float'; +BYTE: 'byte'; +LONG: 'long'; +SHORT: 'short'; VOID: 'void'; STRING: 'string'; WHILE: 'while'; diff --git a/parser/src/main/antlr4/org/intocps/maestro/parser/MablParser.g4 b/parser/src/main/antlr4/org/intocps/maestro/parser/MablParser.g4 index ddf52b7fb..b9918e017 100644 --- a/parser/src/main/antlr4/org/intocps/maestro/parser/MablParser.g4 +++ b/parser/src/main/antlr4/org/intocps/maestro/parser/MablParser.g4 @@ -159,6 +159,10 @@ primitiveType | BOOL #boolType | QUESTION #unknownType | VOID #voidType + | LONG #longType + | BYTE #byteType + | FLOAT #floatType + | SHORT #shortType ; literal diff --git a/parser/src/main/java/org/intocps/maestro/parser/ParseTree2AstConverter.java b/parser/src/main/java/org/intocps/maestro/parser/ParseTree2AstConverter.java index a854d18a2..0ac4cdfe7 100644 --- a/parser/src/main/java/org/intocps/maestro/parser/ParseTree2AstConverter.java +++ b/parser/src/main/java/org/intocps/maestro/parser/ParseTree2AstConverter.java @@ -544,6 +544,26 @@ public INode visitBoolType(MablParser.BoolTypeContext ctx) { return new ABooleanPrimitiveType(); } + @Override + public INode visitByteType(MablParser.ByteTypeContext ctx) { + return new AByteNumericPrimitiveType(); + } + + @Override + public INode visitShortType(MablParser.ShortTypeContext ctx) { + return new AShortNumericPrimitiveType(); + } + + @Override + public INode visitFloatType(MablParser.FloatTypeContext ctx) { + return new AFloatNumericPrimitiveType(); + } + + @Override + public INode visitLongType(MablParser.LongTypeContext ctx) { + return new ALongNumericPrimitiveType(); + } + @Override public INode visitRealType(MablParser.RealTypeContext ctx) { return new ARealNumericPrimitiveType(); diff --git a/pom.xml b/pom.xml index 35402200c..ad58bbf8c 100644 --- a/pom.xml +++ b/pom.xml @@ -24,7 +24,7 @@ 11 11 2.17.1 - 1.3.5 + 1.3.6-SNAPSHOT 1.0.10 1.5.0 2.13.5 diff --git a/typechecker/src/main/java/org/intocps/maestro/typechecker/TypeChecker.java b/typechecker/src/main/java/org/intocps/maestro/typechecker/TypeChecker.java index f5ca78fc6..a5ee6c0f3 100644 --- a/typechecker/src/main/java/org/intocps/maestro/typechecker/TypeChecker.java +++ b/typechecker/src/main/java/org/intocps/maestro/typechecker/TypeChecker.java @@ -24,7 +24,7 @@ public TypeChecker(IErrorReporter errorReporter) { } public static List getRuntimeModules() { - return Arrays.asList("CSV", "DataWriter", "FMI2", "Logger", "Math", "ArrayUtil", "BooleanLogic", "MEnv", "VariableStep", "RealTime", + return Arrays.asList("CSV", "DataWriter", "FMI2", "FMI3", "Logger", "Math", "ArrayUtil", "BooleanLogic", "MEnv", "VariableStep", "RealTime", "DerivativeEstimator", "ConsolePrinter", "SimulationControl"); } diff --git a/typechecker/src/main/resources/org/intocps/maestro/typechecker/FMI3.mabl b/typechecker/src/main/resources/org/intocps/maestro/typechecker/FMI3.mabl new file mode 100644 index 000000000..ddeb5ba35 --- /dev/null +++ b/typechecker/src/main/resources/org/intocps/maestro/typechecker/FMI3.mabl @@ -0,0 +1,300 @@ +module FMI3 import FMI2Component; +import FMI3Instance; +import FMI2; +{ + FMI3Instance instantiateCoSimulation(string instanceName, string instantiationToken, string resourceLocation, bool visible, bool loggingOn, + bool eventModeUsed, bool earlyReturnAllowed, uint[] requiredIntermediateVariables); //, ILogMessageCallback logMessage,IIntermediateUpdateCallback intermediateUpdate + + FMI2Component instantiateCoSimulationWrapAsFmi2(string instanceName, string instantiationToken, string resourceLocation, bool visible, bool loggingOn, + bool eventModeUsed, bool earlyReturnAllowed, uint[] requiredIntermediateVariables);//, ILogMessageCallback logMessage,IIntermediateUpdateCallback intermediateUpdate + + void freeInstance(FMI2Component comp); + void freeInstance(FMI3Instance comp); + +} + + + + + +module FMUS3tate{} +module FMI3Instance import FMUS3tate;{ + + + /** + * size_t nCategories is ignored as it is calculated from categories[]. + * + * @param instance + * @param loggingOn + * @param categories + * @return + */ + int setDebugLogging(bool loggingOn, string categories[]); + + /* tag::FreeInstance[] */ + void freeInstance(); + /* end::FreeInstance[] */ + + /* Enter and exit initialization mode, enter event mode, terminate and reset */ + /* tag::EnterInitializationMode[] */ + int enterInitializationMode(bool toleranceDefined, real tolerance, real startTime, bool stopTimeDefined, + real stopTime); + /* end::EnterInitializationMode[] */ + + /* tag::ExitInitializationMode[] */ + int exitInitializationMode(); + /* end::ExitInitializationMode[] */ + + /* tag::EnterEventMode[] */ + int enterEventMode(); + /* end::EnterEventMode[] */ + + /* tag::Terminate[] */ + int terminate(); + /* end::Terminate[] */ + + /* tag::Reset[] */ + int reset(); + /* end::Reset[] */ + + /* getting and setting variable values */ + /* tag::getters[] */ + int getFloat32(uint valueReferences[], int nValueReferences, float values[], int nValues); + + int getFloat64(uint valueReferences[], int nValueReferences, real values[], int nValues); + + int getInt8(uint valueReferences[], int nValueReferences, byte values[], int nValues); + + int getUInt8(uint valueReferences[], int nValueReferences, byte values[], int nValues); + + int getInt16(uint valueReferences[], int nValueReferences, short values[], int nValues); + + int getUInt16(uint valueReferences[], int nValueReferences, short values[], int nValues); + + int getInt32(uint valueReferences[], int nValueReferences, int values[], int nValues); + + int getUInt32(uint valueReferences[], int nValueReferences, int values[], int nValues); + + int getInt64(uint valueReferences[], int nValueReferences, long values[], int nValues); + + int getUInt64(uint valueReferences[], int nValueReferences, long values[], int nValues); + + int getBoolean(uint valueReferences[], int nValueReferences, bool values[], int nValues); + + int getString(uint valueReferences[], int nValueReferences, string values[], int nValues); + + int getBinary(uint valueReferences[], int nValueReferences, byte values[][], int nValues); + /* end::getters[] */ + + /* tag::setters[] */ + int setFloat32(uint valueReferences[], int nValueReferences, float values[], int nValues); + + int setFloat64(uint valueReferences[], int nValueReferences, real values[], int nValues); + + int setInt8(uint valueReferences[], int nValueReferences, byte values[], int nValues); + + int setUInt8(uint valueReferences[], int nValueReferences, byte values[], int nValues); + + int setInt16(uint valueReferences[], int nValueReferences, short values[], int nValues); + + int setUInt16(uint valueReferences[], int nValueReferences, short values[], int nValues); + + int setInt32(uint valueReferences[], int nValueReferences, int values[], int nValues); + + int setUInt32(uint valueReferences[], int nValueReferences, int values[], int nValues); + + int setInt64(uint valueReferences[], int nValueReferences, long values[], int nValues); + + int setUInt64(uint valueReferences[], int nValueReferences, long values[], int nValues); + + int setBoolean(uint valueReferences[], int nValueReferences, bool values[], int nValues); + + int setString(uint valueReferences[], int nValueReferences, string values[], int nValues); + + int setBinary(uint valueReferences[], int nValueReferences, long sizes[], byte array_name[][], int nValues); + /* end::setters[] */ + + /* getting Variable Dependency Information */ + /* tag::getNumberOfVariableDependencies[] */ + int getNumberOfVariableDependencies(uint valueReference, out int nDependencies); + /* end::getNumberOfVariableDependencies[] */ + + /* tag::getVariableDependencies[] */ + int getVariableDependencies(uint dependent, int elementIndicesOfDependent[], uint independents[], + uint elementIndicesOfIndependents[], int dependencyKinds[], int nDependencies); + /* end::getVariableDependencies[] */ + + /* getting and setting the internal FMU state */ + /* tag::getFMUState[] */ + int getFMUState(out FMUS3tate FMUState); + /* end::getFMUState[] */ + + /* tag::setFMUState[] */ + int setFMUState(FMUS3tate FMUState); + /* end::setFMUState[] */ + + /* tag::FreeFMUState[] */ + int freeFMUState(out FMUS3tate FMUState); + /* end::FreeFMUState[] */ + + /* tag::SerializedFMUStateSize[] */ + //int serializedFMUStateSize(long FMUState, int[] size); + /* end::SerializedFMUStateSize[] */ + + /* tag::SerializeFMUState[] */ + //int serializeFMUState(long FMUState, byte serializedState[], int size); + /* end::SerializeFMUState[] */ + + /* tag::DeserializeFMUState[] */ + //int deserializeFMUState(byte serializedState[], int size, long[] FMUState); + /* end::DeserializeFMUState[] */ + + /* getting partial derivatives */ + /* tag::getDirectionalDerivative[] */ + int getDirectionalDerivative(uint unknowns[], int nUnknowns, uint knowns[], int nKnowns, real seed[], int nSeed, + real sensitivity[], int nSensitivity); + /* end::getDirectionalDerivative[] */ + + /* tag::getAdjointDerivative[] */ + int getAdjointDerivative(uint unknowns[], int nUnknowns, uint knowns[], int nKnowns, real seed[], int nSeed, + real sensitivity[], int nSensitivity); + /* end::getAdjointDerivative[] */ + + + /* Entering and exiting the Configuration or Reconfiguration Mode */ + /* tag::EnterConfigurationMode[] */ + int enterConfigurationMode(); + /* end::EnterConfigurationMode[] */ + + /* tag::ExitConfigurationMode[] */ + int exitConfigurationMode(); + /* end::ExitConfigurationMode[] */ + + /* Clock related functions */ + /* tag::getClock[] */ + int getClock(uint valueReferences[], int nValueReferences, bool values[]); + /* end::getClock[] */ + + /* tag::setClock[] */ + int setClock(uint valueReferences[], int nValueReferences, bool values[]); + /* end::setClock[] */ + + /* tag::getIntervalDecimal[] */ + int getIntervalDecimal(uint valueReferences[], int nValueReferences, real intervals[], + int qualifiers[]); + /* end::getIntervalDecimal[] */ + + /* tag::getIntervalFraction[] */ + int getIntervalFraction(uint valueReferences[], int nValueReferences, uint intervalCounters[], uint resolutions[], + int qualifiers[]); + /* end::getIntervalFraction[] */ + + /* tag::getShiftDecimal[] */ + int getShiftDecimal(uint valueReferences[], int nValueReferences, real shifts[]); + /* end::getShiftDecimal[] */ + + /* tag::getShiftFraction[] */ + int getShiftFraction(uint valueReferences[], int nValueReferences, uint shiftCounters[], uint resolutions[]); + /* end::getShiftFraction[] */ + + /* tag::setIntervalDecimal[] */ + int setIntervalDecimal(uint valueReferences[], int nValueReferences, real interval[]); + /* end::setIntervalDecimal[] */ + + /* tag::setIntervalFraction[] */ + int setIntervalFraction(uint valueReferences[], int nValueReferences, uint intervalCounter[], uint resolution[]); + /* end::setIntervalFraction[] */ + + /* tag::setShiftDecimal[] */ + int setShiftDecimal(uint valueReferences[], int nValueReferences, real shifts[]); + /* end::setShiftDecimal[] */ + + /* tag::setShiftFraction[] */ + int setShiftFraction(uint valueReferences[], int nValueReferences, uint counters[], uint resolutions[]); + /* end::setShiftFraction[] */ + + + /* tag::EvaluateDiscreteStates[] */ + int evaluateDiscreteStates(); + /* end::EvaluateDiscreteStates[] */ + + /* tag::UpdateDiscreteStates[] */ + int updateDiscreteStates(bool[] discreteStatesNeedUpdate, bool[] terminateSimulation, + bool[] nominalsOfContinuousStatesChanged, bool[] valuesOfContinuousStatesChanged, bool[] nextEventTimeDefined, + real[] nextEventTime); + /* end::UpdateDiscreteStates[] */ + + /*************************************************** + Types for Functions for Model Exchange + ****************************************************/ + + /* tag::EnterContinuousTimeMode[] */ + int enterContinuousTimeMode(); + /* end::EnterContinuousTimeMode[] */ + + /* tag::CompletedIntegratorStep[] */ + int completedIntegratorStep(bool nosetFMUStatePriorToCurrentPoint, bool[] enterEventMode, + bool[] terminateSimulation); + /* end::CompletedIntegratorStep[] */ + + /* Providing independent variables and re-initialization of caching */ + /* tag::setTime[] */ + int setTime(real time); + /* end::setTime[] */ + + /* tag::setContinuousStates[] */ + int setContinuousStates(real continuousStates[], int nContinuousStates); + /* end::setContinuousStates[] */ + + /* Evaluation of the model equations */ + /* tag::getDerivatives[] */ + int getContinuousStateDerivatives(real derivatives[], int nContinuousStates); + /* end::getDerivatives[] */ + + /* tag::getEventIndicators[] */ + int getEventIndicators(real eventIndicators[], int nEventIndicators); + /* end::getEventIndicators[] */ + + /* tag::getContinuousStates[] */ + int getContinuousStates(real continuousStates[], int nContinuousStates); + /* end::getContinuousStates[] */ + + /* tag::getNominalsOfContinuousStates[] */ + int getNominalsOfContinuousStates(real nominals[], int nContinuousStates); + /* end::getNominalsOfContinuousStates[] */ + + /* tag::getNumberOfEventIndicators[] */ + int getNumberOfEventIndicators(int[] nEventIndicators); + /* end::getNumberOfEventIndicators[] */ + + /* tag::getNumberOfContinuousStates[] */ + int getNumberOfContinuousStates(int[] nContinuousStates); + /* end::getNumberOfContinuousStates[] */ + + /*************************************************** + Types for Functions for Co-Simulation + ****************************************************/ + + /* Simulating the FMU */ + + /* tag::EnterStepMode[] */ + int enterStepMode(); + /* end::EnterStepMode[] */ + + /* tag::getOutputDerivatives[] */ + int getOutputDerivatives(uint valueReferences[], int nValueReferences, int orders[], real values[], int nValues); + /* end::getOutputDerivatives[] */ + + /* tag::DoStep[] */ + int doStep(real currentCommunicationPoint, real communicationStepSize, bool nosetFMUStatePriorToCurrentPoint, + bool[] eventHandlingNeeded, bool[] terminateSimulation, bool[] earlyReturn, real[] lastSuccessfulTime); + /* end::DoStep[] */ + + /*************************************************** + Types for Functions for Scheduled Execution + ****************************************************/ + /* tag::ActivateModelPartition[] */ + int activateModelPartition(uint clockReference, real activationTime); + +} + diff --git a/typechecker/src/test/java/org/intocps/maestro/typechecker/ModuleTest.java b/typechecker/src/test/java/org/intocps/maestro/typechecker/ModuleTest.java new file mode 100644 index 000000000..343643c8c --- /dev/null +++ b/typechecker/src/test/java/org/intocps/maestro/typechecker/ModuleTest.java @@ -0,0 +1,67 @@ +package org.intocps.maestro.typechecker; + +import org.antlr.v4.runtime.CharStreams; +import org.intocps.maestro.ast.NodeCollector; +import org.intocps.maestro.ast.analysis.AnalysisException; +import org.intocps.maestro.ast.node.AImportedModuleCompilationUnit; +import org.intocps.maestro.ast.node.ARootDocument; +import org.intocps.maestro.core.messages.ErrorReporter; +import org.intocps.maestro.core.messages.IErrorReporter; +import org.intocps.maestro.parser.MablParserUtil; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.Vector; +import java.util.stream.Collectors; + +public class ModuleTest { + public static List getModuleDocuments(List modules) throws IOException { + List allModules = TypeChecker.getRuntimeModules(); + List documents = new ArrayList<>(); + if (modules != null) { + for (String module : modules) { + if (allModules.contains(module)) { + documents.add(getRuntimeModule(module)); + } + } + } + return documents; + } + + public static ARootDocument getRuntimeModule(String module) throws IOException { + InputStream resourceAsStream = TypeChecker.getRuntimeModule(module); + if (resourceAsStream == null) { + return null; + } + return MablParserUtil.parse(CharStreams.fromStream(resourceAsStream)); + } + + @Test + public void testAll() throws IOException, AnalysisException { + IErrorReporter reporter = new ErrorReporter(); + TypeChecker typeChecker = new TypeChecker(reporter); + List maestro2EmbeddedModules = + getModuleDocuments(TypeChecker.getRuntimeModules()).stream().map(x -> NodeCollector.collect(x, AImportedModuleCompilationUnit.class)) + .filter(Optional::isPresent).flatMap(x -> x.get().stream()).collect(Collectors.toList()); + ARootDocument defaultModules = new ARootDocument(); + defaultModules.setContent(maestro2EmbeddedModules); + PrintWriter writer = new PrintWriter(System.err); + + ARootDocument doc = MablParserUtil.parse(CharStreams.fromStream(new ByteArrayInputStream("simulation{}".getBytes()))); + boolean res = typeChecker.typeCheck(List.of(doc, defaultModules), new Vector<>()); + + if (!res) { + reporter.printWarnings(writer); + reporter.printErrors(writer); + } + writer.flush(); + Assertions.assertTrue(res); + } +} From ce9ef572d1f0db7b13d05f4d1c0538c290e72084 Mon Sep 17 00:00:00 2001 From: Kenneth Lausdahl Date: Tue, 23 May 2023 16:28:46 +0200 Subject: [PATCH 02/54] initial implementation of a new type system and fmi3 --- .../framework/fmi2/api/mabl/BaseApiTest.java | 3 +- .../framework/fmi2/api/mabl/ArrayTest.java | 8 +- .../DefaultExternalValueFactory.java | 452 +----- .../maestro/interpreter/Fmi2Interpreter.java | 49 +- .../maestro/interpreter/Fmi3Interpreter.java | 1345 ++++++++++++----- .../interpreter/Fmi3InterpreterAuto.java | 1079 +++++++++++++ .../maestro/interpreter/Interpreter.java | 113 +- .../extensions/ArrayUtilLifecycleHandler.java | 16 + .../extensions/BaseLifecycleHandler.java | 18 + .../BooleanLogicLifecycleHandler.java | 16 + .../ConsolePrinterLifecycleHandler.java | 16 + .../extensions/CsvLifecycleHandler.java | 16 + .../DataWriterLifecycleHandler.java | 69 + .../DerivativeEstimatorLifecycleHandler.java | 16 + .../extensions/Fmi2LifecycleHandler.java | 46 + .../extensions/Fmi3LifecycleHandler.java | 51 + .../extensions/JFmi2LifecycleHandler.java | 44 + .../JavaClasspathLoaderLifecycleHandler.java | 55 + .../extensions/LoggerLifecycleHandler.java | 16 + .../extensions/MEnvLifecycleHandler.java | 116 ++ .../extensions/MathLifecycleHandler.java | 16 + .../ModelTransitionLifecycleHandler.java | 19 + .../extensions/RealTimeLifecycleHandler.java | 16 + ...ulationControlDefaultLifecycleHandler.java | 16 + .../VariableStepLifecycleHandler.java | 28 + .../external/ExternalReflectCallHelper.java | 531 +++++++ .../external/ExternalReflectModuleHelper.java | 99 ++ .../interpreter/external/IArgMapping.java | 23 + .../maestro/interpreter/external/TP.java | 13 + .../interpreter/values/ArrayValue.java | 6 + .../interpreter/values/BooleanValue.java | 2 +- .../maestro/interpreter/values/ByteValue.java | 20 +- .../values/ConsolePrinterValue.java | 34 +- .../interpreter/values/EnumerationValue.java | 7 + .../interpreter/values/FloatValue.java | 18 +- .../interpreter/values/IntegerValue.java | 18 +- .../interpreter/values/LoggerValue.java | 44 +- .../maestro/interpreter/values/LongValue.java | 12 +- .../maestro/interpreter/values/MathValue.java | 9 +- .../interpreter/values/NumericValue.java | 86 ++ .../interpreter/values/RealTimeValue.java | 14 +- .../maestro/interpreter/values/RealValue.java | 24 +- .../interpreter/values/ShortValue.java | 12 +- .../interpreter/values/StringValue.java | 6 + .../interpreter/values/UndefinedValue.java | 7 + .../values/UnsignedIntegerValue.java | 12 +- .../interpreter/values/UpdatableValue.java | 11 + .../maestro/interpreter/values/Value.java | 20 + .../interpreter/values/csv/CsvDataWriter.java | 13 +- .../values/datawriter/DataWriterValue.java | 2 +- .../values/fmi/Fmu3InstanceValue.java | 21 + .../values/fmi/Fmu3StateValue.java | 14 + .../values/utilities/ArrayUtilValue.java | 12 +- .../variablestep/VariableStepConfigValue.java | 56 +- .../variablestep/VariableStepValue.java | 14 +- .../ExternalReflectCallHelperAutoTest.java | 223 +++ .../ExternalReflectCallHelperTest.java | 200 +++ .../interpreter/interpreter_automapper.mabl | 12 + .../webapi/maestro2/Maestro2Broker.java | 57 +- .../interpreter/WebApiInterpreterFactory.java | 12 +- .../maestro/MablRuntimeDataGenerator.java | 4 +- .../org/intocps/maestro/cli/ImportCmd.java | 4 + .../org/intocps/maestro/cli/MablCliUtil.java | 3 +- .../maestro/BuilderGetSetDerivativesTest.java | 60 +- .../java/org/intocps/maestro/BuilderTest.java | 13 +- .../maestro/ConsolePrinterInterfaceTest.java | 4 +- .../maestro/DefaultLoaderFactoryTest.java | 38 +- ...cumentationGettingStartedExamplesTest.java | 5 +- .../org/intocps/maestro/FullSpecCppTest.java | 12 +- .../org/intocps/maestro/FullSpecTest.java | 67 +- .../maestro/MaBLTemplateGeneratorTest.java | 17 +- .../TemplateGeneratorFromScenarioTest.java | 46 +- .../org/intocps/maestro/TransitionTest.java | 8 +- .../org/intocps/maestro/VariableStepTest.java | 20 +- .../org/intocps/maestro/WatertankApiTest.java | 13 +- pom.xml | 2 +- .../maestro/typechecker/TypeCheckVisitor.java | 125 +- .../maestro/typechecker/TypeChecker.java | 12 + .../maestro/typechecker/TypeComparator.java | 43 + .../org/intocps/maestro/typechecker/FMI3.mabl | 70 +- 80 files changed, 4601 insertions(+), 1268 deletions(-) create mode 100644 interpreter/src/main/java/org/intocps/maestro/interpreter/Fmi3InterpreterAuto.java create mode 100644 interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/ArrayUtilLifecycleHandler.java create mode 100644 interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/BaseLifecycleHandler.java create mode 100644 interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/BooleanLogicLifecycleHandler.java create mode 100644 interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/ConsolePrinterLifecycleHandler.java create mode 100644 interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/CsvLifecycleHandler.java create mode 100644 interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/DataWriterLifecycleHandler.java create mode 100644 interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/DerivativeEstimatorLifecycleHandler.java create mode 100644 interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/Fmi2LifecycleHandler.java create mode 100644 interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/Fmi3LifecycleHandler.java create mode 100644 interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/JFmi2LifecycleHandler.java create mode 100644 interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/JavaClasspathLoaderLifecycleHandler.java create mode 100644 interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/LoggerLifecycleHandler.java create mode 100644 interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/MEnvLifecycleHandler.java create mode 100644 interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/MathLifecycleHandler.java create mode 100644 interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/ModelTransitionLifecycleHandler.java create mode 100644 interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/RealTimeLifecycleHandler.java create mode 100644 interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/SimulationControlDefaultLifecycleHandler.java create mode 100644 interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/VariableStepLifecycleHandler.java create mode 100644 interpreter/src/main/java/org/intocps/maestro/interpreter/external/ExternalReflectCallHelper.java create mode 100644 interpreter/src/main/java/org/intocps/maestro/interpreter/external/ExternalReflectModuleHelper.java create mode 100644 interpreter/src/main/java/org/intocps/maestro/interpreter/external/IArgMapping.java create mode 100644 interpreter/src/main/java/org/intocps/maestro/interpreter/external/TP.java create mode 100644 interpreter/src/main/java/org/intocps/maestro/interpreter/values/fmi/Fmu3InstanceValue.java create mode 100644 interpreter/src/main/java/org/intocps/maestro/interpreter/values/fmi/Fmu3StateValue.java create mode 100644 interpreter/src/test/java/org/intocps/maestro/interpreter/ExternalReflectCallHelperAutoTest.java create mode 100644 interpreter/src/test/java/org/intocps/maestro/interpreter/ExternalReflectCallHelperTest.java create mode 100644 interpreter/src/test/resources/org/intocps/maestro/interpreter/interpreter_automapper.mabl diff --git a/frameworks/fmi2api-test/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/BaseApiTest.java b/frameworks/fmi2api-test/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/BaseApiTest.java index 2411de0eb..1d42c904b 100644 --- a/frameworks/fmi2api-test/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/BaseApiTest.java +++ b/frameworks/fmi2api-test/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/BaseApiTest.java @@ -100,7 +100,8 @@ public void check(String spec, assertTrue(res, "Type check errors:" + out); new MableInterpreter( - new DefaultExternalValueFactory(new File("target"), new ByteArrayInputStream(runtimedata.getBytes(StandardCharsets.UTF_8)))).execute( + new DefaultExternalValueFactory(new File("target"),typeChecker::findModule, + new ByteArrayInputStream(runtimedata.getBytes(StandardCharsets.UTF_8)))).execute( doc); } diff --git a/frameworks/fmi2api/src/test/java/org/intocps/maestro/framework/fmi2/api/mabl/ArrayTest.java b/frameworks/fmi2api/src/test/java/org/intocps/maestro/framework/fmi2/api/mabl/ArrayTest.java index 6b46d32b0..cec049f31 100644 --- a/frameworks/fmi2api/src/test/java/org/intocps/maestro/framework/fmi2/api/mabl/ArrayTest.java +++ b/frameworks/fmi2api/src/test/java/org/intocps/maestro/framework/fmi2/api/mabl/ArrayTest.java @@ -41,9 +41,9 @@ public void mdArrayFaultyAssignmentTest() throws Exception { DynamicActiveBuilderScope dynamicScope = builder.getDynamicScope(); IErrorReporter reporter = new ErrorReporter(); TypeChecker typeChecker = new TypeChecker(reporter); - List maestro2EmbeddedModules = - getModuleDocuments(TypeChecker.getRuntimeModules()).stream().map(x -> NodeCollector.collect(x, AImportedModuleCompilationUnit.class)) - .filter(Optional::isPresent).flatMap(x -> x.get().stream()).collect(Collectors.toList()); + List maestro2EmbeddedModules = getModuleDocuments(TypeChecker.getRuntimeModules()).stream() + .map(x -> NodeCollector.collect(x, AImportedModuleCompilationUnit.class)).filter(Optional::isPresent).flatMap(x -> x.get().stream()) + .collect(Collectors.toList()); ARootDocument defaultModules = new ARootDocument(); defaultModules.setContent(maestro2EmbeddedModules); StringWriter out = new StringWriter(); @@ -72,7 +72,7 @@ public void mdArrayFaultyAssignmentTest() throws Exception { Assertions.assertFalse(res, "Expected error: Invalid assignment to cannot assign: 'real' to 'real[]' in: multidimensionalarray[0] = " + "realvar; null"); Assertions.assertThrows(RuntimeException.class, - () -> new MableInterpreter(new DefaultExternalValueFactory(new File("target"), null)).execute(doc)); + () -> new MableInterpreter(new DefaultExternalValueFactory(new File("target"), typeChecker::findModule, null)).execute(doc)); } } diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/DefaultExternalValueFactory.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/DefaultExternalValueFactory.java index 4bb0e5ddc..85eaa76e9 100644 --- a/interpreter/src/main/java/org/intocps/maestro/interpreter/DefaultExternalValueFactory.java +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/DefaultExternalValueFactory.java @@ -1,55 +1,43 @@ package org.intocps.maestro.interpreter; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import com.spencerwi.either.Either; -import org.intocps.maestro.ast.analysis.AnalysisException; +import org.intocps.maestro.ast.AModuleDeclaration; +import org.intocps.maestro.ast.node.AImportedModuleCompilationUnit; import org.intocps.maestro.interpreter.api.IValueLifecycleHandler; -import org.intocps.maestro.interpreter.values.*; -import org.intocps.maestro.interpreter.values.csv.CSVValue; -import org.intocps.maestro.interpreter.values.csv.CsvDataWriter; -import org.intocps.maestro.interpreter.values.datawriter.DataWriterValue; -import org.intocps.maestro.interpreter.values.derivativeestimator.DerivativeEstimatorValue; -import org.intocps.maestro.interpreter.values.fmi.Fmu3Value; -import org.intocps.maestro.interpreter.values.fmi.FmuValue; -import org.intocps.maestro.interpreter.values.modeltransition.ModelTransitionValue; -import org.intocps.maestro.interpreter.values.simulationcontrol.SimulationControlValue; -import org.intocps.maestro.interpreter.values.utilities.ArrayUtilValue; -import org.intocps.maestro.interpreter.values.variablestep.VariableStepValue; +import org.intocps.maestro.interpreter.extensions.*; +import org.intocps.maestro.interpreter.values.Value; +import org.intocps.maestro.interpreter.values.VoidValue; import org.reflections.Reflections; import org.reflections.ReflectionsException; import org.reflections.scanners.SubTypesScanner; import java.io.*; -import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; -import java.net.URI; -import java.net.URISyntaxException; import java.nio.file.Path; import java.util.*; +import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collectors; -import java.util.stream.IntStream; -import java.util.stream.StreamSupport; /** - * Default interpreter factory with framework support and other basic features. - * This class provides run-time support only. It creates and destroys certain types based on load and unload + * Default interpreter factory with framework support and other basic features. This class provides run-time support only. It creates and destroys + * certain types based on load and unload */ public class DefaultExternalValueFactory implements IExternalValueFactory { - final static List> defaultHandlers = - Arrays.asList(LoggerLifecycleHandler.class, CsvLifecycleHandler.class, ArrayUtilLifecycleHandler.class, - JavaClasspathLoaderLifecycleHandler.class, MathLifecycleHandler.class, Fmi2LifecycleHandler.class); + final static List> defaultHandlers = Arrays.asList(LoggerLifecycleHandler.class, + CsvLifecycleHandler.class, ArrayUtilLifecycleHandler.class, JavaClasspathLoaderLifecycleHandler.class, MathLifecycleHandler.class, + Fmi2LifecycleHandler.class); private final File workingDirectory; private final ByteArrayOutputStream baos; + private final Function resolver; protected Map lifecycleHandlers; protected Map values = new HashMap<>(); - public DefaultExternalValueFactory(File workingDirectory, + public DefaultExternalValueFactory(File workingDirectory, Function resolver, InputStream config) throws IOException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { this.workingDirectory = workingDirectory; + this.resolver = resolver; lifecycleHandlers = new HashMap<>(); @@ -106,14 +94,20 @@ public void addLifecycleHandler(IValueLifecycleHandler handler) { private IValueLifecycleHandler instantiateHandler(File workingDirectory, Class handler) throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException { IValueLifecycleHandler value; + try { //found constructor with a File argument. This is for the working directory - value = handler.getDeclaredConstructor(File.class).newInstance(workingDirectory); + value = handler.getDeclaredConstructor(File.class, Function.class).newInstance(workingDirectory, resolver); } catch (NoSuchMethodException e) { try { - value = handler.getDeclaredConstructor().newInstance(); + //found constructor with a File argument. This is for the working directory + value = handler.getDeclaredConstructor(File.class).newInstance(workingDirectory); } catch (NoSuchMethodException e2) { - return null; + try { + value = handler.getDeclaredConstructor().newInstance(); + } catch (NoSuchMethodException e3) { + return null; + } } } return value; @@ -205,404 +199,8 @@ public Value destroy(Value value) { @Override public IExternalValueFactory changeWorkingDirectory(Path newSuggestion, InputStream config) throws IOException, InvocationTargetException, NoSuchMethodException, IllegalAccessException, InstantiationException { - return new DefaultExternalValueFactory(newSuggestion.toFile(), config == null ? new ByteArrayInputStream(baos.toByteArray()) : config); - } - - protected abstract static class BaseLifecycleHandler implements IValueLifecycleHandler { - @Override - public void destroy(Value value) { - - } - - @Override - public InputStream getMablModule() { - return null; - } - } - - @IValueLifecycleHandler.ValueLifecycle(name = "VariableStep") - public static class VariableStepLifecycleHandler extends BaseLifecycleHandler { - @Override - public Either instantiate(List args) { - if (args == null || args.isEmpty()) { - return Either.left(new AnalysisException("No values passed")); - } - - if (args.stream().anyMatch(Objects::isNull)) { - return Either.left(new AnalysisException("Argument list contains null values")); - } - - String config = ((StringValue) args.get(0).deref()).getValue(); - return Either.right(new VariableStepValue(config)); - } - } - - @IValueLifecycleHandler.ValueLifecycle(name = "DerivativeEstimator") - public static class DerivativeEstimatorLifecycleHandler extends BaseLifecycleHandler { - @Override - public Either instantiate(List args) { - return Either.right(new DerivativeEstimatorValue()); - } - } - - @IValueLifecycleHandler.ValueLifecycle(name = "Logger") - public static class LoggerLifecycleHandler extends BaseLifecycleHandler { - @Override - public Either instantiate(List args) { - return Either.right(new LoggerValue()); - } - } - - @IValueLifecycleHandler.ValueLifecycle(name = "ConsolePrinter") - public static class ConsolePrinterLifecycleHandler extends BaseLifecycleHandler { - @Override - public Either instantiate(List args) { - return Either.right(new ConsolePrinterValue()); - } - } - - @IValueLifecycleHandler.ValueLifecycle(name = "CSV") - public static class CsvLifecycleHandler extends BaseLifecycleHandler { - @Override - public Either instantiate(List args) { - return Either.right(new CSVValue()); - } - } - - @IValueLifecycleHandler.ValueLifecycle(name = "ArrayUtil") - public static class ArrayUtilLifecycleHandler extends BaseLifecycleHandler { - @Override - public Either instantiate(List args) { - return Either.right(new ArrayUtilValue()); - } - } - - @IValueLifecycleHandler.ValueLifecycle(name = "JavaClasspathLoader") - public static class JavaClasspathLoaderLifecycleHandler extends BaseLifecycleHandler { - - - @Override - public Either instantiate(List args) { - if (args.isEmpty()) { - return Either.left(new Exception("Missing arguments for java classpath loader. Expecting: ...")); - } - - Value classNameArg = args.get(0).deref(); - if (classNameArg instanceof StringValue) { - - - String qualifiedClassName = ((StringValue) classNameArg).getValue(); - try { - Class clz = Class.forName(qualifiedClassName); - - if (!Value.class.isAssignableFrom(clz)) { - return Either.left(new Exception("Class not compatible with: " + Value.class.getName())); - } - - int argCount = args.size() - 1; - Class[] argTypes = IntStream.range(0, argCount).mapToObj(i -> Value.class).toArray(Class[]::new); - - Constructor ctor; - if (argTypes.length == 0) { - ctor = clz.getDeclaredConstructor(); - return Either.right((Value) ctor.newInstance()); - } else { - ctor = clz.getDeclaredConstructor(argTypes); - return Either.right((Value) ctor.newInstance(args.stream().skip(1).toArray(Value[]::new))); - } - - - } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InstantiationException | - InvocationTargetException e) { - return Either.left(e); - } - } - return Either.left(new Exception("Missing name of the class to load")); - } - } - - @IValueLifecycleHandler.ValueLifecycle(name = "Math") - public static class MathLifecycleHandler extends BaseLifecycleHandler { - @Override - public Either instantiate(List args) { - return Either.right(new MathValue()); - } - } - - @IValueLifecycleHandler.ValueLifecycle(name = "RealTime") - public static class RealTimeLifecycleHandler extends BaseLifecycleHandler { - @Override - public Either instantiate(List args) { - return Either.right(new RealTimeValue()); - } - } - - @IValueLifecycleHandler.ValueLifecycle(name = "BooleanLogic") - public static class BooleanLogicLifecycleHandler extends BaseLifecycleHandler { - @Override - public Either instantiate(List args) { - return Either.right(new BooleanLogicValue()); - } - } - - @IValueLifecycleHandler.ValueLifecycle(name = "FMI2") - public static class Fmi2LifecycleHandler extends BaseLifecycleHandler { - final private File workingDirectory; - - public Fmi2LifecycleHandler(File workingDirectory) { - this.workingDirectory = workingDirectory; - } - - @Override - public void destroy(Value value) { - if (value instanceof FmuValue) { - FmuValue fmuVal = (FmuValue) value; - FunctionValue unloadFunction = (FunctionValue) fmuVal.lookup("unload"); - unloadFunction.evaluate(Collections.emptyList()); - } - } - - @Override - public Either instantiate(List args) { - String guid = ((StringValue) args.get(0)).getValue(); - String path = ((StringValue) args.get(1)).getValue(); - try { - path = (new URI(path)).getRawPath(); - } catch (URISyntaxException e) { - return Either.left(new AnalysisException("The path passed to load is not a URI", e)); - } - return Either.right(new Fmi2Interpreter(workingDirectory).createFmiValue(path, guid)); - } - } - - @IValueLifecycleHandler.ValueLifecycle(name = "FMI3") - public static class Fmi3LifecycleHandler extends BaseLifecycleHandler { - final private File workingDirectory; - - public Fmi3LifecycleHandler(File workingDirectory) { - this.workingDirectory = workingDirectory; - } - - @Override - public void destroy(Value value) { - if (value instanceof Fmu3Value) { - Fmu3Value fmuVal = (Fmu3Value) value; - FunctionValue unloadFunction = (FunctionValue) fmuVal.lookup("unload"); - unloadFunction.evaluate(Collections.emptyList()); - } - } - - @Override - public Either instantiate(List args) { - String guid = ((StringValue) args.get(0)).getValue(); - String path = ((StringValue) args.get(1)).getValue(); - try { - path = (new URI(path)).getRawPath(); - } catch (URISyntaxException e) { - return Either.left(new AnalysisException("The path passed to load is not a URI", e)); - } - return Either.right(new Fmi3Interpreter(workingDirectory).createFmiValue(path, guid)); - } + return new DefaultExternalValueFactory(newSuggestion.toFile(), resolver, + config == null ? new ByteArrayInputStream(baos.toByteArray()) : config); } - @IValueLifecycleHandler.ValueLifecycle(name = "JFMI2") - public static class JFmi2LifecycleHandler extends BaseLifecycleHandler { - final private File workingDirectory; - - public JFmi2LifecycleHandler(File workingDirectory) { - this.workingDirectory = workingDirectory; - } - - @Override - public void destroy(Value value) { - if (value instanceof FmuValue) { - FmuValue fmuVal = (FmuValue) value; - FunctionValue unloadFunction = (FunctionValue) fmuVal.lookup("unload"); - unloadFunction.evaluate(Collections.emptyList()); - } - } - - @Override - public Either instantiate(List args) { - String className = ((StringValue) args.get(0)).getValue(); - try { - Class clz = this.getClass().getClassLoader().loadClass(className); - - return Either.right(new Fmi2Interpreter(workingDirectory).createFmiValue(clz)); - } catch (ClassNotFoundException e) { - return Either.left(new AnalysisException("The path passed to load is not a URI", e)); - } - } - } - - @IValueLifecycleHandler.ValueLifecycle(name = "ModelTransition") - public static class ModelTransitionLifecycleHandler extends BaseLifecycleHandler { - - @Override - public Either instantiate(List args) { - String transitionPath = ((StringValue) args.get(0)).getValue(); - return Either.right(new ModelTransitionValue(transitionPath)); - } - } - - @IValueLifecycleHandler.ValueLifecycle(name = "SimulationControl") - public static class SimulationControlDefaultLifecycleHandler extends BaseLifecycleHandler { - @Override - public Either instantiate(List args) { - return Either.right(new SimulationControlValue()); - } - } - - @IValueLifecycleHandler.ValueLifecycle(name = "MEnv") - public class MEnvLifecycleHandler extends BaseLifecycleHandler { - - public static final String ENVIRONMENT_VARIABLES = "environment_variables"; - - private final Map rawData; - - public MEnvLifecycleHandler(InputStream config) throws IOException { - - if (config != null && config.available() > 0) { - Map map = new ObjectMapper().readValue(config, new TypeReference<>() { - }); - this.rawData = map; - } else { - this.rawData = null; - } - - - } - - @Override - public Either instantiate(List args) { - - if (rawData == null || !rawData.containsKey(ENVIRONMENT_VARIABLES)) { - return Either.left(new Exception("Missing required runtime key: " + ENVIRONMENT_VARIABLES)); - } - - final Map data = (Map) rawData.get(ENVIRONMENT_VARIABLES); - - - Map members = new HashMap<>(); - members.put("getBool", new FunctionValue.ExternalFunctionValue(a -> { - - Value.checkArgLength(a, 1); - - String key = getEnvName(a); - Object val = data.get(key); - - - if (val instanceof Integer) { - return new BooleanValue(((Integer) val) > 1); - } else if (val instanceof Boolean) { - return new BooleanValue((Boolean) val); - } else { - throw new InterpreterException("Env key not found with the right type. Key '" + key + "' value '" + val + "'"); - } - - })); - members.put("getInt", new FunctionValue.ExternalFunctionValue(a -> { - - Value.checkArgLength(a, 1); - - String key = getEnvName(a); - Object val = data.get(key); - - if (val instanceof Integer) { - return new IntegerValue(((Integer) val).intValue()); - } else { - throw new InterpreterException("Env key not found with the right type. Key '" + key + "' value '" + val + "'"); - } - - })); - members.put("getReal", new FunctionValue.ExternalFunctionValue(a -> { - - Value.checkArgLength(a, 1); - - String key = getEnvName(a); - Object val = data.get(key); - - if (val instanceof Integer) { - return new RealValue(((Integer) val).doubleValue()); - } else if (val instanceof Double) { - return new RealValue((Double) val); - } else { - throw new InterpreterException("Env key not found with the right type. Key '" + key + "' value '" + val + "'"); - } - })); - members.put("getString", new FunctionValue.ExternalFunctionValue(a -> { - - Value.checkArgLength(a, 1); - - String key = getEnvName(a); - Object val = data.get(key); - if (val instanceof String) { - return new StringValue((String) val); - } else { - throw new InterpreterException("Env key not found with the right type. Key '" + key + "' value '" + val + "'"); - } - })); - - - ExternalModuleValue> val = new ExternalModuleValue<>(members, data) { - - }; - return Either.right(val); - } - - - private String getEnvName(List a) { - return ((StringValue) a.get(0).deref()).getValue(); - } - } - - @IValueLifecycleHandler.ValueLifecycle(name = "DataWriter") - protected class DataWriterLifecycleHandler extends BaseLifecycleHandler { - - static final String DEFAULT_CSV_FILENAME = "outputs.csv"; - final String DATA_WRITER_TYPE_NAME; - final String dataWriterFileNameFinal; - final List dataWriterFilterFinal; - final private File workingDirectory; - - public DataWriterLifecycleHandler(File workingDirectory, InputStream config) throws IOException { - this.workingDirectory = workingDirectory; - - DATA_WRITER_TYPE_NAME = this.getClass().getAnnotation(IValueLifecycleHandler.ValueLifecycle.class).name(); - String dataWriterFileName = DEFAULT_CSV_FILENAME; - List dataWriterFilter = null; - - if (config != null) { - JsonNode configTree = new ObjectMapper().readTree(config); - - if (configTree.has(DATA_WRITER_TYPE_NAME)) { - JsonNode dwConfig = configTree.get(DATA_WRITER_TYPE_NAME); - - for (JsonNode val : dwConfig) { - if (val.has("type") && val.get("type").isTextual() && val.get("type").asText().equals("CSV")) { - if (val.has("filename") && val.get("filename").isTextual()) { - dataWriterFileName = val.get("filename").asText(); - } - if (val.has("filter")) { - dataWriterFilter = - StreamSupport.stream(Spliterators.spliteratorUnknownSize(val.get("filter").iterator(), Spliterator.ORDERED), - false).map(v -> v.asText()).collect(Collectors.toList()); - } - - } - } - } - } - - dataWriterFileNameFinal = dataWriterFileName; - dataWriterFilterFinal = dataWriterFilter; - } - - @Override - public Either instantiate(List args) { - return Either.right(new DataWriterValue(Collections.singletonList(new CsvDataWriter( - workingDirectory == null ? new File(dataWriterFileNameFinal) : new File(workingDirectory, dataWriterFileNameFinal), - dataWriterFilterFinal)))); - } - } } diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/Fmi2Interpreter.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/Fmi2Interpreter.java index 673dfadbc..c51f149bb 100644 --- a/interpreter/src/main/java/org/intocps/maestro/interpreter/Fmi2Interpreter.java +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/Fmi2Interpreter.java @@ -48,8 +48,10 @@ public static double getDouble(Value value) { value = value.deref(); - if (value instanceof RealValue) { - return ((RealValue) value).getValue(); + if (value.isNumericDecimal()) { + return ((NumericValue) value).doubleValue(); + } else if (value.isNumeric()) { + return ((NumericValue) value).intValue(); } throw new InterpreterException("Value is not double"); } @@ -61,8 +63,8 @@ public static long getUint(Value value) { if (value instanceof UnsignedIntegerValue) { return ((UnsignedIntegerValue) value).getValue(); } - if (value instanceof IntegerValue) { - return ((IntegerValue) value).getValue(); + if (value instanceof NumericValue) { + return ((NumericValue) value).intValue(); } throw new InterpreterException("Value is not unsigned integer"); } @@ -77,7 +79,7 @@ public static String getString(Value value) { throw new InterpreterException("Value is not string"); } - static void checkArgLength(List values, int size) { + public static void checkArgLength(List values, int size) { if (values == null) { throw new InterpreterException("No values passed"); } @@ -87,11 +89,14 @@ static void checkArgLength(List values, int size) { } if (values.size() != size) { + String predix; if (values.size() < size) { - throw new InterpreterException("Too few arguments"); + predix = "Too few arguments."; } else { - throw new InterpreterException("Too many arguments"); + predix = "Too many arguments."; } + throw new InterpreterException(String.format("%s Excepted: %d, Actual: %s, Args: '%s'", predix, size, values.size(), + values.stream().map(v -> v.deref().toString()).collect(Collectors.joining(",")))); } } @@ -99,7 +104,7 @@ static List getArrayValue(Value value, Class clz) { return getArrayValue(value, Optional.empty(), clz); } - static List getArrayValue(Value value, Optional limit, Class clz) { + public static List getArrayValue(Value value, Optional limit, Class clz) { value = value.deref(); @@ -201,7 +206,7 @@ public static FmuComponentValue getFmuComponentValue(BufferedOutputStream fmuLog checkArgLength(fcargs, 3); - if (!(fcargs.get(2) instanceof UpdatableValue)) { + if (!(fcargs.get(2).isUpdatable())) { throw new InterpreterException("value not a reference value"); } long elementsToUse = getUint(fcargs.get(1)); @@ -239,7 +244,7 @@ public static FmuComponentValue getFmuComponentValue(BufferedOutputStream fmuLog getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) .toArray(); int[] values = - getArrayValue(fcargs.get(2), Optional.of(elementsToUse), IntegerValue.class).stream().mapToInt(IntegerValue::getValue).toArray(); + getArrayValue(fcargs.get(2), Optional.of(elementsToUse), NumericValue.class).stream().mapToInt(NumericValue::intValue).toArray(); try { Fmi2Status res = component.setIntegers(scalarValueIndices, values); @@ -253,7 +258,7 @@ public static FmuComponentValue getFmuComponentValue(BufferedOutputStream fmuLog checkArgLength(fcargs, 3); long elementsToUse = getUint(fcargs.get(1)); - if (!(fcargs.get(2) instanceof UpdatableValue)) { + if (!(fcargs.get(2).isUpdatable())) { throw new InterpreterException("value not a reference value"); } @@ -305,7 +310,7 @@ public static FmuComponentValue getFmuComponentValue(BufferedOutputStream fmuLog checkArgLength(fcargs, 3); - if (!(fcargs.get(2) instanceof UpdatableValue)) { + if (!(fcargs.get(2).isUpdatable())) { throw new InterpreterException("value not a reference value"); } @@ -360,7 +365,7 @@ public static FmuComponentValue getFmuComponentValue(BufferedOutputStream fmuLog checkArgLength(fcargs, 3); - if (!(fcargs.get(2) instanceof UpdatableValue)) { + if (!(fcargs.get(2).isUpdatable())) { throw new InterpreterException("value not a reference value"); } @@ -440,7 +445,7 @@ public static FmuComponentValue getFmuComponentValue(BufferedOutputStream fmuLog checkArgLength(fcargs, 1); - if (!(fcargs.get(0) instanceof UpdatableValue)) { + if (!(fcargs.get(0).isUpdatable())) { throw new InterpreterException("value not a reference value"); } @@ -488,17 +493,17 @@ public static FmuComponentValue getFmuComponentValue(BufferedOutputStream fmuLog checkArgLength(fcargs, 2); - if (!(fcargs.get(1) instanceof UpdatableValue)) { + if (!(fcargs.get(1).isUpdatable())) { throw new InterpreterException("value not a reference value"); } Value kindValue = fcargs.get(0).deref(); - if (!(kindValue instanceof IntegerValue)) { + if (!kindValue.isNumeric()) { throw new InterpreterException("Invalid kind value: " + kindValue); } - int kind = ((IntegerValue) kindValue).getValue(); + int kind = ((NumericValue) kindValue).intValue(); Fmi2StatusKind kindEnum = Arrays.stream(Fmi2StatusKind.values()).filter(v -> v.value == kind).findFirst().orElse(null); @@ -525,7 +530,7 @@ public static FmuComponentValue getFmuComponentValue(BufferedOutputStream fmuLog // int getRealOutputDerivatives(long[] scalarValueIndices, UInt nvr, int[] order, ref double[] derivatives); checkArgLength(fcargs, 4); - if (!(fcargs.get(3) instanceof UpdatableValue)) { + if (!(fcargs.get(3).isUpdatable())) { throw new InterpreterException("value not a reference value"); } @@ -744,11 +749,8 @@ public Value createFmiValue(String path, String guid) throws InterpreterExceptio System.out.println("Interpretation load took: " + (stopTime - startExecTime)); return new FmuValue(functions, fmu); - } catch (IOException | FmuInvocationException | FmuMissingLibraryException e) { - - e.printStackTrace(); - return new NullValue(); } catch (Exception e) { + e.printStackTrace(); return new NullValue(); } @@ -768,7 +770,8 @@ public Value createFmiValue(Class clz) { System.out.println("Interpretation load took: " + (stopTime - startExecTime)); return new FmuValue(functions, fmu); - } catch (IOException | FmuInvocationException | FmuMissingLibraryException | NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException | ParserConfigurationException | SAXException | XPathExpressionException e) { + } catch (IOException | FmuInvocationException | FmuMissingLibraryException | NoSuchMethodException | IllegalAccessException | + InstantiationException | InvocationTargetException | ParserConfigurationException | SAXException | XPathExpressionException e) { e.printStackTrace(); return new NullValue(); diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/Fmi3Interpreter.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/Fmi3Interpreter.java index 2a37bb5fc..276b4822c 100644 --- a/interpreter/src/main/java/org/intocps/maestro/interpreter/Fmi3Interpreter.java +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/Fmi3Interpreter.java @@ -6,13 +6,21 @@ import org.apache.logging.log4j.core.impl.Log4jLogEvent; import org.apache.logging.log4j.core.layout.PatternLayout; import org.apache.logging.log4j.message.ParameterizedMessage; -import org.intocps.fmi.*; -import org.intocps.fmi.jnifmuapi.fmi3.FmuResult; +import org.intocps.fmi.FmuInvocationException; +import org.intocps.fmi.FmuMissingLibraryException; import org.intocps.fmi.jnifmuapi.fmi3.*; +import org.intocps.maestro.ast.AFunctionDeclaration; +import org.intocps.maestro.ast.AModuleDeclaration; +import org.intocps.maestro.ast.node.ANameType; +import org.intocps.maestro.ast.node.AReferenceType; +import org.intocps.maestro.ast.node.PType; +import org.intocps.maestro.interpreter.external.ExternalReflectCallHelper; +import org.intocps.maestro.interpreter.external.IArgMapping; +import org.intocps.maestro.interpreter.external.TP; import org.intocps.maestro.interpreter.values.*; +import org.intocps.maestro.interpreter.values.fmi.Fmu3InstanceValue; +import org.intocps.maestro.interpreter.values.fmi.Fmu3StateValue; import org.intocps.maestro.interpreter.values.fmi.Fmu3Value; -import org.intocps.maestro.interpreter.values.fmi.FmuComponentStateValue; -import org.intocps.maestro.interpreter.values.fmi.FmuComponentValue; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -22,20 +30,80 @@ import java.net.URI; import java.nio.charset.StandardCharsets; import java.util.*; +import java.util.function.Function; +import java.util.function.Predicate; import java.util.stream.Collectors; import static org.intocps.maestro.interpreter.Fmi2Interpreter.*; public class Fmi3Interpreter { + static final ExternalReflectCallHelper.ArgMapping boolArrayOutArgMapper = new ExternalReflectCallHelper.ArgMapping(TP.Bool, 2, + ExternalReflectCallHelper.ArgMapping.InOut.Output, null); + static final ExternalReflectCallHelper.ArgMapping doubleArrayOutArgMapper = new ExternalReflectCallHelper.ArgMapping(TP.Real, 2, + ExternalReflectCallHelper.ArgMapping.InOut.Output, null); + + static final ExternalReflectCallHelper.ArgMapping intInArgMapper = new ExternalReflectCallHelper.ArgMapping(TP.Int, 1, + ExternalReflectCallHelper.ArgMapping.InOut.Input, null); + static final ExternalReflectCallHelper.ArgMapping doubleInArgMapper = new ExternalReflectCallHelper.ArgMapping(TP.Real, 1, + ExternalReflectCallHelper.ArgMapping.InOut.Input, null); + + static final ExternalReflectCallHelper.ArgMapping boolInArgMapper = new ExternalReflectCallHelper.ArgMapping(TP.Bool, 1, + ExternalReflectCallHelper.ArgMapping.InOut.Input, null); + + static final ExternalReflectCallHelper.ArgMapping doubleArrayInArgMapper = new ExternalReflectCallHelper.ArgMapping(TP.Real, 2, + ExternalReflectCallHelper.ArgMapping.InOut.Input, null); + + static final ExternalReflectCallHelper.ArgMapping longArrayInArgMapper = new ExternalReflectCallHelper.ArgMapping(TP.Long, 2, + ExternalReflectCallHelper.ArgMapping.InOut.Input, null); + + static final ExternalReflectCallHelper.ArgMapping uintArrayOutArgMapper = new ExternalReflectCallHelper.ArgMapping(TP.Int, 2, + ExternalReflectCallHelper.ArgMapping.InOut.Output, null); + static final ExternalReflectCallHelper.ArgMapping longArrayOutArgMapper = new ExternalReflectCallHelper.ArgMapping(TP.Long, 2, + ExternalReflectCallHelper.ArgMapping.InOut.Output, null); + + static final ExternalReflectCallHelper.ArgMapping intArrayOutArgMapper = new ExternalReflectCallHelper.ArgMapping(TP.Int, 2, + ExternalReflectCallHelper.ArgMapping.InOut.Output, null); + + final static Logger logger = LoggerFactory.getLogger(Interpreter.class); private final File workingDirectory; + private final Function resolver; - public Fmi3Interpreter(File workingDirectory) { + public Fmi3Interpreter(File workingDirectory, Function resolver) { this.workingDirectory = workingDirectory; + this.resolver = resolver; + } + + public static Double getDouble(Value value) { + + if (value == null || value instanceof NullValue) { + return null; + } + + value = value.deref(); + + if (value == null || value instanceof NullValue) { + return null; + } + + if (value instanceof RealValue) { + return ((RealValue) value).getValue(); + } + throw new InterpreterException("Value is not double"); + } + + public static UpdatableValue getUpdatable(Value v) { + if (!(v instanceof UpdatableValue)) { + throw new InterpreterException("value not a reference value"); + } + return (UpdatableValue) v; } - public static Map createFmuMembers(File workingDirectory, String guid, IFmi3Fmu fmu) { + public Map createFmuMembers(File workingDirectory, String guid, IFmi3Fmu fmu) { + + + var fmi3Module = resolver.apply("FMI3"); Map functions = new HashMap<>(); /* @@ -52,69 +120,71 @@ FMI2Component instantiateCoSimulationWrapAsFmi2(string instanceName, string inst functions.put("instantiateCoSimulation", new FunctionValue.ExternalFunctionValue(fargs -> { - Fmi2Interpreter.checkArgLength(fargs, 3); + Fmi2Interpreter.checkArgLength(fargs, 6); String name = Fmi2Interpreter.getString(fargs.get(0)); boolean visible = Fmi2Interpreter.getBool(fargs.get(1)); boolean logginOn = Fmi2Interpreter.getBool(fargs.get(2)); + boolean eventModeUsed = Fmi2Interpreter.getBool(fargs.get(3)); + boolean earlyReturnAllowed = Fmi2Interpreter.getBool(fargs.get(4)); + long[] requiredIntermediateVariables = getArrayValue(fargs.get(5), Optional.empty(), NumericValue.class).stream() + .mapToLong(NumericValue::longValue).toArray(); + try { long startInstantiateTime = System.nanoTime(); logger.debug(String.format("Loading native FMU. GUID: %s, NAME: %s", "" + guid, "" + name)); - BufferedOutputStream fmuLogOutputStream = - workingDirectory == null ? null : new BufferedOutputStream(new FileOutputStream(new File(workingDirectory, name + ".log"))); + BufferedOutputStream fmuLogOutputStream = workingDirectory == null ? null : new BufferedOutputStream( + new FileOutputStream(new File(workingDirectory, name + ".log"))); final String formatter = "{} {} {} {}"; String pattern = "%d{ISO8601} %-5p - %m%n"; Layout layout = PatternLayout.newBuilder().withPattern(pattern).withCharset(StandardCharsets.UTF_8).build();// - boolean eventModeUsed = false; - boolean earlyReturnAllowed = false; - long[] requiredIntermediateVariables = new long[0]; - IFmi3Instance instance = - fmu.instantiateCoSimulation(name, guid, visible, logginOn, eventModeUsed, earlyReturnAllowed, requiredIntermediateVariables, - (instanceName, status, category, message) -> { - logger.info("NATIVE: instance: '{}', status: '{}', category: '{}', message: {}", instanceName, status, category, - message); - { - - if (fmuLogOutputStream == null) { - return; - } - Log4jLogEvent.Builder builder = Log4jLogEvent.newBuilder() - .setMessage(new ParameterizedMessage(formatter, category, status, instanceName, message)); + ILogMessageCallback logCallback = (instanceName, status, category, message) -> { + logger.info("NATIVE: instance: '{}', status: '{}', category: '{}', message: {}", instanceName, status, category, message); + { + if (fmuLogOutputStream == null) { + return; + } - switch (status) { - case OK: - case Discard: - builder.setLevel(Level.INFO); - break; - case Error: - case Fatal: - builder.setLevel(Level.ERROR); - case Warning: - builder.setLevel(Level.WARN); - break; - default: - builder.setLevel(Level.TRACE); - break; - } + Log4jLogEvent.Builder builder = Log4jLogEvent.newBuilder() + .setMessage(new ParameterizedMessage(formatter, category, status, instanceName, message)); + + + switch (status) { + case OK: + case Discard: + builder.setLevel(Level.INFO); + break; + case Error: + case Fatal: + builder.setLevel(Level.ERROR); + case Warning: + builder.setLevel(Level.WARN); + break; + default: + builder.setLevel(Level.TRACE); + break; + } - try { - Log4jLogEvent event = builder.build(); - fmuLogOutputStream.write(layout.toByteArray(event)); - } catch (IOException e) { - e.printStackTrace(); - } - } - }, - (instanceEnvironment, intermediateUpdateTime, clocksTicked, intermediateVariableSetRequested, intermediateVariableGetAllowed, intermediateStepFinished, canReturnEarly) -> new IIntermediateUpdateCallback.IntermediateUpdateResponse( - false, intermediateUpdateTime)); + try { + Log4jLogEvent event = builder.build(); + fmuLogOutputStream.write(layout.toByteArray(event)); + } catch (IOException e) { + e.printStackTrace(); + } + } + }; + IIntermediateUpdateCallback intermediateUpdateCallback = (instanceEnvironment, intermediateUpdateTime, clocksTicked, intermediateVariableSetRequested, intermediateVariableGetAllowed, intermediateStepFinished, canReturnEarly) -> new IIntermediateUpdateCallback.IntermediateUpdateResponse( + false, intermediateUpdateTime); + IFmi3Instance instance = fmu.instantiateCoSimulation(name, guid, visible, logginOn, eventModeUsed, earlyReturnAllowed, + requiredIntermediateVariables, logCallback, null); if (instance == null) { @@ -124,10 +194,10 @@ FMI2Component instantiateCoSimulationWrapAsFmi2(string instanceName, string inst long stopInstantiateTime = System.nanoTime(); System.out.println("Interpretation instantiate took: " + (stopInstantiateTime - startInstantiateTime)); - return getFmuInstanceValue(fmuLogOutputStream, instance); + return getFmuInstanceValue(fmuLogOutputStream, instance, resolver); - } catch (IOException e) { + } catch (IOException | NoSuchMethodException e) { e.printStackTrace(); } @@ -145,11 +215,11 @@ FMI2Component instantiateCoSimulationWrapAsFmi2(string instanceName, string inst throw new InterpreterException("Too few arguments"); } - if (!(fargs.get(0) instanceof FmuComponentValue)) { + if (!(fargs.get(0) instanceof Fmu3InstanceValue)) { throw new InterpreterException("Argument must be an external module reference"); } - FmuComponentValue component = (FmuComponentValue) fargs.get(0); + Fmu3InstanceValue component = (Fmu3InstanceValue) fargs.get(0); try { OutputStream loggerOutputStream = component.getFmuLoggerOutputStream(); @@ -182,65 +252,296 @@ FMI2Component instantiateCoSimulationWrapAsFmi2(string instanceName, string inst return new VoidValue(); })); + + checkRequiredFunctions(fmi3Module, functions); + return functions; } - private static Value getFmuInstanceValue(BufferedOutputStream fmuLogOutputStream, IFmi3Instance instance) throws NoSuchMethodException { + static void checkRequiredFunctions(AModuleDeclaration module, Map functions) { + var expectedFunctions = module.getFunctions().stream().map(f -> f.getName().getText()).collect(Collectors.toSet()); + + if (expectedFunctions.size() != functions.size() || !functions.keySet().equals(expectedFunctions)) { + logger.warn("Runtime type '{}' does not match declaration. Missing: '{}'", module.getName().getText(), + expectedFunctions.stream().filter(n -> !functions.containsKey(n)).sorted().collect(Collectors.joining(",\n\t", "\n\t", ""))); + } + } + + private static Value getFmuInstanceValue(BufferedOutputStream fmuLogOutputStream, IFmi3Instance instance, + Function resolver) throws NoSuchMethodException { //populate component functions + var module = resolver.apply("FMI3Instance"); - Map componentMembers = new HashMap<>(createGetSetMembers(instance)); + Map functions = new HashMap<>(createGetSetMembers(instance)); - //void methods - componentMembers.put("freeInstance", new FunctionValue.ExternalFunctionValue(fcargs -> { + Predicate functionFilter = fun -> !fun.getName().getText().equals("enterInitializationMode") && !fun.getName().getText() + .startsWith("get") && !fun.getName().getText().equals("setBinary"); - checkArgLength(fcargs, 0); - try { - instance.freeInstance(); - return new VoidValue(); - } catch (FmuInvocationException e) { - throw new InterpreterException(e); + Function costumeArgMapper = t -> { + + boolean output = t instanceof AReferenceType; + if (output) { + t = ((AReferenceType) t).getType(); } - })); - String[] voidStatusMethods = - new String[]{"exitInitializationMode", "enterEventMode", "terminate", "reset", "enterConfigurationMode", "exitConfigurationMode", - "evaluateDiscreteStates", "enterContinuousTimeMode", "enterStepMode"}; + if (t instanceof ANameType) { + String typeName = ((ANameType) t).getName().getText(); + if (typeName.equals("FMI3Instance")) { + return new IArgMapping() { + @Override + public int getDimension() { + return 1; + } - for (String methodName : voidStatusMethods) { - Method method = componentMembers.getClass().getMethod(methodName); + @Override + public long[] getLimits() { + return null; + } - componentMembers.put(methodName, new FunctionValue.ExternalFunctionValue(fcargs -> { + @Override + public ExternalReflectCallHelper.ArgMapping.InOut getDirection() { + return ExternalReflectCallHelper.ArgMapping.InOut.Input; + } - checkArgLength(fcargs, 0); + @Override + public Object map(Value v) { + if (v instanceof ExternalModuleValue) { + return ((ExternalModuleValue) v).getModule(); + } + return null; + } + @Override + public void mapOut(Value original, Object value) { + throw new RuntimeException("This is only for input so should not be called"); + } - try { - Fmi3Status res = (Fmi3Status) method.invoke(instance); - return status2IntValue(res); - } catch (IllegalAccessException | InvocationTargetException e) { - throw new InterpreterException(e); + @Override + public Value mapOut(Object value) { + return new ExternalModuleValue<>(null, value) {}; + } + + @Override + public Class getType() { + return Object.class; + } + + @Override + public String getDescriptiveName() { + return "FMI3Instance"; + } + + @Override + public String getDefaultTestValue() { + return "null"; + } + }; + } else if (typeName.equals("FMU3State")) { + return new IArgMapping() { + @Override + public int getDimension() { + return 1; + } + + @Override + public long[] getLimits() { + return null; + } + + @Override + public ExternalReflectCallHelper.ArgMapping.InOut getDirection() { + return output ? ExternalReflectCallHelper.ArgMapping.InOut.Output : ExternalReflectCallHelper.ArgMapping.InOut.Input; + } + + @Override + public Object map(Value v) { + if (v instanceof Fmu3StateValue) { + return ((Fmu3StateValue) v).getModule(); + } + return null; + } + + @Override + public void mapOut(Value original, Object value) { + if (original instanceof UpdatableValue) { + UpdatableValue up = (UpdatableValue) original; + up.setValue(new Fmu3StateValue((Fmi3State) value)); + } + + } + + @Override + public Value mapOut(Object value) { + return null; + } + + @Override + public Class getType() { + return Fmi3State.class; + } + + @Override + public String getDescriptiveName() { + return "Fmi3State"; + } + + @Override + public String getDefaultTestValue() { + return null; + } + }; } - })); + } + return null; + }; + + for (AFunctionDeclaration function : module.getFunctions()) { + if (functionFilter == null || functionFilter.test(function)) { + functions.computeIfAbsent(function.getName().getText(), key -> { + try { + return new ExternalReflectCallHelper(function, instance, costumeArgMapper).build(); + } catch (NoSuchMethodException e) { + System.err.println(e.getMessage()); + return null; + } catch (RuntimeException e) { + System.err.println(e.getMessage()); + return null; + } + }); + + } } - // componentMembers.put("setDebugLogging", new FunctionValue.ExternalFunctionValue(fcargs -> { - // - // checkArgLength(fcargs, 3); - // - // boolean debugLogginOn = getBool(fcargs.get(0)); - // List categories = getArrayValue(fcargs.get(2), StringValue.class); + + for (AFunctionDeclaration function : module.getFunctions()) { + if (functionFilter == null || functionFilter.test(function)) { + + functions.computeIfAbsent(function.getName().getText(), key -> { + try { + return new ExternalReflectCallHelper(function, instance, costumeArgMapper) { + @Override + public FunctionValue.ExternalFunctionValue build() throws NoSuchMethodException { + final List args = Collections.unmodifiableList(this); + final IArgMapping rArg = returnArg; + final Method method = object.getClass().getMethod(functionName, + args.stream().filter(arg -> arg.getDirection() == ArgMapping.InOut.Input).map(IArgMapping::getType) + .toArray(Class[]::new)); + + if (method.getReturnType().isAssignableFrom(FmuResult.class)) { + //ok so we are using the result return type + long outputs = args.stream().filter(arg -> arg.getDirection() == ArgMapping.InOut.Output).count(); + System.out.println(outputs); + } + + + return new FunctionValue.ExternalFunctionValue(fcargs -> { + + checkArgLength(fcargs, args.size()); + + //map inputs + var vitr = fcargs.iterator(); + var mitr = args.iterator(); + List argValues = new ArrayList(args.size()); + while (vitr.hasNext() && mitr.hasNext()) { + var v = vitr.next(); + IArgMapping mapper = mitr.next(); + switch (mapper.getDirection()) { + case Input: + case Output: + argValues.add(mapper.map(v)); + break; + } + } + + try { + var ret = method.invoke(object, argValues.toArray()); + + //map outputs + vitr = fcargs.iterator(); + var voitr = argValues.iterator(); + mitr = args.iterator(); + while (vitr.hasNext() && voitr.hasNext() && mitr.hasNext()) { + var original = vitr.next(); + IArgMapping mapper = mitr.next(); + + Object output = null; + + switch (mapper.getDirection()) { + case Input: + case Output: + output = voitr.next(); + break; + } + + if (mapper.getDirection() == ArgMapping.InOut.Output) { + mapper.mapOut(original, output); + } + } + + + if (rArg == null) { + return new VoidValue(); + } + return rArg.mapOut(ret); + + + } catch (IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + }); + } + }.build(); + } catch (NoSuchMethodException e) { + System.err.println(e.getMessage()); + return null; + } catch (RuntimeException e) { + System.err.println(e.getMessage()); + return null; + } + }); + + } + } + + + //void methods + // functions.put("freeInstance", new FunctionValue.ExternalFunctionValue(fcargs -> { // + // checkArgLength(fcargs, 0); // try { - // Fmi3Status res = instance.setDebugLogging(debugLogginOn, categories.stream().map(StringValue::getValue).toArray(String[]::new)); - // return status2IntValue(res); + // instance.freeInstance(); + // return new VoidValue(); // } catch (FmuInvocationException e) { // throw new InterpreterException(e); // } + // // })); + // + // String[] voidStatusMethods = new String[]{"exitInitializationMode", "enterEventMode", "terminate", "reset", "enterConfigurationMode", + // "exitConfigurationMode", "evaluateDiscreteStates", "enterContinuousTimeMode", "enterStepMode"}; + // + // for (String methodName : voidStatusMethods) { + // Method method = instance.getClass().getMethod(methodName); + // + // functions.put(methodName, new FunctionValue.ExternalFunctionValue(fcargs -> { + // + // checkArgLength(fcargs, 0); + // + // + // try { + // Fmi3Status res = (Fmi3Status) method.invoke(instance); + // return status2IntValue(res); + // } catch (IllegalAccessException | InvocationTargetException e) { + // throw new InterpreterException(e); + // } + // })); + // + // } + /* @@ -284,306 +585,517 @@ int doStep(real currentCommunicationPoint, real communicationStepSize, bool nose */ - componentMembers.put("setDebugLogging", new FunctionValue.ExternalFunctionValue(fcargs -> { + // functions.put("setDebugLogging", new FunctionValue.ExternalFunctionValue(fcargs -> { + // + // checkArgLength(fcargs, 3); + // + // boolean debugLogginOn = getBool(fcargs.get(0)); + // // int arraySize = getInteger(fcargs.get(1)); + // List categories = getArrayValue(fcargs.get(2), StringValue.class); + // + // try { + // Fmi3Status res = instance.setDebugLogging(debugLogginOn, categories.stream().map(StringValue::getValue).toArray(String[]::new)); + // return new IntegerValue(res.value); + // } catch (FmuInvocationException e) { + // throw new InterpreterException(e); + // } + // })); + + // functions.put("setupExperiment", new FunctionValue.ExternalFunctionValue(fcargs -> { + // + // checkArgLength(fcargs, 5); + // + // boolean toleranceDefined = getBool(fcargs.get(0)); + // double tolerance = getDouble(fcargs.get(1)); + // double startTime = getDouble(fcargs.get(2)); + // boolean stopTimeDefined = getBool(fcargs.get(3)); + // double stopTime = getDouble(fcargs.get(4)); + // try { + // Fmi2Status res = instance.setupExperiment(toleranceDefined, tolerance, startTime, stopTimeDefined, stopTime); + // return new IntegerValue(res.value); + // } catch (FmuInvocationException e) { + // throw new InterpreterException(e); + // } + // })); + functions.put("enterInitializationMode", new FunctionValue.ExternalFunctionValue(fcargs -> { checkArgLength(fcargs, 3); - boolean debugLogginOn = getBool(fcargs.get(0)); - // int arraySize = getInteger(fcargs.get(1)); - List categories = getArrayValue(fcargs.get(2), StringValue.class); + Double tolerance = getDouble(fcargs.get(0)); + double startTime = getDouble(fcargs.get(1)); + Double stopTime = getDouble(fcargs.get(2)); + try { - Fmi3Status res = instance.setDebugLogging(debugLogginOn, categories.stream().map(StringValue::getValue).toArray(String[]::new)); + Fmi3Status res = instance.enterInitializationMode(tolerance, startTime, stopTime); return new IntegerValue(res.value); } catch (FmuInvocationException e) { throw new InterpreterException(e); } - })); - componentMembers.put("setupExperiment", new FunctionValue.ExternalFunctionValue(fcargs -> { + })); - checkArgLength(fcargs, 5); + functions.put("completedIntegratorStep", new FunctionValue.ExternalFunctionValue(fcargs -> { + // int completedIntegratorStep(bool nosetFMUStatePriorToCurrentPoint, bool[] enterEventMode,bool[] terminateSimulation); - boolean toleranceDefined = getBool(fcargs.get(0)); - double tolerance = getDouble(fcargs.get(1)); - double startTime = getDouble(fcargs.get(2)); - boolean stopTimeDefined = getBool(fcargs.get(3)); - double stopTime = getDouble(fcargs.get(4)); + checkArgLength(fcargs, 3); try { - Fmi2Status res = instance.setupExperiment(toleranceDefined, tolerance, startTime, stopTimeDefined, stopTime); - return new IntegerValue(res.value); + FmuResult res = instance.completedIntegratorStep( + (Boolean) boolInArgMapper.map(fcargs.get(0))); + boolArrayOutArgMapper.mapOut(fcargs.get(1), new boolean[]{res.result.isEnterEventMode()}); + boolArrayOutArgMapper.mapOut(fcargs.get(2), new boolean[]{res.result.isTerminateSimulation()}); + return status2IntValue(res.status); } catch (FmuInvocationException e) { throw new InterpreterException(e); } + })); - componentMembers.put("enterInitializationMode", new FunctionValue.ExternalFunctionValue(fcargs -> { - checkArgLength(fcargs, 0); + functions.put("getAdjointDerivative", new FunctionValue.ExternalFunctionValue(fcargs -> { + // int getAdjointDerivative(uint unknowns[], int nUnknowns, uint knowns[], int nKnowns, real seed[], int nSeed, + // real sensitivity[], int nSensitivity); + + checkArgLength(fcargs, 8); try { - Fmi2Status res = instance.enterInitializationMode(); - return new IntegerValue(res.value); + FmuResult res = instance.getGetAdjointDerivative((long[]) longArrayInArgMapper.map(fcargs.get(0)), + (long[]) longArrayInArgMapper.map(fcargs.get(2)), (double[]) doubleArrayInArgMapper.map(fcargs.get(4)), + (Integer) intInArgMapper.map(fcargs.get(5))); + doubleArrayOutArgMapper.mapOut(fcargs.get(6), res.result); + return status2IntValue(res.status); } catch (FmuInvocationException e) { throw new InterpreterException(e); } })); - componentMembers.put("exitInitializationMode", new FunctionValue.ExternalFunctionValue(fcargs -> { - checkArgLength(fcargs, 0); + + functions.put("getClock", new FunctionValue.ExternalFunctionValue(fcargs -> { + // int getClock(uint valueReferences[], int nValueReferences, bool values[]); + + checkArgLength(fcargs, 3); try { - Fmi2Status res = instance.exitInitializationMode(); - return new IntegerValue(res.value); + FmuResult res = instance.getClock((long[]) longArrayInArgMapper.map(fcargs.get(0))); + boolArrayOutArgMapper.mapOut(fcargs.get(2), res.result); + return status2IntValue(res.status); } catch (FmuInvocationException e) { throw new InterpreterException(e); } + })); - componentMembers.put("setReal", new FunctionValue.ExternalFunctionValue(fcargs -> { - checkArgLength(fcargs, 3); - long elementsToUse = getUint(fcargs.get(1)); - long[] scalarValueIndices = - getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) - .toArray(); - double[] values = getArrayValue(fcargs.get(2), Optional.of(elementsToUse), NumericValue.class).stream().limit(elementsToUse) - .mapToDouble(NumericValue::realValue).toArray(); + + functions.put("getContinuousStateDerivatives", new FunctionValue.ExternalFunctionValue(fcargs -> { + //int getContinuousStateDerivatives(real derivatives[], int nContinuousStates); + + checkArgLength(fcargs, 2); try { - Fmi2Status res = instance.setReals(scalarValueIndices, values); - return new IntegerValue(res.value); - } catch (InvalidParameterException | FmiInvalidNativeStateException e) { + FmuResult res = instance.getContinuousStateDerivatives((Integer) intInArgMapper.map(fcargs.get(1))); + doubleArrayOutArgMapper.mapOut(fcargs.get(0), res.result); + return status2IntValue(res.status); + } catch (FmuInvocationException e) { throw new InterpreterException(e); } })); - componentMembers.put("getReal", new FunctionValue.ExternalFunctionValue(fcargs -> { - checkArgLength(fcargs, 3); + functions.put("getContinuousStates", new FunctionValue.ExternalFunctionValue(fcargs -> { + //int getContinuousStates(real continuousStates[], int nContinuousStates); - if (!(fcargs.get(2) instanceof UpdatableValue)) { - throw new InterpreterException("value not a reference value"); + checkArgLength(fcargs, 2); + try { + FmuResult res = instance.getGetContinuousStates((Integer) intInArgMapper.map(fcargs.get(1))); + doubleArrayOutArgMapper.mapOut(fcargs.get(0), res.result); + return status2IntValue(res.status); + } catch (FmuInvocationException e) { + throw new InterpreterException(e); } - long elementsToUse = getUint(fcargs.get(1)); - long[] scalarValueIndices = - getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) - .toArray(); + })); + functions.put("getDirectionalDerivative", new FunctionValue.ExternalFunctionValue(fcargs -> { + // int getDirectionalDerivative(uint unknowns[], int nUnknowns, uint knowns[], int nKnowns, real seed[], int nSeed, + // real sensitivity[], int nSensitivity); + checkArgLength(fcargs, 8); try { - org.intocps.fmi.FmuResult res = instance.getReal(scalarValueIndices); - - if (res.status == Fmi2Status.OK) { - UpdatableValue ref = (UpdatableValue) fcargs.get(2); - - List values = Arrays.stream(ArrayUtils.toObject(res.result)).limit(elementsToUse).map(d -> new RealValue(d)) - .collect(Collectors.toList()); - - ref.setValue(new ArrayValue<>(values)); - } - - - return new IntegerValue(res.status.value); + FmuResult res = instance.getDirectionalDerivative((long[]) longArrayInArgMapper.map(fcargs.get(0)), + (long[]) longArrayInArgMapper.map(fcargs.get(2)), (double[]) doubleArrayInArgMapper.map(fcargs.get(4))); + doubleArrayOutArgMapper.mapOut(fcargs.get(6), res.result); + return status2IntValue(res.status); } catch (FmuInvocationException e) { throw new InterpreterException(e); } - })); - componentMembers.put("setInteger", new FunctionValue.ExternalFunctionValue(fcargs -> { - checkArgLength(fcargs, 3); - long elementsToUse = getUint(fcargs.get(1)); - long[] scalarValueIndices = - getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) - .toArray(); - int[] values = - getArrayValue(fcargs.get(2), Optional.of(elementsToUse), IntegerValue.class).stream().mapToInt(IntegerValue::getValue).toArray(); + + functions.put("getEventIndicators", new FunctionValue.ExternalFunctionValue(fcargs -> { + // int getEventIndicators(real eventIndicators[], int nEventIndicators); + + checkArgLength(fcargs, 2); try { - Fmi2Status res = instance.setIntegers(scalarValueIndices, values); - return new IntegerValue(res.value); - } catch (InvalidParameterException | FmiInvalidNativeStateException e) { + FmuResult res = instance.getGetEventIndicators((Integer) intInArgMapper.map(fcargs.get(1))); + doubleArrayOutArgMapper.mapOut(fcargs.get(0), res.result); + return status2IntValue(res.status); + } catch (FmuInvocationException e) { throw new InterpreterException(e); } - })); - componentMembers.put("getInteger", new FunctionValue.ExternalFunctionValue(fcargs -> { - - checkArgLength(fcargs, 3); - long elementsToUse = getUint(fcargs.get(1)); - if (!(fcargs.get(2) instanceof UpdatableValue)) { - throw new InterpreterException("value not a reference value"); - } + })); - long[] scalarValueIndices = - getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) - .toArray(); + functions.put("getIntervalDecimal", new FunctionValue.ExternalFunctionValue(fcargs -> { + // int getIntervalDecimal(uint valueReferences[], int nValueReferences, real intervals[], + // int qualifiers[]); + checkArgLength(fcargs, 4); try { - org.intocps.fmi.FmuResult res = instance.getInteger(scalarValueIndices); - - if (res.status == Fmi2Status.OK) { - UpdatableValue ref = (UpdatableValue) fcargs.get(2); - - List values = Arrays.stream(ArrayUtils.toObject(res.result)).limit(elementsToUse).map(i -> new IntegerValue(i)) - .collect(Collectors.toList()); - - ref.setValue(new ArrayValue<>(values)); - } - - - return new IntegerValue(res.status.value); - + FmuResult res = instance.getIntervalDecimal( + (long[]) longArrayInArgMapper.map(fcargs.get(0))); + doubleArrayOutArgMapper.mapOut(fcargs.get(2), res.result.getIntervals()); + doubleArrayOutArgMapper.mapOut(fcargs.get(3), res.result.getQualifiers()); + return status2IntValue(res.status); } catch (FmuInvocationException e) { throw new InterpreterException(e); } - })); - componentMembers.put("setBoolean", new FunctionValue.ExternalFunctionValue(fcargs -> { - checkArgLength(fcargs, 3); - long elementsToUse = getUint(fcargs.get(1)); - long[] scalarValueIndices = - getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) - .toArray(); - boolean[] values = ArrayUtils.toPrimitive( - getArrayValue(fcargs.get(2), Optional.of(elementsToUse), BooleanValue.class).stream().map(BooleanValue::getValue) - .collect(Collectors.toList()).toArray(new Boolean[]{})); + functions.put("getIntervalFraction", new FunctionValue.ExternalFunctionValue(fcargs -> { + // int getIntervalFraction(uint valueReferences[], int nValueReferences, uint intervalCounters[], uint resolutions[], + // int qualifiers[]); + checkArgLength(fcargs, 5); try { - Fmi2Status res = instance.setBooleans(scalarValueIndices, values); - return new IntegerValue(res.value); - } catch (InvalidParameterException | FmiInvalidNativeStateException e) { + FmuResult res = instance.getIntervalFraction( + (long[]) longArrayInArgMapper.map(fcargs.get(0))); + uintArrayOutArgMapper.mapOut(fcargs.get(2), res.result.getIntervalCounters()); + uintArrayOutArgMapper.mapOut(fcargs.get(3), res.result.getResolutions()); + intInArgMapper.mapOut(fcargs.get(3), Arrays.stream(res.result.getQualifiers()).map(q -> q.getValue()).toArray()); + return status2IntValue(res.status); + } catch (FmuInvocationException e) { throw new InterpreterException(e); } - })); - componentMembers.put("getBoolean", new FunctionValue.ExternalFunctionValue(fcargs -> { - checkArgLength(fcargs, 3); - - if (!(fcargs.get(2) instanceof UpdatableValue)) { - throw new InterpreterException("value not a reference value"); - } - - long elementsToUse = getUint(fcargs.get(1)); - - - long[] scalarValueIndices = - getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) - .toArray(); + })); + functions.put("getNominalsOfContinuousStates", new FunctionValue.ExternalFunctionValue(fcargs -> { + // int getNominalsOfContinuousStates(real nominals[], int nContinuousStates); + checkArgLength(fcargs, 2); try { - org.intocps.fmi.FmuResult res = instance.getBooleans(scalarValueIndices); - - if (res.status == Fmi2Status.OK) { - UpdatableValue ref = (UpdatableValue) fcargs.get(2); - - List values = - Arrays.stream(ArrayUtils.toObject(res.result)).limit(elementsToUse).map(BooleanValue::new).collect(Collectors.toList()); - - ref.setValue(new ArrayValue<>(values)); - } - - - return new IntegerValue(res.status.value); - + FmuResult res = instance.getGetNominalsOfContinuousStates((Integer) intInArgMapper.map(fcargs.get(1))); + doubleArrayOutArgMapper.mapOut(fcargs.get(0), res.result); + return status2IntValue(res.status); } catch (FmuInvocationException e) { throw new InterpreterException(e); } })); - componentMembers.put("setString", new FunctionValue.ExternalFunctionValue(fcargs -> { - - checkArgLength(fcargs, 3); - long elementsToUse = getUint(fcargs.get(1)); - long[] scalarValueIndices = - getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) - .toArray(); - String[] values = getArrayValue(fcargs.get(2), Optional.of(elementsToUse), StringValue.class).stream().map(StringValue::getValue) - .collect(Collectors.toList()).toArray(new String[]{}); + functions.put("getNumberOfContinuousStates", new FunctionValue.ExternalFunctionValue(fcargs -> { + // int getNumberOfContinuousStates(int[] nContinuousStates); + checkArgLength(fcargs, 1); try { - Fmi2Status res = instance.setStrings(scalarValueIndices, values); - return new IntegerValue(res.value); - } catch (InvalidParameterException | FmiInvalidNativeStateException e) { + FmuResult res = instance.getNumberOfContinuousStates(); + longArrayOutArgMapper.mapOut(fcargs.get(0), res.result); + return status2IntValue(res.status); + } catch (FmuInvocationException e) { throw new InterpreterException(e); } })); - componentMembers.put("getString", new FunctionValue.ExternalFunctionValue(fcargs -> { - - checkArgLength(fcargs, 3); - - if (!(fcargs.get(2) instanceof UpdatableValue)) { - throw new InterpreterException("value not a reference value"); - } - - - long elementsToUse = getUint(fcargs.get(1)); - - - long[] scalarValueIndices = - getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) - .toArray(); + functions.put("getNumberOfEventIndicators", new FunctionValue.ExternalFunctionValue(fcargs -> { + // int getNumberOfEventIndicators(int[] nEventIndicators); + checkArgLength(fcargs, 1); try { - org.intocps.fmi.FmuResult res = instance.getStrings(scalarValueIndices); - - if (res.status == Fmi2Status.OK) { - UpdatableValue ref = (UpdatableValue) fcargs.get(2); - - List values = Arrays.stream(res.result).limit(elementsToUse).map(StringValue::new).collect(Collectors.toList()); - - ref.setValue(new ArrayValue<>(values)); - } - - - return new IntegerValue(res.status.value); - + FmuResult res = instance.getNumberOfEventIndicators(); + intArrayOutArgMapper.mapOut(fcargs.get(0), res.result); + return status2IntValue(res.status); } catch (FmuInvocationException e) { throw new InterpreterException(e); } - })); - componentMembers.put("doStep", new FunctionValue.ExternalFunctionValue(fcargs -> { - checkArgLength(fcargs, 3); + // functions.put("exitInitializationMode", new FunctionValue.ExternalFunctionValue(fcargs -> { + // checkArgLength(fcargs, 0); + // try { + // Fmi3Status res = instance.exitInitializationMode(); + // return new IntegerValue(res.value); + // } catch (FmuInvocationException e) { + // throw new InterpreterException(e); + // } + // })); + // functions.put("setReal", new FunctionValue.ExternalFunctionValue(fcargs -> { + // checkArgLength(fcargs, 3); + // long elementsToUse = getUint(fcargs.get(1)); + // long[] scalarValueIndices = + // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) + // .toArray(); + // double[] values = getArrayValue(fcargs.get(2), Optional.of(elementsToUse), NumericValue.class).stream().limit(elementsToUse) + // .mapToDouble(NumericValue::realValue).toArray(); + // + // try { + // Fmi3Status res = instance.setReals(scalarValueIndices, values); + // return new IntegerValue(res.value); + // } catch (InvalidParameterException | FmiInvalidNativeStateException e) { + // throw new InterpreterException(e); + // } + // + // })); + // functions.put("getReal", new FunctionValue.ExternalFunctionValue(fcargs -> { + // + // checkArgLength(fcargs, 3); + // + // if (!(fcargs.get(2) instanceof UpdatableValue)) { + // throw new InterpreterException("value not a reference value"); + // } + // long elementsToUse = getUint(fcargs.get(1)); + // + // long[] scalarValueIndices = + // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) + // .toArray(); + // + // + // try { + // org.intocps.fmi.FmuResult res = instance.getReal(scalarValueIndices); + // + // if (res.status == Fmi2Status.OK) { + // UpdatableValue ref = (UpdatableValue) fcargs.get(2); + // + // List values = Arrays.stream(ArrayUtils.toObject(res.result)).limit(elementsToUse).map(d -> new RealValue(d)) + // .collect(Collectors.toList()); + // + // ref.setValue(new ArrayValue<>(values)); + // } + // + // + // return new IntegerValue(res.status.value); + // + // } catch (FmuInvocationException e) { + // throw new InterpreterException(e); + // } + // + // + // })); + // functions.put("setInteger", new FunctionValue.ExternalFunctionValue(fcargs -> { + // checkArgLength(fcargs, 3); + // long elementsToUse = getUint(fcargs.get(1)); + // long[] scalarValueIndices = + // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) + // .toArray(); + // int[] values = + // getArrayValue(fcargs.get(2), Optional.of(elementsToUse), IntegerValue.class).stream().mapToInt(IntegerValue::getValue).toArray(); + // + // try { + // Fmi2Status res = instance.setIntegers(scalarValueIndices, values); + // return new IntegerValue(res.value); + // } catch (InvalidParameterException | FmiInvalidNativeStateException e) { + // throw new InterpreterException(e); + // } + // })); + // functions.put("getInteger", new FunctionValue.ExternalFunctionValue(fcargs -> { + // + // checkArgLength(fcargs, 3); + // long elementsToUse = getUint(fcargs.get(1)); + // + // if (!(fcargs.get(2) instanceof UpdatableValue)) { + // throw new InterpreterException("value not a reference value"); + // } + // + // long[] scalarValueIndices = + // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) + // .toArray(); + // + // + // try { + // org.intocps.fmi.FmuResult res = instance.getInteger(scalarValueIndices); + // + // if (res.status == Fmi2Status.OK) { + // UpdatableValue ref = (UpdatableValue) fcargs.get(2); + // + // List values = Arrays.stream(ArrayUtils.toObject(res.result)).limit(elementsToUse).map(i -> new IntegerValue(i)) + // .collect(Collectors.toList()); + // + // ref.setValue(new ArrayValue<>(values)); + // } + // + // + // return new IntegerValue(res.status.value); + // + // } catch (FmuInvocationException e) { + // throw new InterpreterException(e); + // } + // + // + // })); + // functions.put("setBoolean", new FunctionValue.ExternalFunctionValue(fcargs -> { + // + // checkArgLength(fcargs, 3); + // long elementsToUse = getUint(fcargs.get(1)); + // long[] scalarValueIndices = + // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) + // .toArray(); + // boolean[] values = ArrayUtils.toPrimitive( + // getArrayValue(fcargs.get(2), Optional.of(elementsToUse), BooleanValue.class).stream().map(BooleanValue::getValue) + // .collect(Collectors.toList()).toArray(new Boolean[]{})); + // + // try { + // Fmi2Status res = instance.setBooleans(scalarValueIndices, values); + // return new IntegerValue(res.value); + // } catch (InvalidParameterException | FmiInvalidNativeStateException e) { + // throw new InterpreterException(e); + // } + // })); + // functions.put("getBoolean", new FunctionValue.ExternalFunctionValue(fcargs -> { + // + // checkArgLength(fcargs, 3); + // + // if (!(fcargs.get(2) instanceof UpdatableValue)) { + // throw new InterpreterException("value not a reference value"); + // } + // + // long elementsToUse = getUint(fcargs.get(1)); + // + // + // long[] scalarValueIndices = + // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) + // .toArray(); + // + // + // try { + // org.intocps.fmi.FmuResult res = instance.getBooleans(scalarValueIndices); + // + // if (res.status == Fmi2Status.OK) { + // UpdatableValue ref = (UpdatableValue) fcargs.get(2); + // + // List values = + // Arrays.stream(ArrayUtils.toObject(res.result)).limit(elementsToUse).map(BooleanValue::new).collect(Collectors.toList()); + // + // ref.setValue(new ArrayValue<>(values)); + // } + // + // + // return new IntegerValue(res.status.value); + // + // } catch (FmuInvocationException e) { + // throw new InterpreterException(e); + // } + // + // })); + // functions.put("setString", new FunctionValue.ExternalFunctionValue(fcargs -> { + // + // checkArgLength(fcargs, 3); + // long elementsToUse = getUint(fcargs.get(1)); + // + // long[] scalarValueIndices = + // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) + // .toArray(); + // String[] values = getArrayValue(fcargs.get(2), Optional.of(elementsToUse), StringValue.class).stream().map(StringValue::getValue) + // .collect(Collectors.toList()).toArray(new String[]{}); + // + // try { + // Fmi2Status res = instance.setStrings(scalarValueIndices, values); + // return new IntegerValue(res.value); + // } catch (InvalidParameterException | FmiInvalidNativeStateException e) { + // throw new InterpreterException(e); + // } + // + // })); + // functions.put("getString", new FunctionValue.ExternalFunctionValue(fcargs -> { + // + // checkArgLength(fcargs, 3); + // + // if (!(fcargs.get(2) instanceof UpdatableValue)) { + // throw new InterpreterException("value not a reference value"); + // } + // + // + // long elementsToUse = getUint(fcargs.get(1)); + // + // + // long[] scalarValueIndices = + // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) + // .toArray(); + // + // + // try { + // org.intocps.fmi.FmuResult res = instance.getStrings(scalarValueIndices); + // + // if (res.status == Fmi2Status.OK) { + // UpdatableValue ref = (UpdatableValue) fcargs.get(2); + // + // List values = Arrays.stream(res.result).limit(elementsToUse).map(StringValue::new).collect(Collectors.toList()); + // + // ref.setValue(new ArrayValue<>(values)); + // } + // + // + // return new IntegerValue(res.status.value); + // + // } catch (FmuInvocationException e) { + // throw new InterpreterException(e); + // } + // + // + // })); + functions.put("doStep", new FunctionValue.ExternalFunctionValue(fcargs -> { + + checkArgLength(fcargs, 7); + + //in double currentCommunicationPoint = getDouble(fcargs.get(0)); double communicationStepSize = getDouble(fcargs.get(1)); boolean noSetFMUStatePriorToCurrentPoint = getBool(fcargs.get(2)); + //out + + UpdatableValue eventHandlingNeeded = getUpdatable(fcargs.get(3)); + UpdatableValue terminateSimulation = getUpdatable(fcargs.get(4)); + UpdatableValue earlyReturn = getUpdatable(fcargs.get(5)); + UpdatableValue lastSuccessfulTime = getUpdatable(fcargs.get(6)); + /*int doStep(real currentCommunicationPoint, real communicationStepSize, bool nosetFMUStatePriorToCurrentPoint, + out bool eventHandlingNeeded,out bool terminateSimulation,out bool earlyReturn,out real lastSuccessfulTime);*/ try { - Fmi2Status res = instance.doStep(currentCommunicationPoint, communicationStepSize, noSetFMUStatePriorToCurrentPoint); - return new IntegerValue(res.value); + FmuResult res = instance.doStep(currentCommunicationPoint, communicationStepSize, + noSetFMUStatePriorToCurrentPoint); + + if (res.status == Fmi3Status.OK) { + eventHandlingNeeded.setValue(new BooleanValue(res.result.isEventHandlingNeeded())); + terminateSimulation.setValue(new BooleanValue(res.result.isTerminateSimulation())); + earlyReturn.setValue(new BooleanValue(res.result.isEarlyReturn())); + lastSuccessfulTime.setValue(new RealValue(res.result.getLastSuccessfulTime())); + } + return new IntegerValue(res.status.value); } catch (FmuInvocationException e) { throw new InterpreterException(e); } })); - componentMembers.put("terminate", new FunctionValue.ExternalFunctionValue(fcargs -> { + functions.put("terminate", new FunctionValue.ExternalFunctionValue(fcargs -> { checkArgLength(fcargs, 0); try { - Fmi2Status res = instance.terminate(); + Fmi3Status res = instance.terminate(); return new IntegerValue(res.value); } catch (FmuInvocationException e) { throw new InterpreterException(e); } })); - componentMembers.put("setState", new FunctionValue.ExternalFunctionValue(fcargs -> { + functions.put("setFMUState", new FunctionValue.ExternalFunctionValue(fcargs -> { checkArgLength(fcargs, 1); Value v = fcargs.get(0).deref(); - if (v instanceof FmuComponentStateValue) { + if (v instanceof Fmu3StateValue) { try { - FmuComponentStateValue stateValue = (FmuComponentStateValue) v; - Fmi2Status res = instance.setState(stateValue.getModule()); + Fmu3StateValue stateValue = (Fmu3StateValue) v; + Fmi3Status res = instance.setState(stateValue.getModule()); return new IntegerValue(res.value); } catch (FmuInvocationException e) { throw new InterpreterException(e); @@ -592,7 +1104,7 @@ int doStep(real currentCommunicationPoint, real communicationStepSize, bool nose throw new InterpreterException("Invalid value"); })); - componentMembers.put("getState", new FunctionValue.ExternalFunctionValue(fcargs -> { + functions.put("getFMUState", new FunctionValue.ExternalFunctionValue(fcargs -> { checkArgLength(fcargs, 1); @@ -603,11 +1115,11 @@ int doStep(real currentCommunicationPoint, real communicationStepSize, bool nose try { - org.intocps.fmi.FmuResult res = instance.getState(); + org.intocps.fmi.jnifmuapi.fmi3.FmuResult res = instance.getState(); - if (res.status == Fmi2Status.OK) { + if (res.status == Fmi3Status.OK) { UpdatableValue ref = (UpdatableValue) fcargs.get(0); - ref.setValue(new FmuComponentStateValue(res.result)); + ref.setValue(new Fmu3StateValue(res.result)); } @@ -619,16 +1131,16 @@ int doStep(real currentCommunicationPoint, real communicationStepSize, bool nose })); - componentMembers.put("freeState", new FunctionValue.ExternalFunctionValue(fcargs -> { + functions.put("freeFMUState", new FunctionValue.ExternalFunctionValue(fcargs -> { checkArgLength(fcargs, 1); Value v = fcargs.get(0).deref(); - if (v instanceof FmuComponentStateValue) { + if (v instanceof Fmu3StateValue) { try { - FmuComponentStateValue stateValue = (FmuComponentStateValue) v; - Fmi2Status res = instance.freeState(stateValue.getModule()); + Fmu3StateValue stateValue = (Fmu3StateValue) v; + Fmi3Status res = instance.freeState(stateValue.getModule()); return new IntegerValue(res.value); } catch (FmuInvocationException e) { throw new InterpreterException(e); @@ -640,110 +1152,111 @@ int doStep(real currentCommunicationPoint, real communicationStepSize, bool nose })); - componentMembers.put("getRealStatus", new FunctionValue.ExternalFunctionValue(fcargs -> { - - checkArgLength(fcargs, 2); - - if (!(fcargs.get(1) instanceof UpdatableValue)) { - throw new InterpreterException("value not a reference value"); - } - - Value kindValue = fcargs.get(0).deref(); - - if (!(kindValue instanceof IntegerValue)) { - throw new InterpreterException("Invalid kind value: " + kindValue); - } - - int kind = ((IntegerValue) kindValue).getValue(); - - Fmi2StatusKind kindEnum = Arrays.stream(Fmi2StatusKind.values()).filter(v -> v.value == kind).findFirst().orElse(null); - - try { - org.intocps.fmi.FmuResult res = instance.getRealStatus(kindEnum); - - if (res.status == Fmi2Status.OK) { - UpdatableValue ref = (UpdatableValue) fcargs.get(1); - - ref.setValue(new RealValue(res.result)); - } - - - return new IntegerValue(res.status.value); - - } catch (FmuInvocationException e) { - throw new InterpreterException(e); - } - - - })); - - componentMembers.put("getRealOutputDerivatives", new FunctionValue.ExternalFunctionValue(fcargs -> { - // int getRealOutputDerivatives(long[] scalarValueIndices, UInt nvr, int[] order, ref double[] derivatives); - checkArgLength(fcargs, 4); - - if (!(fcargs.get(3) instanceof UpdatableValue)) { - throw new InterpreterException("value not a reference value"); - } - - long elementsToUse = getUint(fcargs.get(1)); - - - long[] scalarValueIndices = - getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) - .toArray(); - - int[] orders = - getArrayValue(fcargs.get(2), Optional.of(elementsToUse), NumericValue.class).stream().mapToInt(NumericValue::intValue).toArray(); - - try { - FmuResult res = instance.getRealOutputDerivatives(scalarValueIndices, orders); - - if (res.status == Fmi2Status.OK) { - UpdatableValue ref = (UpdatableValue) fcargs.get(3); - - List values = Arrays.stream(ArrayUtils.toObject(res.result)).limit(elementsToUse).map(d -> new RealValue(d)) - .collect(Collectors.toList()); - - ref.setValue(new ArrayValue<>(values)); - } - - - return new IntegerValue(res.status.value); - - } catch (FmuInvocationException e) { - throw new InterpreterException(e); - } - - - })); - - componentMembers.put("setRealInputDerivatives", new FunctionValue.ExternalFunctionValue(fcargs -> { - // int setRealInputDerivatives(UInt[] scalarValueIndices, UInt nvr, int[] order, ref real[] derivatives); - checkArgLength(fcargs, 4); - long elementsToUse = getUint(fcargs.get(1)); - - - long[] scalarValueIndices = - getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) - .toArray(); - - int[] orders = - getArrayValue(fcargs.get(2), Optional.of(elementsToUse), NumericValue.class).stream().mapToInt(NumericValue::intValue).toArray(); - - double[] values = - getArrayValue(fcargs.get(3), Optional.of(elementsToUse), RealValue.class).stream().mapToDouble(RealValue::getValue).toArray(); - - try { - Fmi2Status res = instance.setRealInputDerivatives(scalarValueIndices, orders, values); - return new IntegerValue(res.value); - } catch (FmuInvocationException e) { - throw new InterpreterException(e); - } - - })); - + // functions.put("getRealStatus", new FunctionValue.ExternalFunctionValue(fcargs -> { + // + // checkArgLength(fcargs, 2); + // + // if (!(fcargs.get(1) instanceof UpdatableValue)) { + // throw new InterpreterException("value not a reference value"); + // } + // + // Value kindValue = fcargs.get(0).deref(); + // + // if (!(kindValue instanceof IntegerValue)) { + // throw new InterpreterException("Invalid kind value: " + kindValue); + // } + // + // int kind = ((IntegerValue) kindValue).getValue(); + // + // Fmi2StatusKind kindEnum = Arrays.stream(Fmi2StatusKind.values()).filter(v -> v.value == kind).findFirst().orElse(null); + // + // try { + // org.intocps.fmi.FmuResult res = instance.getRealStatus(kindEnum); + // + // if (res.status == Fmi2Status.OK) { + // UpdatableValue ref = (UpdatableValue) fcargs.get(1); + // + // ref.setValue(new RealValue(res.result)); + // } + // + // + // return new IntegerValue(res.status.value); + // + // } catch (FmuInvocationException e) { + // throw new InterpreterException(e); + // } + // + // + // })); + // + // functions.put("getRealOutputDerivatives", new FunctionValue.ExternalFunctionValue(fcargs -> { + // // int getRealOutputDerivatives(long[] scalarValueIndices, UInt nvr, int[] order, ref double[] derivatives); + // checkArgLength(fcargs, 4); + // + // if (!(fcargs.get(3) instanceof UpdatableValue)) { + // throw new InterpreterException("value not a reference value"); + // } + // + // long elementsToUse = getUint(fcargs.get(1)); + // + // + // long[] scalarValueIndices = + // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) + // .toArray(); + // + // int[] orders = + // getArrayValue(fcargs.get(2), Optional.of(elementsToUse), NumericValue.class).stream().mapToInt(NumericValue::intValue).toArray(); + // + // try { + // FmuResult res = instance.getRealOutputDerivatives(scalarValueIndices, orders); + // + // if (res.status == Fmi2Status.OK) { + // UpdatableValue ref = (UpdatableValue) fcargs.get(3); + // + // List values = Arrays.stream(ArrayUtils.toObject(res.result)).limit(elementsToUse).map(d -> new RealValue(d)) + // .collect(Collectors.toList()); + // + // ref.setValue(new ArrayValue<>(values)); + // } + // + // + // return new IntegerValue(res.status.value); + // + // } catch (FmuInvocationException e) { + // throw new InterpreterException(e); + // } + // + // + // })); + // + // functions.put("setRealInputDerivatives", new FunctionValue.ExternalFunctionValue(fcargs -> { + // // int setRealInputDerivatives(UInt[] scalarValueIndices, UInt nvr, int[] order, ref real[] derivatives); + // checkArgLength(fcargs, 4); + // long elementsToUse = getUint(fcargs.get(1)); + // + // + // long[] scalarValueIndices = + // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) + // .toArray(); + // + // int[] orders = + // getArrayValue(fcargs.get(2), Optional.of(elementsToUse), NumericValue.class).stream().mapToInt(NumericValue::intValue).toArray(); + // + // double[] values = + // getArrayValue(fcargs.get(3), Optional.of(elementsToUse), RealValue.class).stream().mapToDouble(RealValue::getValue).toArray(); + // + // try { + // Fmi2Status res = instance.setRealInputDerivatives(scalarValueIndices, orders, values); + // return new IntegerValue(res.value); + // } catch (FmuInvocationException e) { + // throw new InterpreterException(e); + // } + // + // }) + // ) + checkRequiredFunctions(module, functions); - return new FmuComponentValue(componentMembers, component, fmuLogOutputStream); + return new Fmu3InstanceValue(functions, instance, fmuLogOutputStream); } private static Value status2IntValue(Fmi3Status res) { @@ -803,24 +1316,30 @@ private static Value status2IntValue(Fmi3Status res) { componentMembers.put(method.getKey(), new FunctionValue.ExternalFunctionValue(fcargs -> { - checkArgLength(fcargs, 3); + checkArgLength(fcargs, 2); + Value scalarValue = fcargs.get(0); + Value valuesValue = fcargs.get(1); - if (!(fcargs.get(2) instanceof UpdatableValue)) { + if (!(valuesValue instanceof UpdatableValue)) { throw new InterpreterException("value not a reference value"); } - long elementsToUse = getUint(fcargs.get(1)); + // long elementsToUse = getUint(fcargs.get(1)); + + // long[] scalarValueIndices = + // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) + // .toArray(); - long[] scalarValueIndices = - getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) - .toArray(); + long[] scalarValueIndices = getArrayValue(scalarValue, Optional.empty(), NumericValue.class).stream() + .mapToLong(NumericValue::longValue).toArray(); + long elementsToUse = scalarValueIndices.length; try { @SuppressWarnings("rawtypes") FmuResult res = (FmuResult) m.invoke(instance, scalarValueIndices);// instance.getFloat64(scalarValueIndices); if (res.status == Fmi3Status.OK) { - UpdatableValue ref = (UpdatableValue) fcargs.get(2); + UpdatableValue ref = (UpdatableValue) valuesValue; List values = null; switch (method.getValue()) { @@ -904,14 +1423,21 @@ private static Value status2IntValue(Fmi3Status res) { break; } - Method m = instance.getClass().getMethod(method.getKey(), argClass); + Method m = instance.getClass().getMethod(method.getKey(), long[].class, argClass); componentMembers.put(method.getKey(), new FunctionValue.ExternalFunctionValue(fcargs -> { - checkArgLength(fcargs, 3); - long elementsToUse = getUint(fcargs.get(1)); - long[] scalarValueIndices = - getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) - .toArray(); + checkArgLength(fcargs, 2); + // long elementsToUse = getUint(fcargs.get(1)); + // long[] scalarValueIndices = + // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) + // .toArray(); + Value scalarValue = fcargs.get(0); + Value valuesValue = fcargs.get(1); + + long[] scalarValueIndices = getArrayValue(scalarValue, Optional.empty(), NumericValue.class).stream() + .mapToLong(NumericValue::longValue).toArray(); + + long elementsToUse = scalarValueIndices.length; //extract values Object values = null; @@ -920,46 +1446,47 @@ private static Value status2IntValue(Fmi3Status res) { case Bool: values = ArrayUtils.toPrimitive( - getArrayValue(fcargs.get(2), Optional.of(elementsToUse), BooleanValue.class).stream().map(BooleanValue::getValue) + getArrayValue(valuesValue, Optional.of(elementsToUse), BooleanValue.class).stream().map(BooleanValue::getValue) .collect(Collectors.toList()).toArray(new Boolean[]{})); break; case Byte: + //todo change native type to use int as byte us unsigned values = ArrayUtils.toPrimitive( - getArrayValue(fcargs.get(2), Optional.of(elementsToUse), ByteValue.class).stream().map(ByteValue::getValue) - .collect(Collectors.toList()).toArray(new Byte[]{})); + getArrayValue(valuesValue, Optional.of(elementsToUse), ByteValue.class).stream().map(ByteValue::getValue) + .map(v -> v & 0x00ff).map(Integer::byteValue).collect(Collectors.toList()).toArray(new Byte[]{})); break; case Float: values = ArrayUtils.toPrimitive( - getArrayValue(fcargs.get(2), Optional.of(elementsToUse), FloatValue.class).stream().map(FloatValue::getValue) + getArrayValue(valuesValue, Optional.of(elementsToUse), FloatValue.class).stream().map(FloatValue::getValue) .collect(Collectors.toList()).toArray(new Float[]{})); break; case Int: values = ArrayUtils.toPrimitive( - getArrayValue(fcargs.get(2), Optional.of(elementsToUse), IntegerValue.class).stream().map(IntegerValue::getValue) + getArrayValue(valuesValue, Optional.of(elementsToUse), IntegerValue.class).stream().map(IntegerValue::getValue) .collect(Collectors.toList()).toArray(new Integer[]{})); break; case Long: values = ArrayUtils.toPrimitive( - getArrayValue(fcargs.get(2), Optional.of(elementsToUse), LongValue.class).stream().map(LongValue::getValue) + getArrayValue(valuesValue, Optional.of(elementsToUse), LongValue.class).stream().map(LongValue::getValue) .collect(Collectors.toList()).toArray(new Long[]{})); break; case Real: - values = getArrayValue(fcargs.get(2), Optional.of(elementsToUse), NumericValue.class).stream().limit(elementsToUse) + values = getArrayValue(valuesValue, Optional.of(elementsToUse), NumericValue.class).stream().limit(elementsToUse) .mapToDouble(NumericValue::realValue).toArray(); break; case Short: values = ArrayUtils.toPrimitive( - getArrayValue(fcargs.get(2), Optional.of(elementsToUse), ShortValue.class).stream().map(ShortValue::getValue) + getArrayValue(valuesValue, Optional.of(elementsToUse), ShortValue.class).stream().map(ShortValue::getValue) .collect(Collectors.toList()).toArray(new Short[]{})); break; case String: - values = getArrayValue(fcargs.get(2), Optional.of(elementsToUse), StringValue.class).stream().map(StringValue::getValue) + values = getArrayValue(valuesValue, Optional.of(elementsToUse), StringValue.class).stream().map(StringValue::getValue) .collect(Collectors.toList()).toArray(new String[]{}); break; } try { - Fmi2Status res = (Fmi2Status) m.invoke(instance, scalarValueIndices, values);// instance.setBoolean().setReals + Fmi3Status res = (Fmi3Status) m.invoke(instance, scalarValueIndices, values);// instance.setBoolean().setReals // (scalarValueIndices, values); return new IntegerValue(res.value); } catch (IllegalAccessException | InvocationTargetException e) { @@ -1021,6 +1548,7 @@ public Value createFmiValue(String path, String guid) { long stopTime = System.nanoTime(); System.out.println("Interpretation load took: " + (stopTime - startExecTime)); + return new Fmu3Value(functions, fmu); } catch (IOException | FmuInvocationException | FmuMissingLibraryException e) { @@ -1033,14 +1561,5 @@ public Value createFmiValue(String path, String guid) { } } - private enum TP { - Bool, - Byte, - Float, - Int, - Long, - Real, - Short, - String, - } + } diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/Fmi3InterpreterAuto.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/Fmi3InterpreterAuto.java new file mode 100644 index 000000000..3c0507a7c --- /dev/null +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/Fmi3InterpreterAuto.java @@ -0,0 +1,1079 @@ +package org.intocps.maestro.interpreter; + +import org.apache.commons.lang3.ArrayUtils; +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.core.Layout; +import org.apache.logging.log4j.core.impl.Log4jLogEvent; +import org.apache.logging.log4j.core.layout.PatternLayout; +import org.apache.logging.log4j.message.ParameterizedMessage; +import org.intocps.fmi.FmuInvocationException; +import org.intocps.fmi.FmuMissingLibraryException; +import org.intocps.fmi.jnifmuapi.fmi3.*; +import org.intocps.maestro.interpreter.external.TP; +import org.intocps.maestro.interpreter.values.*; +import org.intocps.maestro.interpreter.values.fmi.Fmu3InstanceValue; +import org.intocps.maestro.interpreter.values.fmi.Fmu3StateValue; +import org.intocps.maestro.interpreter.values.fmi.Fmu3Value; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.*; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.stream.Collectors; + +import static org.intocps.maestro.interpreter.Fmi2Interpreter.*; + +public class Fmi3InterpreterAuto { + final static Logger logger = LoggerFactory.getLogger(Interpreter.class); + private final File workingDirectory; + + public Fmi3InterpreterAuto(File workingDirectory) { + + this.workingDirectory = workingDirectory; + } + + public static Double getDouble(Value value) { + + if (value == null || value instanceof NullValue) { + return null; + } + + value = value.deref(); + + if (value == null || value instanceof NullValue) { + return null; + } + + if (value instanceof RealValue) { + return ((RealValue) value).getValue(); + } + throw new InterpreterException("Value is not double"); + } + + public static UpdatableValue getUpdatable(Value v) { + if (!(v instanceof UpdatableValue)) { + throw new InterpreterException("value not a reference value"); + } + return (UpdatableValue) v; + } + + public static Map createFmuMembers(File workingDirectory, String guid, IFmi3Fmu fmu) { + Map functions = new HashMap<>(); + + functions.put("instantiateCoSimulation", new FunctionValue.ExternalFunctionValue(fargs -> { + + Fmi2Interpreter.checkArgLength(fargs, 6); + + String name = Fmi2Interpreter.getString(fargs.get(0)); + boolean visible = Fmi2Interpreter.getBool(fargs.get(1)); + boolean logginOn = Fmi2Interpreter.getBool(fargs.get(2)); + + boolean eventModeUsed = Fmi2Interpreter.getBool(fargs.get(3)); + boolean earlyReturnAllowed = Fmi2Interpreter.getBool(fargs.get(4)); + long[] requiredIntermediateVariables = + getArrayValue(fargs.get(5), Optional.empty(), NumericValue.class).stream().mapToLong(NumericValue::longValue).toArray(); + + try { + + long startInstantiateTime = System.nanoTime(); + + logger.debug(String.format("Loading native FMU. GUID: %s, NAME: %s", "" + guid, "" + name)); + + BufferedOutputStream fmuLogOutputStream = + workingDirectory == null ? null : new BufferedOutputStream(new FileOutputStream(new File(workingDirectory, name + ".log"))); + + final String formatter = "{} {} {} {}"; + String pattern = "%d{ISO8601} %-5p - %m%n"; + + Layout layout = PatternLayout.newBuilder().withPattern(pattern).withCharset(StandardCharsets.UTF_8).build();// + + ILogMessageCallback logCallback = (instanceName, status, category, message) -> { + logger.info("NATIVE: instance: '{}', status: '{}', category: '{}', message: {}", instanceName, status, category, message); + { + + if (fmuLogOutputStream == null) { + return; + } + + Log4jLogEvent.Builder builder = + Log4jLogEvent.newBuilder().setMessage(new ParameterizedMessage(formatter, category, status, instanceName, message)); + + + switch (status) { + case OK: + case Discard: + builder.setLevel(Level.INFO); + break; + case Error: + case Fatal: + builder.setLevel(Level.ERROR); + case Warning: + builder.setLevel(Level.WARN); + break; + default: + builder.setLevel(Level.TRACE); + break; + } + + try { + Log4jLogEvent event = builder.build(); + fmuLogOutputStream.write(layout.toByteArray(event)); + } catch (IOException e) { + e.printStackTrace(); + } + } + }; + IIntermediateUpdateCallback intermediateUpdateCallback = + (instanceEnvironment, intermediateUpdateTime, clocksTicked, intermediateVariableSetRequested, intermediateVariableGetAllowed, intermediateStepFinished, canReturnEarly) -> new IIntermediateUpdateCallback.IntermediateUpdateResponse( + false, intermediateUpdateTime); + IFmi3Instance instance = + fmu.instantiateCoSimulation(name, guid, visible, logginOn, eventModeUsed, earlyReturnAllowed, requiredIntermediateVariables, + logCallback, null); + + + if (instance == null) { + logger.debug("Instance instantiate failed"); + return new NullValue(); + } + long stopInstantiateTime = System.nanoTime(); + System.out.println("Interpretation instantiate took: " + (stopInstantiateTime - startInstantiateTime)); + + return getFmuInstanceValue(fmuLogOutputStream, instance); + + + } catch (IOException | NoSuchMethodException e) { + e.printStackTrace(); + } + + return null; + })); + + + functions.put("freeInstance", new FunctionValue.ExternalFunctionValue(fargs -> { + + fargs = fargs.stream().map(Value::deref).collect(Collectors.toList()); + + logger.debug("freeInstance"); + + if (fargs.size() != 1) { + throw new InterpreterException("Too few arguments"); + } + + if (!(fargs.get(0) instanceof Fmu3InstanceValue)) { + throw new InterpreterException("Argument must be an external module reference"); + } + + Fmu3InstanceValue component = (Fmu3InstanceValue) fargs.get(0); + + try { + OutputStream loggerOutputStream = component.getFmuLoggerOutputStream(); + if (loggerOutputStream != null) { + loggerOutputStream.close(); + } + component.getModule().freeInstance(); + } catch (IOException | FmuInvocationException e) { + e.printStackTrace(); + } + + + return new VoidValue(); + })); + + functions.put("unload", new FunctionValue.ExternalFunctionValue(fargs -> { + fargs = fargs.stream().map(Value::deref).collect(Collectors.toList()); + + logger.debug("unload"); + + if (fargs.size() != 0) { + throw new InterpreterException("Too many arguments"); + } + + try { + fmu.unLoad(); + } catch (FmuInvocationException e) { + e.printStackTrace(); + } + + return new VoidValue(); + })); + return functions; + } + + private static Value getFmuInstanceValue(BufferedOutputStream fmuLogOutputStream, IFmi3Instance instance) throws NoSuchMethodException { + + //populate component functions + + + Map componentMembers = new HashMap<>(createGetSetMembers(instance)); + + //void methods + componentMembers.put("freeInstance", new FunctionValue.ExternalFunctionValue(fcargs -> { + + checkArgLength(fcargs, 0); + try { + instance.freeInstance(); + return new VoidValue(); + } catch (FmuInvocationException e) { + throw new InterpreterException(e); + } + + })); + + String[] voidStatusMethods = + new String[]{"exitInitializationMode", "enterEventMode", "terminate", "reset", "enterConfigurationMode", "exitConfigurationMode", + "evaluateDiscreteStates", "enterContinuousTimeMode", "enterStepMode"}; + + for (String methodName : voidStatusMethods) { + Method method = instance.getClass().getMethod(methodName); + + componentMembers.put(methodName, new FunctionValue.ExternalFunctionValue(fcargs -> { + + checkArgLength(fcargs, 0); + + + try { + Fmi3Status res = (Fmi3Status) method.invoke(instance); + return status2IntValue(res); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new InterpreterException(e); + } + })); + + } + + + + /* + +int setDebugLogging(bool loggingOn, string categories[]); +int enterInitializationMode(bool toleranceDefined, real tolerance, real startTime, bool stopTimeDefined, + +int getBinary(uint valueReferences[], int nValueReferences, byte values[][], int nValues); +int setBinary(uint valueReferences[], int nValueReferences, long sizes[], byte array_name[][], int nValues); +int getNumberOfVariableDependencies(uint valueReference, out int nDependencies); +int getVariableDependencies(uint dependent, int elementIndicesOfDependent[], uint independents[], +int getFMUState(out FMUS3tate FMUState); +int setFMUState(FMUS3tate FMUState); +int freeFMUState(out FMUS3tate FMUState); +int getDirectionalDerivative(uint unknowns[], int nUnknowns, uint knowns[], int nKnowns, real seed[], int nSeed, +int getAdjointDerivative(uint unknowns[], int nUnknowns, uint knowns[], int nKnowns, real seed[], int nSeed, +int getClock(uint valueReferences[], int nValueReferences, bool values[]); +int setClock(uint valueReferences[], int nValueReferences, bool values[]); +int getIntervalDecimal(uint valueReferences[], int nValueReferences, real intervals[], +int getIntervalFraction(uint valueReferences[], int nValueReferences, uint intervalCounters[], uint resolutions[], +int getShiftDecimal(uint valueReferences[], int nValueReferences, real shifts[]); +int getShiftFraction(uint valueReferences[], int nValueReferences, uint shiftCounters[], uint resolutions[]); +int setIntervalDecimal(uint valueReferences[], int nValueReferences, real interval[]); +int setIntervalFraction(uint valueReferences[], int nValueReferences, uint intervalCounter[], uint resolution[]); +int setShiftDecimal(uint valueReferences[], int nValueReferences, real shifts[]); +int setShiftFraction(uint valueReferences[], int nValueReferences, uint counters[], uint resolutions[]); +int updateDiscreteStates(bool[] discreteStatesNeedUpdate, bool[] terminateSimulation, +int completedIntegratorStep(bool nosetFMUStatePriorToCurrentPoint, bool[] enterEventMode, +int setTime(real time); +int setContinuousStates(real continuousStates[], int nContinuousStates); +int getContinuousStateDerivatives(real derivatives[], int nContinuousStates); +int getEventIndicators(real eventIndicators[], int nEventIndicators); +int getContinuousStates(real continuousStates[], int nContinuousStates); +int getNominalsOfContinuousStates(real nominals[], int nContinuousStates); +int getNumberOfEventIndicators(int[] nEventIndicators); +int getNumberOfContinuousStates(int[] nContinuousStates); +int getOutputDerivatives(uint valueReferences[], int nValueReferences, int orders[], real values[], int nValues); +int doStep(real currentCommunicationPoint, real communicationStepSize, bool nosetFMUStatePriorToCurrentPoint, +int activateModelPartition(uint clockReference, real activationTime); + + */ + + + componentMembers.put("setDebugLogging", new FunctionValue.ExternalFunctionValue(fcargs -> { + + checkArgLength(fcargs, 3); + + boolean debugLogginOn = getBool(fcargs.get(0)); + // int arraySize = getInteger(fcargs.get(1)); + List categories = getArrayValue(fcargs.get(2), StringValue.class); + + try { + Fmi3Status res = instance.setDebugLogging(debugLogginOn, categories.stream().map(StringValue::getValue).toArray(String[]::new)); + return new IntegerValue(res.value); + } catch (FmuInvocationException e) { + throw new InterpreterException(e); + } + })); + + // componentMembers.put("setupExperiment", new FunctionValue.ExternalFunctionValue(fcargs -> { + // + // checkArgLength(fcargs, 5); + // + // boolean toleranceDefined = getBool(fcargs.get(0)); + // double tolerance = getDouble(fcargs.get(1)); + // double startTime = getDouble(fcargs.get(2)); + // boolean stopTimeDefined = getBool(fcargs.get(3)); + // double stopTime = getDouble(fcargs.get(4)); + // try { + // Fmi2Status res = instance.setupExperiment(toleranceDefined, tolerance, startTime, stopTimeDefined, stopTime); + // return new IntegerValue(res.value); + // } catch (FmuInvocationException e) { + // throw new InterpreterException(e); + // } + // })); + componentMembers.put("enterInitializationMode", new FunctionValue.ExternalFunctionValue(fcargs -> { + + checkArgLength(fcargs, 3); + + Double tolerance = getDouble(fcargs.get(0)); + double startTime = getDouble(fcargs.get(1)); + Double stopTime = getDouble(fcargs.get(2)); + + + try { + Fmi3Status res = instance.enterInitializationMode(tolerance, startTime, stopTime); + return new IntegerValue(res.value); + } catch (FmuInvocationException e) { + throw new InterpreterException(e); + } + + })); + // componentMembers.put("exitInitializationMode", new FunctionValue.ExternalFunctionValue(fcargs -> { + // checkArgLength(fcargs, 0); + // try { + // Fmi3Status res = instance.exitInitializationMode(); + // return new IntegerValue(res.value); + // } catch (FmuInvocationException e) { + // throw new InterpreterException(e); + // } + // })); + // componentMembers.put("setReal", new FunctionValue.ExternalFunctionValue(fcargs -> { + // checkArgLength(fcargs, 3); + // long elementsToUse = getUint(fcargs.get(1)); + // long[] scalarValueIndices = + // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) + // .toArray(); + // double[] values = getArrayValue(fcargs.get(2), Optional.of(elementsToUse), NumericValue.class).stream().limit(elementsToUse) + // .mapToDouble(NumericValue::realValue).toArray(); + // + // try { + // Fmi3Status res = instance.setReals(scalarValueIndices, values); + // return new IntegerValue(res.value); + // } catch (InvalidParameterException | FmiInvalidNativeStateException e) { + // throw new InterpreterException(e); + // } + // + // })); + // componentMembers.put("getReal", new FunctionValue.ExternalFunctionValue(fcargs -> { + // + // checkArgLength(fcargs, 3); + // + // if (!(fcargs.get(2) instanceof UpdatableValue)) { + // throw new InterpreterException("value not a reference value"); + // } + // long elementsToUse = getUint(fcargs.get(1)); + // + // long[] scalarValueIndices = + // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) + // .toArray(); + // + // + // try { + // org.intocps.fmi.FmuResult res = instance.getReal(scalarValueIndices); + // + // if (res.status == Fmi2Status.OK) { + // UpdatableValue ref = (UpdatableValue) fcargs.get(2); + // + // List values = Arrays.stream(ArrayUtils.toObject(res.result)).limit(elementsToUse).map(d -> new RealValue(d)) + // .collect(Collectors.toList()); + // + // ref.setValue(new ArrayValue<>(values)); + // } + // + // + // return new IntegerValue(res.status.value); + // + // } catch (FmuInvocationException e) { + // throw new InterpreterException(e); + // } + // + // + // })); + // componentMembers.put("setInteger", new FunctionValue.ExternalFunctionValue(fcargs -> { + // checkArgLength(fcargs, 3); + // long elementsToUse = getUint(fcargs.get(1)); + // long[] scalarValueIndices = + // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) + // .toArray(); + // int[] values = + // getArrayValue(fcargs.get(2), Optional.of(elementsToUse), IntegerValue.class).stream().mapToInt(IntegerValue::getValue).toArray(); + // + // try { + // Fmi2Status res = instance.setIntegers(scalarValueIndices, values); + // return new IntegerValue(res.value); + // } catch (InvalidParameterException | FmiInvalidNativeStateException e) { + // throw new InterpreterException(e); + // } + // })); + // componentMembers.put("getInteger", new FunctionValue.ExternalFunctionValue(fcargs -> { + // + // checkArgLength(fcargs, 3); + // long elementsToUse = getUint(fcargs.get(1)); + // + // if (!(fcargs.get(2) instanceof UpdatableValue)) { + // throw new InterpreterException("value not a reference value"); + // } + // + // long[] scalarValueIndices = + // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) + // .toArray(); + // + // + // try { + // org.intocps.fmi.FmuResult res = instance.getInteger(scalarValueIndices); + // + // if (res.status == Fmi2Status.OK) { + // UpdatableValue ref = (UpdatableValue) fcargs.get(2); + // + // List values = Arrays.stream(ArrayUtils.toObject(res.result)).limit(elementsToUse).map(i -> new IntegerValue(i)) + // .collect(Collectors.toList()); + // + // ref.setValue(new ArrayValue<>(values)); + // } + // + // + // return new IntegerValue(res.status.value); + // + // } catch (FmuInvocationException e) { + // throw new InterpreterException(e); + // } + // + // + // })); + // componentMembers.put("setBoolean", new FunctionValue.ExternalFunctionValue(fcargs -> { + // + // checkArgLength(fcargs, 3); + // long elementsToUse = getUint(fcargs.get(1)); + // long[] scalarValueIndices = + // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) + // .toArray(); + // boolean[] values = ArrayUtils.toPrimitive( + // getArrayValue(fcargs.get(2), Optional.of(elementsToUse), BooleanValue.class).stream().map(BooleanValue::getValue) + // .collect(Collectors.toList()).toArray(new Boolean[]{})); + // + // try { + // Fmi2Status res = instance.setBooleans(scalarValueIndices, values); + // return new IntegerValue(res.value); + // } catch (InvalidParameterException | FmiInvalidNativeStateException e) { + // throw new InterpreterException(e); + // } + // })); + // componentMembers.put("getBoolean", new FunctionValue.ExternalFunctionValue(fcargs -> { + // + // checkArgLength(fcargs, 3); + // + // if (!(fcargs.get(2) instanceof UpdatableValue)) { + // throw new InterpreterException("value not a reference value"); + // } + // + // long elementsToUse = getUint(fcargs.get(1)); + // + // + // long[] scalarValueIndices = + // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) + // .toArray(); + // + // + // try { + // org.intocps.fmi.FmuResult res = instance.getBooleans(scalarValueIndices); + // + // if (res.status == Fmi2Status.OK) { + // UpdatableValue ref = (UpdatableValue) fcargs.get(2); + // + // List values = + // Arrays.stream(ArrayUtils.toObject(res.result)).limit(elementsToUse).map(BooleanValue::new).collect(Collectors.toList()); + // + // ref.setValue(new ArrayValue<>(values)); + // } + // + // + // return new IntegerValue(res.status.value); + // + // } catch (FmuInvocationException e) { + // throw new InterpreterException(e); + // } + // + // })); + // componentMembers.put("setString", new FunctionValue.ExternalFunctionValue(fcargs -> { + // + // checkArgLength(fcargs, 3); + // long elementsToUse = getUint(fcargs.get(1)); + // + // long[] scalarValueIndices = + // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) + // .toArray(); + // String[] values = getArrayValue(fcargs.get(2), Optional.of(elementsToUse), StringValue.class).stream().map(StringValue::getValue) + // .collect(Collectors.toList()).toArray(new String[]{}); + // + // try { + // Fmi2Status res = instance.setStrings(scalarValueIndices, values); + // return new IntegerValue(res.value); + // } catch (InvalidParameterException | FmiInvalidNativeStateException e) { + // throw new InterpreterException(e); + // } + // + // })); + // componentMembers.put("getString", new FunctionValue.ExternalFunctionValue(fcargs -> { + // + // checkArgLength(fcargs, 3); + // + // if (!(fcargs.get(2) instanceof UpdatableValue)) { + // throw new InterpreterException("value not a reference value"); + // } + // + // + // long elementsToUse = getUint(fcargs.get(1)); + // + // + // long[] scalarValueIndices = + // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) + // .toArray(); + // + // + // try { + // org.intocps.fmi.FmuResult res = instance.getStrings(scalarValueIndices); + // + // if (res.status == Fmi2Status.OK) { + // UpdatableValue ref = (UpdatableValue) fcargs.get(2); + // + // List values = Arrays.stream(res.result).limit(elementsToUse).map(StringValue::new).collect(Collectors.toList()); + // + // ref.setValue(new ArrayValue<>(values)); + // } + // + // + // return new IntegerValue(res.status.value); + // + // } catch (FmuInvocationException e) { + // throw new InterpreterException(e); + // } + // + // + // })); + componentMembers.put("doStep", new FunctionValue.ExternalFunctionValue(fcargs -> { + + checkArgLength(fcargs, 7); + + //in + double currentCommunicationPoint = getDouble(fcargs.get(0)); + double communicationStepSize = getDouble(fcargs.get(1)); + boolean noSetFMUStatePriorToCurrentPoint = getBool(fcargs.get(2)); + //out + + UpdatableValue eventHandlingNeeded = getUpdatable(fcargs.get(3)); + UpdatableValue terminateSimulation = getUpdatable(fcargs.get(4)); + UpdatableValue earlyReturn = getUpdatable(fcargs.get(5)); + UpdatableValue lastSuccessfulTime = getUpdatable(fcargs.get(6)); + /*int doStep(real currentCommunicationPoint, real communicationStepSize, bool nosetFMUStatePriorToCurrentPoint, + out bool eventHandlingNeeded,out bool terminateSimulation,out bool earlyReturn,out real lastSuccessfulTime);*/ + + try { + FmuResult res = + instance.doStep(currentCommunicationPoint, communicationStepSize, noSetFMUStatePriorToCurrentPoint); + + if (res.status == Fmi3Status.OK) { + eventHandlingNeeded.setValue(new BooleanValue(res.result.isEventHandlingNeeded())); + terminateSimulation.setValue(new BooleanValue(res.result.isTerminateSimulation())); + earlyReturn.setValue(new BooleanValue(res.result.isEarlyReturn())); + lastSuccessfulTime.setValue(new RealValue(res.result.getLastSuccessfulTime())); + } + return new IntegerValue(res.status.value); + } catch (FmuInvocationException e) { + throw new InterpreterException(e); + } + })); + + componentMembers.put("terminate", new FunctionValue.ExternalFunctionValue(fcargs -> { + checkArgLength(fcargs, 0); + try { + Fmi3Status res = instance.terminate(); + return new IntegerValue(res.value); + } catch (FmuInvocationException e) { + throw new InterpreterException(e); + } + })); + + componentMembers.put("setState", new FunctionValue.ExternalFunctionValue(fcargs -> { + checkArgLength(fcargs, 1); + + Value v = fcargs.get(0).deref(); + + if (v instanceof Fmu3StateValue) { + try { + Fmu3StateValue stateValue = (Fmu3StateValue) v; + Fmi3Status res = instance.setState(stateValue.getModule()); + return new IntegerValue(res.value); + } catch (FmuInvocationException e) { + throw new InterpreterException(e); + } + } + + throw new InterpreterException("Invalid value"); + })); + componentMembers.put("getState", new FunctionValue.ExternalFunctionValue(fcargs -> { + + checkArgLength(fcargs, 1); + + if (!(fcargs.get(0) instanceof UpdatableValue)) { + throw new InterpreterException("value not a reference value"); + } + + + try { + + FmuResult res = instance.getState(); + + if (res.status == Fmi3Status.OK) { + UpdatableValue ref = (UpdatableValue) fcargs.get(0); + ref.setValue(new Fmu3StateValue(res.result)); + } + + + return new IntegerValue(res.status.value); + + } catch (FmuInvocationException e) { + throw new InterpreterException(e); + } + + + })); + componentMembers.put("freeState", new FunctionValue.ExternalFunctionValue(fcargs -> { + + checkArgLength(fcargs, 1); + + Value v = fcargs.get(0).deref(); + + if (v instanceof Fmu3StateValue) { + try { + Fmu3StateValue stateValue = (Fmu3StateValue) v; + Fmi3Status res = instance.freeState(stateValue.getModule()); + return new IntegerValue(res.value); + } catch (FmuInvocationException e) { + throw new InterpreterException(e); + } + } + + throw new InterpreterException("Invalid value"); + + + })); + + // componentMembers.put("getRealStatus", new FunctionValue.ExternalFunctionValue(fcargs -> { + // + // checkArgLength(fcargs, 2); + // + // if (!(fcargs.get(1) instanceof UpdatableValue)) { + // throw new InterpreterException("value not a reference value"); + // } + // + // Value kindValue = fcargs.get(0).deref(); + // + // if (!(kindValue instanceof IntegerValue)) { + // throw new InterpreterException("Invalid kind value: " + kindValue); + // } + // + // int kind = ((IntegerValue) kindValue).getValue(); + // + // Fmi2StatusKind kindEnum = Arrays.stream(Fmi2StatusKind.values()).filter(v -> v.value == kind).findFirst().orElse(null); + // + // try { + // org.intocps.fmi.FmuResult res = instance.getRealStatus(kindEnum); + // + // if (res.status == Fmi2Status.OK) { + // UpdatableValue ref = (UpdatableValue) fcargs.get(1); + // + // ref.setValue(new RealValue(res.result)); + // } + // + // + // return new IntegerValue(res.status.value); + // + // } catch (FmuInvocationException e) { + // throw new InterpreterException(e); + // } + // + // + // })); + // + // componentMembers.put("getRealOutputDerivatives", new FunctionValue.ExternalFunctionValue(fcargs -> { + // // int getRealOutputDerivatives(long[] scalarValueIndices, UInt nvr, int[] order, ref double[] derivatives); + // checkArgLength(fcargs, 4); + // + // if (!(fcargs.get(3) instanceof UpdatableValue)) { + // throw new InterpreterException("value not a reference value"); + // } + // + // long elementsToUse = getUint(fcargs.get(1)); + // + // + // long[] scalarValueIndices = + // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) + // .toArray(); + // + // int[] orders = + // getArrayValue(fcargs.get(2), Optional.of(elementsToUse), NumericValue.class).stream().mapToInt(NumericValue::intValue).toArray(); + // + // try { + // FmuResult res = instance.getRealOutputDerivatives(scalarValueIndices, orders); + // + // if (res.status == Fmi2Status.OK) { + // UpdatableValue ref = (UpdatableValue) fcargs.get(3); + // + // List values = Arrays.stream(ArrayUtils.toObject(res.result)).limit(elementsToUse).map(d -> new RealValue(d)) + // .collect(Collectors.toList()); + // + // ref.setValue(new ArrayValue<>(values)); + // } + // + // + // return new IntegerValue(res.status.value); + // + // } catch (FmuInvocationException e) { + // throw new InterpreterException(e); + // } + // + // + // })); + // + // componentMembers.put("setRealInputDerivatives", new FunctionValue.ExternalFunctionValue(fcargs -> { + // // int setRealInputDerivatives(UInt[] scalarValueIndices, UInt nvr, int[] order, ref real[] derivatives); + // checkArgLength(fcargs, 4); + // long elementsToUse = getUint(fcargs.get(1)); + // + // + // long[] scalarValueIndices = + // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) + // .toArray(); + // + // int[] orders = + // getArrayValue(fcargs.get(2), Optional.of(elementsToUse), NumericValue.class).stream().mapToInt(NumericValue::intValue).toArray(); + // + // double[] values = + // getArrayValue(fcargs.get(3), Optional.of(elementsToUse), RealValue.class).stream().mapToDouble(RealValue::getValue).toArray(); + // + // try { + // Fmi2Status res = instance.setRealInputDerivatives(scalarValueIndices, orders, values); + // return new IntegerValue(res.value); + // } catch (FmuInvocationException e) { + // throw new InterpreterException(e); + // } + // + // }) + // ) + + + return new Fmu3InstanceValue(componentMembers, instance, fmuLogOutputStream); + } + + private static Value status2IntValue(Fmi3Status res) { + switch (res) { + + case OK: + return new IntegerValue(0); + case Warning: + return new IntegerValue(1); + case Discard: + return new IntegerValue(2); + case Error: + return new IntegerValue(3); + case Fatal: + return new IntegerValue(4); + } + return null; + } + + private static Map createGetSetMembers(IFmi3Instance instance) throws NoSuchMethodException { + Map componentMembers = new HashMap<>(); + + Map methodTypeMapping = new HashMap<>() {{ + put("getFloat32", TP.Float); + put("getFloat64", TP.Real); + put("getInt8", TP.Byte); + put("getUInt8", TP.Byte); + put("getInt16", TP.Short); + put("getUInt16", TP.Short); + put("getInt32", TP.Int); + put("getUInt32", TP.Int); + put("getInt64", TP.Long); + put("getUInt64", TP.Long); + put("getBoolean", TP.Bool); + put("getString", TP.String); + put("setFloat32", TP.Float); + put("setFloat64", TP.Real); + put("setInt8", TP.Byte); + put("setUInt8", TP.Byte); + put("setInt16", TP.Short); + put("setUInt16", TP.Short); + put("setInt32", TP.Int); + put("setUInt32", TP.Int); + put("setInt64", TP.Long); + put("setUInt64", TP.Long); + put("setBoolean", TP.Bool); + put("setString", TP.String); + + + }}; + + + for (Map.Entry method : methodTypeMapping.entrySet()) { + if (method.getKey().startsWith("get")) { + + Method m = instance.getClass().getMethod(method.getKey(), long[].class); + + componentMembers.put(method.getKey(), new FunctionValue.ExternalFunctionValue(fcargs -> { + + checkArgLength(fcargs, 2); + Value scalarValue = fcargs.get(0); + Value valuesValue = fcargs.get(1); + + if (!(valuesValue instanceof UpdatableValue)) { + throw new InterpreterException("value not a reference value"); + } + // long elementsToUse = getUint(fcargs.get(1)); + + // long[] scalarValueIndices = + // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) + // .toArray(); + + long[] scalarValueIndices = + getArrayValue(scalarValue, Optional.empty(), NumericValue.class).stream().mapToLong(NumericValue::longValue).toArray(); + + long elementsToUse = scalarValueIndices.length; + + try { + @SuppressWarnings("rawtypes") + FmuResult res = (FmuResult) m.invoke(instance, scalarValueIndices);// instance.getFloat64(scalarValueIndices); + + if (res.status == Fmi3Status.OK) { + UpdatableValue ref = (UpdatableValue) valuesValue; + + List values = null; + switch (method.getValue()) { + + case Bool: + values = Arrays.stream(ArrayUtils.toObject((boolean[]) res.result)).limit(elementsToUse).map(BooleanValue::new) + .collect(Collectors.toList()); + break; + case Byte: + values = Arrays.stream(ArrayUtils.toObject((byte[]) res.result)).limit(elementsToUse).map(ByteValue::new) + .collect(Collectors.toList()); + break; + case Float: + values = Arrays.stream(ArrayUtils.toObject((float[]) res.result)).limit(elementsToUse).map(FloatValue::new) + .collect(Collectors.toList()); + break; + case Int: + values = Arrays.stream(ArrayUtils.toObject((int[]) res.result)).limit(elementsToUse).map(IntegerValue::new) + .collect(Collectors.toList()); + break; + case Long: + values = Arrays.stream(ArrayUtils.toObject((long[]) res.result)).limit(elementsToUse).map(LongValue::new) + .collect(Collectors.toList()); + break; + case Real: + values = Arrays.stream(ArrayUtils.toObject((double[]) res.result)).limit(elementsToUse).map(RealValue::new) + .collect(Collectors.toList()); + break; + case Short: + values = Arrays.stream(ArrayUtils.toObject((short[]) res.result)).limit(elementsToUse).map(ShortValue::new) + .collect(Collectors.toList()); + break; + case String: + values = Arrays.stream((String[]) res.result).limit(elementsToUse).map(StringValue::new) + .collect(Collectors.toList()); + break; + } + + + ref.setValue(new ArrayValue<>(values)); + } + + return status2IntValue(res.status); + + } catch (IllegalAccessException | InvocationTargetException e) { + throw new InterpreterException(e); + } + + + })); + + } else { + + Class argClass = null; + + switch (method.getValue()) { + + case Bool: + argClass = boolean[].class; + break; + case Byte: + argClass = byte[].class; + break; + case Float: + argClass = float[].class; + break; + case Int: + argClass = int[].class; + break; + case Long: + argClass = long[].class; + break; + case Real: + argClass = double[].class; + break; + case Short: + argClass = short[].class; + break; + case String: + argClass = String[].class; + break; + } + + Method m = instance.getClass().getMethod(method.getKey(), long[].class, argClass); + + componentMembers.put(method.getKey(), new FunctionValue.ExternalFunctionValue(fcargs -> { + checkArgLength(fcargs, 2); + // long elementsToUse = getUint(fcargs.get(1)); + // long[] scalarValueIndices = + // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) + // .toArray(); + Value scalarValue = fcargs.get(0); + Value valuesValue = fcargs.get(1); + + long[] scalarValueIndices = + getArrayValue(scalarValue, Optional.empty(), NumericValue.class).stream().mapToLong(NumericValue::longValue).toArray(); + + long elementsToUse = scalarValueIndices.length; + + //extract values + Object values = null; + + switch (method.getValue()) { + + case Bool: + values = ArrayUtils.toPrimitive( + getArrayValue(valuesValue, Optional.of(elementsToUse), BooleanValue.class).stream().map(BooleanValue::getValue) + .collect(Collectors.toList()).toArray(new Boolean[]{})); + break; + case Byte: + //todo change native type to use int as byte us unsigned + values = ArrayUtils.toPrimitive( + getArrayValue(valuesValue, Optional.of(elementsToUse), ByteValue.class).stream().map(ByteValue::getValue) + .map(v -> v & 0x00ff).map(Integer::byteValue).collect(Collectors.toList()).toArray(new Byte[]{})); + break; + case Float: + values = ArrayUtils.toPrimitive( + getArrayValue(valuesValue, Optional.of(elementsToUse), FloatValue.class).stream().map(FloatValue::getValue) + .collect(Collectors.toList()).toArray(new Float[]{})); + break; + case Int: + values = ArrayUtils.toPrimitive( + getArrayValue(valuesValue, Optional.of(elementsToUse), IntegerValue.class).stream().map(IntegerValue::getValue) + .collect(Collectors.toList()).toArray(new Integer[]{})); + break; + case Long: + values = ArrayUtils.toPrimitive( + getArrayValue(valuesValue, Optional.of(elementsToUse), LongValue.class).stream().map(LongValue::getValue) + .collect(Collectors.toList()).toArray(new Long[]{})); + break; + case Real: + values = getArrayValue(valuesValue, Optional.of(elementsToUse), NumericValue.class).stream().limit(elementsToUse) + .mapToDouble(NumericValue::realValue).toArray(); + break; + case Short: + values = ArrayUtils.toPrimitive( + getArrayValue(valuesValue, Optional.of(elementsToUse), ShortValue.class).stream().map(ShortValue::getValue) + .collect(Collectors.toList()).toArray(new Short[]{})); + break; + case String: + values = getArrayValue(valuesValue, Optional.of(elementsToUse), StringValue.class).stream().map(StringValue::getValue) + .collect(Collectors.toList()).toArray(new String[]{}); + break; + } + + try { + Fmi3Status res = (Fmi3Status) m.invoke(instance, scalarValueIndices, values);// instance.setBoolean().setReals + // (scalarValueIndices, values); + return new IntegerValue(res.value); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new InterpreterException(e); + } + + })); + } + } + + /* +int getFloat32(uint valueReferences[], int nValueReferences, float values[], int nValues); +int getFloat64(uint valueReferences[], int nValueReferences, real values[], int nValues); +int getInt8(uint valueReferences[], int nValueReferences, byte values[], int nValues); +int getUInt8(uint valueReferences[], int nValueReferences, byte values[], int nValues); +int getInt16(uint valueReferences[], int nValueReferences, short values[], int nValues); +int getUInt16(uint valueReferences[], int nValueReferences, short values[], int nValues); +int getInt32(uint valueReferences[], int nValueReferences, int values[], int nValues); +int getUInt32(uint valueReferences[], int nValueReferences, int values[], int nValues); +int getInt64(uint valueReferences[], int nValueReferences, long values[], int nValues); +int getUInt64(uint valueReferences[], int nValueReferences, long values[], int nValues); +int getBoolean(uint valueReferences[], int nValueReferences, bool values[], int nValues); +int getString(uint valueReferences[], int nValueReferences, string values[], int nValues); +int setFloat32(uint valueReferences[], int nValueReferences, float values[], int nValues); +int setFloat64(uint valueReferences[], int nValueReferences, real values[], int nValues); +int setInt8(uint valueReferences[], int nValueReferences, byte values[], int nValues); +int setUInt8(uint valueReferences[], int nValueReferences, byte values[], int nValues); +int setInt16(uint valueReferences[], int nValueReferences, short values[], int nValues); +int setUInt16(uint valueReferences[], int nValueReferences, short values[], int nValues); +int setInt32(uint valueReferences[], int nValueReferences, int values[], int nValues); +int setUInt32(uint valueReferences[], int nValueReferences, int values[], int nValues); +int setInt64(uint valueReferences[], int nValueReferences, long values[], int nValues); +int setUInt64(uint valueReferences[], int nValueReferences, long values[], int nValues); +int setBoolean(uint valueReferences[], int nValueReferences, bool values[], int nValues); +int setString(uint valueReferences[], int nValueReferences, string values[], int nValues); + */ + + + return componentMembers; + + } + + public Value createFmiValue(String path, String guid) { + try { + long startExecTime = System.nanoTime(); + + URI uri = URI.create(path); + if (!uri.isAbsolute()) { + uri = new File(".").toURI().resolve(uri); + } + File file = new File(uri); + + final IFmi3Fmu fmu = new Fmu3(file); + + fmu.load(); + + Map functions = createFmuMembers(workingDirectory, guid, fmu); + + long stopTime = System.nanoTime(); + + System.out.println("Interpretation load took: " + (stopTime - startExecTime)); + return new Fmu3Value(functions, fmu); + + } catch (IOException | FmuInvocationException | FmuMissingLibraryException e) { + + e.printStackTrace(); + return new NullValue(); + } catch (Exception e) { + e.printStackTrace(); + return new NullValue(); + } + } + + +} diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/Interpreter.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/Interpreter.java index 50b79ea0c..cc6244ced 100644 --- a/interpreter/src/main/java/org/intocps/maestro/interpreter/Interpreter.java +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/Interpreter.java @@ -10,16 +10,27 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.Vector; +import java.util.*; import java.util.stream.Collectors; public class Interpreter extends QuestionAnswerAdaptor { + final static Logger logger = LoggerFactory.getLogger(Interpreter.class); + static final Map, Class> typeValueMappings = new HashMap<>() {{ + put(AIntNumericPrimitiveType.class, IntegerValue.class); + put(AByteNumericPrimitiveType.class, ByteValue.class); + put(AShortNumericPrimitiveType.class, ShortValue.class); + put(AUIntNumericPrimitiveType.class, UnsignedIntegerValue.class); + put(ALongNumericPrimitiveType.class, LongValue.class); + put(AFloatNumericPrimitiveType.class, FloatValue.class); + put(ARealNumericPrimitiveType.class, RealValue.class); + put(AStringPrimitiveType.class, StringValue.class); + put(ABooleanPrimitiveType.class, BooleanValue.class); + put(ANameType.class, ExternalModuleValue.class); + }}; private final IExternalValueFactory loadFactory; private final ITransitionManager transitionManager; + public Interpreter(IExternalValueFactory loadFactory) { this(loadFactory, null); } @@ -189,28 +200,29 @@ public Value caseANotEqualBinaryExp(ANotEqualBinaryExp node, Context question) t } - public UpdatableValue createArrayValue(List sizes, PType type, Context question) throws AnalysisException { + public ArrayValue createArrayValue(List sizes, PType type, Context question) throws AnalysisException { List arrayValues = new ArrayList<>(); - for (int i = 0; i < ((IntegerValue) sizes.get(0).apply(this, question)).getValue(); i++) { + for (int i = 0; i < ((NumericValue) sizes.get(0).apply(this, question)).intValue(); i++) { if (sizes.size() > 1) { List nextSizes = sizes.subList(1, sizes.size()); // Call recursively - arrayValues.add(createArrayValue(nextSizes, type, question)); + arrayValues.add(new UpdatableValue(createArrayValue(nextSizes, type, question))); } else { - if (type instanceof AIntNumericPrimitiveType) { - arrayValues.add(new IntegerValue(0)); + + if (type instanceof AFunctionType || type instanceof ARealNumericPrimitiveType) { + arrayValues.add(new RealValue(0.0)); + } else if (type instanceof SNumericPrimitiveType) { + arrayValues.add(new ByteValue(0)); } else if (type instanceof ABooleanPrimitiveType) { arrayValues.add(new BooleanValue(false)); } else if (type instanceof AStringPrimitiveType) { arrayValues.add(new StringValue("")); - } else if (type instanceof ARealNumericPrimitiveType) { - arrayValues.add(new RealValue(0.0)); } else { arrayValues.add(new NullValue()); } } } - return new UpdatableValue(new ArrayValue<>(arrayValues)); + return new ArrayValue<>(arrayValues); } @Override @@ -223,25 +235,72 @@ public Value caseAVariableDeclaration(AVariableDeclaration node, Context questio if (!node.getSize().isEmpty() /*lazy check for array type*/) { - UpdatableValue val; + ArrayValue arrayValue; if (node.getInitializer() != null) { - val = new UpdatableValue(node.getInitializer().apply(this, question)); + arrayValue = (ArrayValue) node.getInitializer().apply(this, question); } else { if (node.getSize() == null || node.getSize().isEmpty()) { - throw new InterpreterException("Array size cannot be unspecified when no initializer is specified: " + node.getName()); + throw new InterpreterException("Array size cannot be unspecified when no .conlizer is specified: " + node.getName()); } //array deceleration - val = createArrayValue(node.getSize(), node.getType(), question); + arrayValue = createArrayValue(node.getSize(), node.getType(), question); + } + + //DTC: check that all values are of the right type + Class targetValueType = typeValueMappings.get(node.getType().getClass()); + for (int i = 0; i < arrayValue.getValues().size(); i++) { + + Value v = (Value) arrayValue.getValues().get(i); + if (targetValueType == null || targetValueType.isAssignableFrom(v.getClass())) { + continue; + } else if (v.isNumeric()) { + //we need to upcast all values explicitly here + NumericValue upcasted = ((NumericValue) v).upCast((Class) targetValueType); + + if (upcasted == null) { + throw new InterpreterException( + String.format("Array initializer value at index %d '%s' could not be upcasted. In ", i, v.toString()) + + "initializer is " + "specified: " + node.getName()); + } + + arrayValue.getValues().set(i, upcasted); + } + + } + // if (arrayValue.getValues().stream().anyMatch(v -> !targetValueType.isAssignableFrom(v.getClass()))) { + // + // arrayValue.getValues().stream().filter(v -> !targetValueType.isAssignableFrom(v.getClass())).map(v -> v.toString()) + // .collect(Collectors.joining(",")); + // } - question.put(node.getName(), val); + question.put(node.getName(), new UpdatableValue(arrayValue)); } else { - question.put(node.getName(), - new UpdatableValue(node.getInitializer() == null ? new UndefinedValue() : node.getInitializer().apply(this, question))); + Value initialValue = node.getInitializer() == null ? new UndefinedValue() : node.getInitializer().apply(this, question); + + if (initialValue.isNumeric()) { + Class targetValueType = typeValueMappings.get(node.getType().getClass()); + + if (targetValueType != null) { + + //we need to upcast all values explicitly here + NumericValue upcasted = ((NumericValue) initialValue).upCast((Class) targetValueType); + + if (upcasted == null) { + throw new InterpreterException( + String.format("Initializer value could not be upcasted. In ", initialValue.toString()) + "initializer is " + + "specified: " + node.getName() + " in " + node); + } + initialValue = upcasted; + } + } + + + question.put(node.getName(), new UpdatableValue(initialValue)); } return new VoidValue(); } @@ -293,11 +352,11 @@ public Value caseAPlusBinaryExp(APlusBinaryExp node, Context question) throws An NumericValue right = (NumericValue) node.getRight().apply(this, question).deref(); - if (left instanceof IntegerValue && right instanceof IntegerValue) { + if (!left.isNumericDecimal() && !right.isNumericDecimal()) { return new IntegerValue(left.intValue() + right.intValue()); + } else { + return new RealValue(left.realValue() + right.realValue()); } - - return new RealValue(left.realValue() + right.realValue()); } @@ -307,7 +366,7 @@ public Value caseAMinusBinaryExp(AMinusBinaryExp node, Context question) throws NumericValue right = (NumericValue) node.getRight().apply(this, question).deref(); - if (left instanceof IntegerValue && right instanceof IntegerValue) { + if (!left.isNumericDecimal() && !right.isNumericDecimal()) { return new IntegerValue(left.intValue() - right.intValue()); } @@ -441,7 +500,7 @@ private BooleanValue equals(Value lv, Value rv) throws AnalysisException { rv = rv.deref(); if (lv.equals(rv)) { - new BooleanValue(true); + return new BooleanValue(true); } else if (lv instanceof NumericValue && rv instanceof NumericValue) { NumericValue left = (NumericValue) lv; NumericValue right = (NumericValue) rv; @@ -486,7 +545,7 @@ public Value caseAGreaterEqualBinaryExp(AGreaterEqualBinaryExp node, Context que @Override public Value caseARealLiteralExp(ARealLiteralExp node, Context question) throws AnalysisException { - return new RealValue(node.getValue()); + return NumericValue.valueOf(node.getValue()); } @Override @@ -501,12 +560,12 @@ public Value caseAStringLiteralExp(AStringLiteralExp node, Context question) thr @Override public Value caseAIntLiteralExp(AIntLiteralExp node, Context question) throws AnalysisException { - return new IntegerValue(node.getValue()); + return NumericValue.valueOf(node.getValue()); } @Override public Value caseAUIntLiteralExp(AUIntLiteralExp node, Context question) throws AnalysisException { - return new UnsignedIntegerValue(node.getValue()); + return NumericValue.valueOf(node.getValue()); } protected Value getInnerArrayValue(ArrayValue arrayValue, List indices) { diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/ArrayUtilLifecycleHandler.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/ArrayUtilLifecycleHandler.java new file mode 100644 index 000000000..0f9454167 --- /dev/null +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/ArrayUtilLifecycleHandler.java @@ -0,0 +1,16 @@ +package org.intocps.maestro.interpreter.extensions; + +import com.spencerwi.either.Either; +import org.intocps.maestro.interpreter.api.IValueLifecycleHandler; +import org.intocps.maestro.interpreter.values.Value; +import org.intocps.maestro.interpreter.values.utilities.ArrayUtilValue; + +import java.util.List; + +@IValueLifecycleHandler.ValueLifecycle(name = "ArrayUtil") +public class ArrayUtilLifecycleHandler extends BaseLifecycleHandler { + @Override + public Either instantiate(List args) { + return Either.right(new ArrayUtilValue()); + } +} \ No newline at end of file diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/BaseLifecycleHandler.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/BaseLifecycleHandler.java new file mode 100644 index 000000000..fcaa2451e --- /dev/null +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/BaseLifecycleHandler.java @@ -0,0 +1,18 @@ +package org.intocps.maestro.interpreter.extensions; + +import org.intocps.maestro.interpreter.api.IValueLifecycleHandler; +import org.intocps.maestro.interpreter.values.Value; + +import java.io.InputStream; + +public abstract class BaseLifecycleHandler implements IValueLifecycleHandler { + @Override + public void destroy(Value value) { + + } + + @Override + public InputStream getMablModule() { + return null; + } +} \ No newline at end of file diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/BooleanLogicLifecycleHandler.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/BooleanLogicLifecycleHandler.java new file mode 100644 index 000000000..746d2e88f --- /dev/null +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/BooleanLogicLifecycleHandler.java @@ -0,0 +1,16 @@ +package org.intocps.maestro.interpreter.extensions; + +import com.spencerwi.either.Either; +import org.intocps.maestro.interpreter.api.IValueLifecycleHandler; +import org.intocps.maestro.interpreter.values.BooleanLogicValue; +import org.intocps.maestro.interpreter.values.Value; + +import java.util.List; + +@IValueLifecycleHandler.ValueLifecycle(name = "BooleanLogic") +public class BooleanLogicLifecycleHandler extends BaseLifecycleHandler { + @Override + public Either instantiate(List args) { + return Either.right(new BooleanLogicValue()); + } +} diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/ConsolePrinterLifecycleHandler.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/ConsolePrinterLifecycleHandler.java new file mode 100644 index 000000000..7c325e366 --- /dev/null +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/ConsolePrinterLifecycleHandler.java @@ -0,0 +1,16 @@ +package org.intocps.maestro.interpreter.extensions; + +import com.spencerwi.either.Either; +import org.intocps.maestro.interpreter.api.IValueLifecycleHandler; +import org.intocps.maestro.interpreter.values.ConsolePrinterValue; +import org.intocps.maestro.interpreter.values.Value; + +import java.util.List; + +@IValueLifecycleHandler.ValueLifecycle(name = "ConsolePrinter") +public class ConsolePrinterLifecycleHandler extends BaseLifecycleHandler { + @Override + public Either instantiate(List args) { + return Either.right(new ConsolePrinterValue()); + } +} \ No newline at end of file diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/CsvLifecycleHandler.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/CsvLifecycleHandler.java new file mode 100644 index 000000000..02d83e08b --- /dev/null +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/CsvLifecycleHandler.java @@ -0,0 +1,16 @@ +package org.intocps.maestro.interpreter.extensions; + +import com.spencerwi.either.Either; +import org.intocps.maestro.interpreter.api.IValueLifecycleHandler; +import org.intocps.maestro.interpreter.values.Value; +import org.intocps.maestro.interpreter.values.csv.CSVValue; + +import java.util.List; + +@IValueLifecycleHandler.ValueLifecycle(name = "CSV") +public class CsvLifecycleHandler extends BaseLifecycleHandler { + @Override + public Either instantiate(List args) { + return Either.right(new CSVValue()); + } +} \ No newline at end of file diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/DataWriterLifecycleHandler.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/DataWriterLifecycleHandler.java new file mode 100644 index 000000000..a3f03ed8a --- /dev/null +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/DataWriterLifecycleHandler.java @@ -0,0 +1,69 @@ +package org.intocps.maestro.interpreter.extensions; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.spencerwi.either.Either; +import org.intocps.maestro.interpreter.api.IValueLifecycleHandler; +import org.intocps.maestro.interpreter.values.Value; +import org.intocps.maestro.interpreter.values.csv.CsvDataWriter; +import org.intocps.maestro.interpreter.values.datawriter.DataWriterValue; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.Collections; +import java.util.List; +import java.util.Spliterator; +import java.util.Spliterators; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; + +@IValueLifecycleHandler.ValueLifecycle(name = "DataWriter") +public class DataWriterLifecycleHandler extends BaseLifecycleHandler { + + static final String DEFAULT_CSV_FILENAME = "outputs.csv"; + final String DATA_WRITER_TYPE_NAME; + final String dataWriterFileNameFinal; + final List dataWriterFilterFinal; + final private File workingDirectory; + + public DataWriterLifecycleHandler(File workingDirectory, InputStream config) throws IOException { + this.workingDirectory = workingDirectory; + + DATA_WRITER_TYPE_NAME = this.getClass().getAnnotation(IValueLifecycleHandler.ValueLifecycle.class).name(); + String dataWriterFileName = DEFAULT_CSV_FILENAME; + List dataWriterFilter = null; + + if (config != null) { + JsonNode configTree = new ObjectMapper().readTree(config); + + if (configTree.has(DATA_WRITER_TYPE_NAME)) { + JsonNode dwConfig = configTree.get(DATA_WRITER_TYPE_NAME); + + for (JsonNode val : dwConfig) { + if (val.has("type") && val.get("type").isTextual() && val.get("type").asText().equals("CSV")) { + if (val.has("filename") && val.get("filename").isTextual()) { + dataWriterFileName = val.get("filename").asText(); + } + if (val.has("filter")) { + dataWriterFilter = + StreamSupport.stream(Spliterators.spliteratorUnknownSize(val.get("filter").iterator(), Spliterator.ORDERED), + false).map(v -> v.asText()).collect(Collectors.toList()); + } + + } + } + } + } + + dataWriterFileNameFinal = dataWriterFileName; + dataWriterFilterFinal = dataWriterFilter; + } + + @Override + public Either instantiate(List args) { + return Either.right(new DataWriterValue(Collections.singletonList(new CsvDataWriter( + workingDirectory == null ? new File(dataWriterFileNameFinal) : new File(workingDirectory, dataWriterFileNameFinal), + dataWriterFilterFinal)))); + } +} \ No newline at end of file diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/DerivativeEstimatorLifecycleHandler.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/DerivativeEstimatorLifecycleHandler.java new file mode 100644 index 000000000..5b30f9750 --- /dev/null +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/DerivativeEstimatorLifecycleHandler.java @@ -0,0 +1,16 @@ +package org.intocps.maestro.interpreter.extensions; + +import com.spencerwi.either.Either; +import org.intocps.maestro.interpreter.api.IValueLifecycleHandler; +import org.intocps.maestro.interpreter.values.Value; +import org.intocps.maestro.interpreter.values.derivativeestimator.DerivativeEstimatorValue; + +import java.util.List; + +@IValueLifecycleHandler.ValueLifecycle(name = "DerivativeEstimator") +public class DerivativeEstimatorLifecycleHandler extends BaseLifecycleHandler { + @Override + public Either instantiate(List args) { + return Either.right(new DerivativeEstimatorValue()); + } +} \ No newline at end of file diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/Fmi2LifecycleHandler.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/Fmi2LifecycleHandler.java new file mode 100644 index 000000000..c3571c21a --- /dev/null +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/Fmi2LifecycleHandler.java @@ -0,0 +1,46 @@ +package org.intocps.maestro.interpreter.extensions; + +import com.spencerwi.either.Either; +import org.intocps.maestro.ast.analysis.AnalysisException; +import org.intocps.maestro.interpreter.Fmi2Interpreter; +import org.intocps.maestro.interpreter.api.IValueLifecycleHandler; +import org.intocps.maestro.interpreter.values.FunctionValue; +import org.intocps.maestro.interpreter.values.StringValue; +import org.intocps.maestro.interpreter.values.Value; +import org.intocps.maestro.interpreter.values.fmi.FmuValue; + +import java.io.File; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Collections; +import java.util.List; + +@IValueLifecycleHandler.ValueLifecycle(name = "FMI2") +public class Fmi2LifecycleHandler extends BaseLifecycleHandler { + final private File workingDirectory; + + public Fmi2LifecycleHandler(File workingDirectory) { + this.workingDirectory = workingDirectory; + } + + @Override + public void destroy(Value value) { + if (value instanceof FmuValue) { + FmuValue fmuVal = (FmuValue) value; + FunctionValue unloadFunction = (FunctionValue) fmuVal.lookup("unload"); + unloadFunction.evaluate(Collections.emptyList()); + } + } + + @Override + public Either instantiate(List args) { + String guid = ((StringValue) args.get(0)).getValue(); + String path = ((StringValue) args.get(1)).getValue(); + try { + path = (new URI(path)).getRawPath(); + } catch (URISyntaxException e) { + return Either.left(new AnalysisException("The path passed to load is not a URI", e)); + } + return Either.right(new Fmi2Interpreter(workingDirectory).createFmiValue(path, guid)); + } +} diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/Fmi3LifecycleHandler.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/Fmi3LifecycleHandler.java new file mode 100644 index 000000000..5c07c967d --- /dev/null +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/Fmi3LifecycleHandler.java @@ -0,0 +1,51 @@ +package org.intocps.maestro.interpreter.extensions; + +import com.spencerwi.either.Either; +import org.intocps.maestro.ast.AModuleDeclaration; +import org.intocps.maestro.ast.analysis.AnalysisException; +import org.intocps.maestro.interpreter.DefaultExternalValueFactory; +import org.intocps.maestro.interpreter.Fmi3Interpreter; +import org.intocps.maestro.interpreter.api.IValueLifecycleHandler; +import org.intocps.maestro.interpreter.values.FunctionValue; +import org.intocps.maestro.interpreter.values.StringValue; +import org.intocps.maestro.interpreter.values.Value; +import org.intocps.maestro.interpreter.values.fmi.Fmu3Value; + +import java.io.File; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Collections; +import java.util.List; +import java.util.function.Function; + +@IValueLifecycleHandler.ValueLifecycle(name = "FMI3") +public class Fmi3LifecycleHandler extends BaseLifecycleHandler { + final private File workingDirectory; + private final Function resolver; + + public Fmi3LifecycleHandler(File workingDirectory, Function resolver) { + this.workingDirectory = workingDirectory; + this.resolver = resolver; + } + + @Override + public void destroy(Value value) { + if (value instanceof Fmu3Value) { + Fmu3Value fmuVal = (Fmu3Value) value; + FunctionValue unloadFunction = (FunctionValue) fmuVal.lookup("unload"); + unloadFunction.evaluate(Collections.emptyList()); + } + } + + @Override + public Either instantiate(List args) { + String guid = ((StringValue) args.get(0)).getValue(); + String path = ((StringValue) args.get(1)).getValue(); + try { + path = (new URI(path)).getRawPath(); + } catch (URISyntaxException e) { + return Either.left(new AnalysisException("The path passed to load is not a URI", e)); + } + return Either.right(new Fmi3Interpreter(workingDirectory,resolver).createFmiValue(path, guid)); + } +} \ No newline at end of file diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/JFmi2LifecycleHandler.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/JFmi2LifecycleHandler.java new file mode 100644 index 000000000..38b308028 --- /dev/null +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/JFmi2LifecycleHandler.java @@ -0,0 +1,44 @@ +package org.intocps.maestro.interpreter.extensions; + +import com.spencerwi.either.Either; +import org.intocps.maestro.ast.analysis.AnalysisException; +import org.intocps.maestro.interpreter.Fmi2Interpreter; +import org.intocps.maestro.interpreter.api.IValueLifecycleHandler; +import org.intocps.maestro.interpreter.values.FunctionValue; +import org.intocps.maestro.interpreter.values.StringValue; +import org.intocps.maestro.interpreter.values.Value; +import org.intocps.maestro.interpreter.values.fmi.FmuValue; + +import java.io.File; +import java.util.Collections; +import java.util.List; + +@IValueLifecycleHandler.ValueLifecycle(name = "JFMI2") +public class JFmi2LifecycleHandler extends BaseLifecycleHandler { + final private File workingDirectory; + + public JFmi2LifecycleHandler(File workingDirectory) { + this.workingDirectory = workingDirectory; + } + + @Override + public void destroy(Value value) { + if (value instanceof FmuValue) { + FmuValue fmuVal = (FmuValue) value; + FunctionValue unloadFunction = (FunctionValue) fmuVal.lookup("unload"); + unloadFunction.evaluate(Collections.emptyList()); + } + } + + @Override + public Either instantiate(List args) { + String className = ((StringValue) args.get(0)).getValue(); + try { + Class clz = this.getClass().getClassLoader().loadClass(className); + + return Either.right(new Fmi2Interpreter(workingDirectory).createFmiValue(clz)); + } catch (ClassNotFoundException e) { + return Either.left(new AnalysisException("The path passed to load is not a URI", e)); + } + } +} diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/JavaClasspathLoaderLifecycleHandler.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/JavaClasspathLoaderLifecycleHandler.java new file mode 100644 index 000000000..b41863c72 --- /dev/null +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/JavaClasspathLoaderLifecycleHandler.java @@ -0,0 +1,55 @@ +package org.intocps.maestro.interpreter.extensions; + +import com.spencerwi.either.Either; +import org.intocps.maestro.interpreter.api.IValueLifecycleHandler; +import org.intocps.maestro.interpreter.values.StringValue; +import org.intocps.maestro.interpreter.values.Value; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.List; +import java.util.stream.IntStream; + +@IValueLifecycleHandler.ValueLifecycle(name = "JavaClasspathLoader") +public class JavaClasspathLoaderLifecycleHandler extends BaseLifecycleHandler { + + + @Override + public Either instantiate(List args) { + if (args.isEmpty()) { + return Either.left(new Exception("Missing arguments for java classpath loader. Expecting: ...")); + } + + Value classNameArg = args.get(0).deref(); + if (classNameArg instanceof StringValue) { + + + String qualifiedClassName = ((StringValue) classNameArg).getValue(); + try { + Class clz = Class.forName(qualifiedClassName); + + if (!Value.class.isAssignableFrom(clz)) { + return Either.left(new Exception("Class not compatible with: " + Value.class.getName())); + } + + int argCount = args.size() - 1; + Class[] argTypes = IntStream.range(0, argCount).mapToObj(i -> Value.class).toArray(Class[]::new); + + Constructor ctor; + if (argTypes.length == 0) { + ctor = clz.getDeclaredConstructor(); + return Either.right((Value) ctor.newInstance()); + } else { + ctor = clz.getDeclaredConstructor(argTypes); + return Either.right((Value) ctor.newInstance(args.stream().skip(1).toArray(Value[]::new))); + } + + + } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InstantiationException | + InvocationTargetException e) { + return Either.left(e); + } + } + return Either.left(new Exception("Missing name of the class to load")); + } +} \ No newline at end of file diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/LoggerLifecycleHandler.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/LoggerLifecycleHandler.java new file mode 100644 index 000000000..73fb71b27 --- /dev/null +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/LoggerLifecycleHandler.java @@ -0,0 +1,16 @@ +package org.intocps.maestro.interpreter.extensions; + +import com.spencerwi.either.Either; +import org.intocps.maestro.interpreter.api.IValueLifecycleHandler; +import org.intocps.maestro.interpreter.values.LoggerValue; +import org.intocps.maestro.interpreter.values.Value; + +import java.util.List; + +@IValueLifecycleHandler.ValueLifecycle(name = "Logger") +public class LoggerLifecycleHandler extends BaseLifecycleHandler { + @Override + public Either instantiate(List args) { + return Either.right(new LoggerValue()); + } +} \ No newline at end of file diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/MEnvLifecycleHandler.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/MEnvLifecycleHandler.java new file mode 100644 index 000000000..c224ec1c8 --- /dev/null +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/MEnvLifecycleHandler.java @@ -0,0 +1,116 @@ +package org.intocps.maestro.interpreter.extensions; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.spencerwi.either.Either; +import org.intocps.maestro.interpreter.InterpreterException; +import org.intocps.maestro.interpreter.api.IValueLifecycleHandler; +import org.intocps.maestro.interpreter.values.*; + +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@IValueLifecycleHandler.ValueLifecycle(name = "MEnv") +public class MEnvLifecycleHandler extends BaseLifecycleHandler { + + public static final String ENVIRONMENT_VARIABLES = "environment_variables"; + + private final Map rawData; + + public MEnvLifecycleHandler(InputStream config) throws IOException { + + if (config != null && config.available() > 0) { + Map map = new ObjectMapper().readValue(config, new TypeReference<>() {}); + this.rawData = map; + } else { + this.rawData = null; + } + + + } + + @Override + public Either instantiate(List args) { + + if (rawData == null || !rawData.containsKey(ENVIRONMENT_VARIABLES)) { + return Either.left(new Exception("Missing required runtime key: " + ENVIRONMENT_VARIABLES)); + } + + final Map data = (Map) rawData.get(ENVIRONMENT_VARIABLES); + + + Map members = new HashMap<>(); + members.put("getBool", new FunctionValue.ExternalFunctionValue(a -> { + + Value.checkArgLength(a, 1); + + String key = getEnvName(a); + Object val = data.get(key); + + + if (val instanceof Integer) { + return new BooleanValue(((Integer) val) > 1); + } else if (val instanceof Boolean) { + return new BooleanValue((Boolean) val); + } else { + throw new InterpreterException("Env key not found with the right type. Key '" + key + "' value '" + val + "'"); + } + + })); + members.put("getInt", new FunctionValue.ExternalFunctionValue(a -> { + + Value.checkArgLength(a, 1); + + String key = getEnvName(a); + Object val = data.get(key); + + if (val instanceof Integer) { + return new IntegerValue(((Integer) val).intValue()); + } else { + throw new InterpreterException("Env key not found with the right type. Key '" + key + "' value '" + val + "'"); + } + + })); + members.put("getReal", new FunctionValue.ExternalFunctionValue(a -> { + + Value.checkArgLength(a, 1); + + String key = getEnvName(a); + Object val = data.get(key); + + if (val instanceof Integer) { + return new RealValue(((Integer) val).doubleValue()); + } else if (val instanceof Double) { + return new RealValue((Double) val); + } else { + throw new InterpreterException("Env key not found with the right type. Key '" + key + "' value '" + val + "'"); + } + })); + members.put("getString", new FunctionValue.ExternalFunctionValue(a -> { + + Value.checkArgLength(a, 1); + + String key = getEnvName(a); + Object val = data.get(key); + if (val instanceof String) { + return new StringValue((String) val); + } else { + throw new InterpreterException("Env key not found with the right type. Key '" + key + "' value '" + val + "'"); + } + })); + + + ExternalModuleValue> val = new ExternalModuleValue<>(members, data) { + + }; + return Either.right(val); + } + + + private String getEnvName(List a) { + return ((StringValue) a.get(0).deref()).getValue(); + } +} diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/MathLifecycleHandler.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/MathLifecycleHandler.java new file mode 100644 index 000000000..07bee940b --- /dev/null +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/MathLifecycleHandler.java @@ -0,0 +1,16 @@ +package org.intocps.maestro.interpreter.extensions; + +import com.spencerwi.either.Either; +import org.intocps.maestro.interpreter.api.IValueLifecycleHandler; +import org.intocps.maestro.interpreter.values.MathValue; +import org.intocps.maestro.interpreter.values.Value; + +import java.util.List; + +@IValueLifecycleHandler.ValueLifecycle(name = "Math") +public class MathLifecycleHandler extends BaseLifecycleHandler { + @Override + public Either instantiate(List args) { + return Either.right(new MathValue()); + } +} diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/ModelTransitionLifecycleHandler.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/ModelTransitionLifecycleHandler.java new file mode 100644 index 000000000..20eaacd27 --- /dev/null +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/ModelTransitionLifecycleHandler.java @@ -0,0 +1,19 @@ +package org.intocps.maestro.interpreter.extensions; + +import com.spencerwi.either.Either; +import org.intocps.maestro.interpreter.api.IValueLifecycleHandler; +import org.intocps.maestro.interpreter.values.StringValue; +import org.intocps.maestro.interpreter.values.Value; +import org.intocps.maestro.interpreter.values.modeltransition.ModelTransitionValue; + +import java.util.List; + +@IValueLifecycleHandler.ValueLifecycle(name = "ModelTransition") +public class ModelTransitionLifecycleHandler extends BaseLifecycleHandler { + + @Override + public Either instantiate(List args) { + String transitionPath = ((StringValue) args.get(0)).getValue(); + return Either.right(new ModelTransitionValue(transitionPath)); + } +} diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/RealTimeLifecycleHandler.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/RealTimeLifecycleHandler.java new file mode 100644 index 000000000..25bd3b99c --- /dev/null +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/RealTimeLifecycleHandler.java @@ -0,0 +1,16 @@ +package org.intocps.maestro.interpreter.extensions; + +import com.spencerwi.either.Either; +import org.intocps.maestro.interpreter.api.IValueLifecycleHandler; +import org.intocps.maestro.interpreter.values.RealTimeValue; +import org.intocps.maestro.interpreter.values.Value; + +import java.util.List; + +@IValueLifecycleHandler.ValueLifecycle(name = "RealTime") +public class RealTimeLifecycleHandler extends BaseLifecycleHandler { + @Override + public Either instantiate(List args) { + return Either.right(new RealTimeValue()); + } +} diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/SimulationControlDefaultLifecycleHandler.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/SimulationControlDefaultLifecycleHandler.java new file mode 100644 index 000000000..2cd7d7e2b --- /dev/null +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/SimulationControlDefaultLifecycleHandler.java @@ -0,0 +1,16 @@ +package org.intocps.maestro.interpreter.extensions; + +import com.spencerwi.either.Either; +import org.intocps.maestro.interpreter.api.IValueLifecycleHandler; +import org.intocps.maestro.interpreter.values.Value; +import org.intocps.maestro.interpreter.values.simulationcontrol.SimulationControlValue; + +import java.util.List; + +@IValueLifecycleHandler.ValueLifecycle(name = "SimulationControl") +public class SimulationControlDefaultLifecycleHandler extends BaseLifecycleHandler { + @Override + public Either instantiate(List args) { + return Either.right(new SimulationControlValue()); + } +} \ No newline at end of file diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/VariableStepLifecycleHandler.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/VariableStepLifecycleHandler.java new file mode 100644 index 000000000..f3bbf9e1a --- /dev/null +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/VariableStepLifecycleHandler.java @@ -0,0 +1,28 @@ +package org.intocps.maestro.interpreter.extensions; + +import com.spencerwi.either.Either; +import org.intocps.maestro.ast.analysis.AnalysisException; +import org.intocps.maestro.interpreter.api.IValueLifecycleHandler; +import org.intocps.maestro.interpreter.values.StringValue; +import org.intocps.maestro.interpreter.values.Value; +import org.intocps.maestro.interpreter.values.variablestep.VariableStepValue; + +import java.util.List; +import java.util.Objects; + +@IValueLifecycleHandler.ValueLifecycle(name = "VariableStep") +public class VariableStepLifecycleHandler extends BaseLifecycleHandler { + @Override + public Either instantiate(List args) { + if (args == null || args.isEmpty()) { + return Either.left(new AnalysisException("No values passed")); + } + + if (args.stream().anyMatch(Objects::isNull)) { + return Either.left(new AnalysisException("Argument list contains null values")); + } + + String config = ((StringValue) args.get(0).deref()).getValue(); + return Either.right(new VariableStepValue(config)); + } +} \ No newline at end of file diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/external/ExternalReflectCallHelper.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/external/ExternalReflectCallHelper.java new file mode 100644 index 000000000..b07937066 --- /dev/null +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/external/ExternalReflectCallHelper.java @@ -0,0 +1,531 @@ +package org.intocps.maestro.interpreter.external; + +import org.apache.commons.lang3.ArrayUtils; +import org.intocps.maestro.ast.AFunctionDeclaration; +import org.intocps.maestro.ast.node.*; +import org.intocps.maestro.interpreter.values.*; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import static org.intocps.maestro.interpreter.Fmi2Interpreter.checkArgLength; +import static org.intocps.maestro.interpreter.Fmi2Interpreter.getArrayValue; + +public class ExternalReflectCallHelper extends Vector { + + + protected final String functionName; + protected final Object object; + protected IArgMapping returnArg = null; + + public ExternalReflectCallHelper(String functionName, Object object) { + this.functionName = functionName; + this.object = object; + } + + public ExternalReflectCallHelper(AFunctionDeclaration functionDeclaration, Object object, Function costumeArgMapper) { + this(functionDeclaration.getName().getText(), object); + autoBuild(functionDeclaration, costumeArgMapper); + } + + public ExternalReflectCallHelper(AFunctionDeclaration functionDeclaration, Object object) { + this(functionDeclaration, object, null); + } + + public static Map.Entry getReverseType(PType t) throws ExceptionUnknownTypeMapping { + + if (t instanceof AArrayType) { + AArrayType at = ((AArrayType) t); + return Map.entry(getReverseType(at.getType()).getKey(), Integer.valueOf(2)); + } + + if (t instanceof AReferenceType) { + return getReverseType(((AReferenceType) t).getType()); + } + + Map, TP> mapping = new HashMap<>() {{ + put(ABooleanPrimitiveType.class, TP.Bool); + put(AByteNumericPrimitiveType.class, TP.Byte); + put(AShortNumericPrimitiveType.class, TP.Short); + put(AIntNumericPrimitiveType.class, TP.Int); + put(AUIntNumericPrimitiveType.class, TP.Long); + put(AFloatNumericPrimitiveType.class, TP.Float); + put(ARealNumericPrimitiveType.class, TP.Real); + put(ALongNumericPrimitiveType.class, TP.Long); + put(AStringPrimitiveType.class, TP.String); + }}; + + var tp = mapping.get(t.getClass()); + if (tp == null) { + throw new ExceptionUnknownTypeMapping("Type mapping unknown for the type: " + t); + } + return Map.entry(tp, 1); + + + } + + public String getSignature(boolean body) { + StringBuilder sb = new StringBuilder(); + sb.append("public "); + if (returnArg != null) { + sb.append(returnArg.getType().getSimpleName()); + } else { + sb.append("void"); + } + sb.append(" "); + sb.append(functionName); + sb.append("("); + // sb.append(stream().map(a -> a.getType().getSimpleName()).collect(Collectors.joining(", "))); + for (int i = 0; i < size(); i++) { + sb.append(get(i).getType().getSimpleName()); + sb.append(" arg" + i); + if (i + 1 < size()) { + sb.append(", "); + } + } + sb.append(")"); + if (body) { + sb.append("{"); + for (int i = 0; i < size(); i++) { + IArgMapping argMapping = get(i); + if (argMapping.getDirection() == ArgMapping.InOut.Output) { + sb.append("arg" + i + "[0] = "); + sb.append(returnArg.getDefaultTestValue()); + sb.append(";"); + } + } + if (returnArg != null) { + + sb.append("return " + returnArg.getDefaultTestValue() + ";"); + + sb.append("}"); + } + } else { + sb.append(";"); + } + return sb.toString(); + } + + @Override + public synchronized String toString() { + StringBuilder sb = new StringBuilder(); + + sb.append(getSignature(false) + "\n"); + + + sb.append(functionName); + sb.append("\n"); + for (int i = 0; i < size(); i++) { + IArgMapping argMapping = get(i); + sb.append(String.format("\t%2d: ", i)); + sb.append(String.format("%-6s", argMapping.getDirection())); + sb.append(" "); + sb.append(String.format("%-8s", argMapping.getDescriptiveName() + IntStream.range(1, argMapping.getDimension()).mapToObj(n -> "[]") + .collect(Collectors.joining()))); + sb.append(" -- "); + sb.append(argMapping.getType().getSimpleName()); + sb.append("\n"); + + } + + if (returnArg != null) { + sb.append("\t *: "); + sb.append(String.format("%-6s", returnArg.getDirection())); + sb.append(" "); + sb.append(String.format("%-8s", + returnArg.getDescriptiveName() + IntStream.range(1, returnArg.getDimension()).mapToObj(n -> "[]").collect(Collectors.joining()))); + sb.append(" -- "); + sb.append(returnArg.getType().getSimpleName()); + sb.append("\n"); + } + + return sb.toString(); + } + + private void autoBuild(AFunctionDeclaration functionDeclaration, Function costumeArgMapper) { + PType returnType = functionDeclaration.getReturnType(); + if (returnType != null && !(returnType instanceof AVoidType)) { + try { + addReturn(getReverseType(returnType).getKey()); + } catch (ExceptionUnknownTypeMapping e) { + IArgMapping ca; + if (costumeArgMapper != null && (ca = costumeArgMapper.apply(returnType)) != null) { + addReturn(ca); + } else { + throw new RuntimeException(e); + } + } + } + + for (AFormalParameter formal : functionDeclaration.getFormals()) { + try { + var tDim = getReverseType(formal.getType()); + addArg(tDim.getKey(), tDim.getValue(), formal.getType() instanceof AReferenceType ? ArgMapping.InOut.Output : ArgMapping.InOut.Input); + } catch (ExceptionUnknownTypeMapping e) { + IArgMapping ca; + if (costumeArgMapper != null && (ca = costumeArgMapper.apply(formal.getType())) != null) { + add(ca); + } else { + throw new RuntimeException(e); + } + } + } + } + + public ExternalReflectCallHelper addReturn(TP type) { + return addReturn(new ArgMapping(type, 1, ArgMapping.InOut.Output, null)); + } + + public ExternalReflectCallHelper addReturn(IArgMapping returnArg) { + this.returnArg = returnArg; + return this; + } + + public ExternalReflectCallHelper addArg(TP type) { + this.add(new ArgMapping(type)); + return this; + } + + public ExternalReflectCallHelper addArg(TP type, int dimiention) { + this.add(new ArgMapping(type, dimiention, ArgMapping.InOut.Input, null)); + return this; + } + + public ExternalReflectCallHelper addArg(TP type, int dimiention, ArgMapping.InOut direction) { + this.add(new ArgMapping(type, dimiention, direction, null)); + return this; + } + + public ExternalReflectCallHelper addArg(TP type, int dimiention, ArgMapping.InOut direction, long... limits) { + this.add(new ArgMapping(type, dimiention, direction, limits)); + return this; + } + + public FunctionValue.ExternalFunctionValue build() throws NoSuchMethodException { + + final List args = Collections.unmodifiableList(this); + final IArgMapping rArg = returnArg; + final Method method = object.getClass().getMethod(functionName, args.stream().map(IArgMapping::getType).toArray(Class[]::new)); + + + return new FunctionValue.ExternalFunctionValue(fcargs -> { + + checkArgLength(fcargs, args.size()); + + //map inputs + var vitr = fcargs.iterator(); + var mitr = args.iterator(); + List argValues = new ArrayList(args.size()); + while (vitr.hasNext() && mitr.hasNext()) { + var v = vitr.next(); + IArgMapping mapper = mitr.next(); + // if (mapper.direction == ArgMapping.InOut.Input) { + argValues.add(mapper.map(v)); + //} + } + + try { + var ret = method.invoke(object, argValues.toArray()); + + //map outputs + vitr = fcargs.iterator(); + var voitr = argValues.iterator(); + mitr = args.iterator(); + while (vitr.hasNext() && voitr.hasNext() && mitr.hasNext()) { + var original = vitr.next(); + var passedValue = voitr.next(); + IArgMapping mapper = mitr.next(); + if (mapper.getDirection() == ArgMapping.InOut.Output) { + mapper.mapOut(original, passedValue); + } + } + + + if (rArg == null) { + return new VoidValue(); + } + return rArg.mapOut(ret); + + + } catch (IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + }); + } + + public static class ExceptionUnknownTypeMapping extends Exception { + public ExceptionUnknownTypeMapping(String message) { + super(message); + } + } + + public static class ArgMapping implements IArgMapping { + + final TP type; + final int dimension; + final long[] limits; + + final InOut direction; + + public ArgMapping(TP type, int dimension, InOut direction, long[] limits) { + this.type = type; + this.dimension = dimension; + this.direction = direction; + this.limits = limits; + } + + public ArgMapping(TP type) { + this(type, 1, InOut.Input, null); + } + + @Override + public int getDimension() { + return dimension; + } + + @Override + public long[] getLimits() { + return limits; + } + + @Override + public InOut getDirection() { + return direction; + } + + @Override + public Object map(Value v) { + //map value to primitive type + if (direction == InOut.Input) { + v = v.deref(); + } + + if (dimension == 1) { + switch (type) { + + case Bool: + return ((BooleanValue) v).getValue(); + case Byte: { + var n = ((NumericValue) v); + return Integer.valueOf(n.intValue()).byteValue(); + } + case Float: { + var n = ((NumericValue) v); + return Integer.valueOf(n.intValue()).floatValue(); + } + case Int: { + var n = ((NumericValue) v); + return n.intValue(); + } + case Long: { + var n = ((NumericValue) v); + return Integer.valueOf(n.intValue()).longValue(); + } + case Real: { + var n = ((NumericValue) v); + return Integer.valueOf(n.intValue()).doubleValue(); + } + case Short: { + var n = ((NumericValue) v); + return Integer.valueOf(n.intValue()).shortValue(); + } + case String: + return ((StringValue) v).getValue(); + } + } else if (dimension == 2) { + Optional limit = limits == null ? Optional.empty() : Optional.of(limits[0]); + switch (type) { + + case Bool: + return ArrayUtils.toPrimitive( + getArrayValue(v, limit, BooleanValue.class).stream().map(BooleanValue::getValue).collect(Collectors.toList()) + .toArray(new Boolean[]{})); + case Byte: + //todo change native type to use int as byte us unsigned + return ArrayUtils.toPrimitive( + getArrayValue(v, limit, NumericValue.class).stream().map(NumericValue::intValue).map(vb -> vb & 0x00ff) + .map(Integer::byteValue).collect(Collectors.toList()).toArray(new Byte[]{})); + case Float: + return ArrayUtils.toPrimitive( + getArrayValue(v, limit, NumericValue.class).stream().map(NumericValue::floatValue).collect(Collectors.toList()) + .toArray(new Float[]{})); + case Int: + return ArrayUtils.toPrimitive( + getArrayValue(v, limit, NumericValue.class).stream().map(NumericValue::intValue).collect(Collectors.toList()) + .toArray(new Integer[]{})); + case Long: + return ArrayUtils.toPrimitive( + getArrayValue(v, limit, NumericValue.class).stream().map(NumericValue::longValue).collect(Collectors.toList()) + .toArray(new Long[]{})); + case Real: + return getArrayValue(v, limit, NumericValue.class).stream().mapToDouble(NumericValue::realValue).toArray(); + case Short: + return ArrayUtils.toPrimitive( + getArrayValue(v, limit, NumericValue.class).stream().map(NumericValue::intValue).map(Integer::shortValue) + .collect(Collectors.toList()).toArray(new Short[]{})); + case String: + return getArrayValue(v, limit, StringValue.class).stream().map(StringValue::getValue).collect(Collectors.toList()) + .toArray(new String[]{}); + } + } + return null; + } + + @Override + public void mapOut(Value original, Object value) { + //TODO write back the value into the original value + UpdatableValue ref = (UpdatableValue) original; + + List values = null; + if (dimension == 2) { + long elementsToUse = limits == null ? Long.MAX_VALUE : limits[0]; + switch (type) { + + case Bool: + values = Arrays.stream(ArrayUtils.toObject((boolean[]) (value.getClass().isArray() ? value : new boolean[]{(boolean) value}))) + .limit(elementsToUse).map(BooleanValue::new).collect(Collectors.toList()); + break; + case Byte: + values = Arrays.stream(ArrayUtils.toObject((byte[]) (value.getClass().isArray() ?value: new byte[]{(byte) value}))).limit(elementsToUse).map(ByteValue::new) + .collect(Collectors.toList()); + break; + case Float: + values = Arrays.stream(ArrayUtils.toObject((float[])(value.getClass().isArray() ? value: new float[]{(float) value}))).limit(elementsToUse).map(FloatValue::new) + .collect(Collectors.toList()); + break; + case Int: + values = Arrays.stream(ArrayUtils.toObject((int[])(value.getClass().isArray() ? value: new int[]{(int) value}))).limit(elementsToUse).map(IntegerValue::new) + .collect(Collectors.toList()); + break; + case Long: + values = Arrays.stream(ArrayUtils.toObject((long[])(value.getClass().isArray() ? value: new long[]{(long) value}))).limit(elementsToUse).map(LongValue::new) + .collect(Collectors.toList()); + break; + case Real: + values = Arrays.stream(ArrayUtils.toObject((double[])(value.getClass().isArray() ? value: new double[]{(double) value}))).limit(elementsToUse).map(RealValue::new) + .collect(Collectors.toList()); + break; + case Short: + values = Arrays.stream(ArrayUtils.toObject((short[])(value.getClass().isArray() ? value: new short[]{(short) value}))).limit(elementsToUse).map(ShortValue::new) + .collect(Collectors.toList()); + break; + case String: + values = Arrays.stream((String[])(value.getClass().isArray() ? value: new String[]{(String) value})).limit(elementsToUse).map(StringValue::new).collect(Collectors.toList()); + break; + } + ref.setValue(new ArrayValue<>(values)); + } + + } + + @Override + public Value mapOut(Object value) { + //todo create value from value + switch (type) { + + case Bool: + return new BooleanValue((Boolean) value); + case Byte: + return new ByteValue((Integer) value); + case Float: + return new FloatValue((Float) value); + case Int: + return new IntegerValue((Integer) value); + case Long: + return new LongValue((Long) value); + case Real: + return new RealValue((Double) value); + case Short: + return new ShortValue((Short) value); + case String: + return new StringValue((String) value); + } + throw new IllegalArgumentException("No mapping for value:" + value); + } + + @Override + public Class getType() { + //reflect search type + if (dimension == 1) { + switch (type) { + + case Bool: + return boolean.class; + case Byte: + return byte.class; + case Float: + return float.class; + case Int: + return int.class; + case Long: + return long.class; + case Real: + return double.class; + case Short: + return short.class; + case String: + return String.class; + } + } else if (dimension == 2) { + switch (type) { + + case Bool: + return boolean[].class; + case Byte: + return byte[].class; + case Float: + return float[].class; + case Int: + return int[].class; + case Long: + return long[].class; + case Real: + return double[].class; + case Short: + return short[].class; + case String: + return String[].class; + } + } + + throw new IllegalArgumentException("dimension not supported: " + dimension + " for type " + type); + } + + @Override + public String getDescriptiveName() { + return type.toString(); + } + + @Override + public String getDefaultTestValue() { + switch (type) { + + case Bool: + return ("true"); + case Byte: + case Int: + case Long: + + case Short: + return ("1"); + case Float: + case Real: + return ("1.1"); + + case String: + return ("hi"); + } + return ""; + } + + public enum InOut { + Input, + Output, + OutputThroughReturn + } + } +} \ No newline at end of file diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/external/ExternalReflectModuleHelper.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/external/ExternalReflectModuleHelper.java new file mode 100644 index 000000000..2b74b0e09 --- /dev/null +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/external/ExternalReflectModuleHelper.java @@ -0,0 +1,99 @@ +package org.intocps.maestro.interpreter.external; + +import org.intocps.maestro.ast.AFunctionDeclaration; +import org.intocps.maestro.ast.AModuleDeclaration; +import org.intocps.maestro.ast.node.ANameType; +import org.intocps.maestro.ast.node.PType; +import org.intocps.maestro.interpreter.values.ExternalModuleValue; +import org.intocps.maestro.interpreter.values.Value; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.Function; +import java.util.function.Predicate; + +public class ExternalReflectModuleHelper { + + public static Map createMembers(AModuleDeclaration module, Object target, + Predicate functionFilter) throws NoSuchMethodException { + + if (target == null) { + throw new IllegalArgumentException("Target must not be null"); + } + + Function costumeArgMapper = t -> { + if (t instanceof ANameType) { + if (((ANameType) t).getName().getText().equals("FMI3Instance")) { + return new IArgMapping() { + @Override + public int getDimension() { + return 1; + } + + @Override + public long[] getLimits() { + return null; + } + + @Override + public ExternalReflectCallHelper.ArgMapping.InOut getDirection() { + return ExternalReflectCallHelper.ArgMapping.InOut.Input; + } + + @Override + public Object map(Value v) { + if (v instanceof ExternalModuleValue) { + return ((ExternalModuleValue) v).getModule(); + } + return null; + } + + @Override + public void mapOut(Value original, Object value) { + throw new RuntimeException("This is only for input so should not be called"); + } + + @Override + public Value mapOut(Object value) { + return new ExternalModuleValue<>(null, value) { + }; + } + + @Override + public Class getType() { + return Object.class; + } + + @Override + public String getDescriptiveName() { + return "FMI3Instance"; + } + + @Override + public String getDefaultTestValue() { + return "null"; + } + }; + } + } + return null; + }; + Map members = new HashMap<>(); + for (AFunctionDeclaration function : module.getFunctions()) { + if (functionFilter == null || functionFilter.test(function)) { + members.put(function.getName().getText(), new ExternalReflectCallHelper(function, target, costumeArgMapper).build()); + } + } + return members; + } + + public static ExternalModuleValue createExternalModule(AModuleDeclaration module, Object target, + Predicate functionFilter) throws NoSuchMethodException { + return new ExternalModuleValue(createMembers(module, target, functionFilter), target) { + @Override + public Object getModule() { + return target; + } + }; + } +} diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/external/IArgMapping.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/external/IArgMapping.java new file mode 100644 index 000000000..17e66e49c --- /dev/null +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/external/IArgMapping.java @@ -0,0 +1,23 @@ +package org.intocps.maestro.interpreter.external; + +import org.intocps.maestro.interpreter.values.Value; + +public interface IArgMapping { + int getDimension(); + + long[] getLimits(); + + ExternalReflectCallHelper.ArgMapping.InOut getDirection(); + + Object map(Value v); + + void mapOut(Value original, Object value); + + Value mapOut(Object value); + + Class getType(); + + String getDescriptiveName(); + + String getDefaultTestValue(); +} diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/external/TP.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/external/TP.java new file mode 100644 index 000000000..f91c93968 --- /dev/null +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/external/TP.java @@ -0,0 +1,13 @@ +package org.intocps.maestro.interpreter.external; + +public enum TP { + Bool, + Byte, + Float, + Int, + Long, + Real, + Short, + String, + +} diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/ArrayValue.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/ArrayValue.java index 54de0b260..d6e11ad5e 100644 --- a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/ArrayValue.java +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/ArrayValue.java @@ -1,6 +1,7 @@ package org.intocps.maestro.interpreter.values; import java.util.List; +import java.util.stream.Collectors; public class ArrayValue extends Value { final List values; @@ -12,4 +13,9 @@ public ArrayValue(List values) { public List getValues() { return values; } + + @Override + public String toString() { + return values.stream().map(Object::toString).collect(Collectors.joining(",", "[", "]")); + } } diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/BooleanValue.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/BooleanValue.java index 84e17b059..e89f43957 100644 --- a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/BooleanValue.java +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/BooleanValue.java @@ -13,7 +13,7 @@ public Boolean getValue() { @Override public String toString() { - return "BooleanValue{" + "value=" + value + '}'; + return "" + value; } @Override diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/ByteValue.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/ByteValue.java index 1736b9bbe..f1a260131 100644 --- a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/ByteValue.java +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/ByteValue.java @@ -1,19 +1,19 @@ package org.intocps.maestro.interpreter.values; public class ByteValue extends NumericValue { - final byte value; + final int value; - public ByteValue(byte value) { + public ByteValue(int value) { this.value = value; } - public byte getValue() { + public int getValue() { return value; } @Override public String toString() { - return "ByteValue{" + "value=" + value + '}'; + return "" + value; } @Override @@ -31,13 +31,23 @@ public double realValue() { return value; } + @Override + public double doubleValue() { + return value; + } + + @Override + public float floatValue() { + return value; + } + @Override public int compareTo(Value other) { other = other.deref(); if (other instanceof ByteValue) { ByteValue io = (ByteValue) other; - return Byte.compare(value, io.value); + return (value < io.value ? -1 : (value == io.value ? 0 : 1)); } else if (other instanceof IntegerValue) { IntegerValue io = (IntegerValue) other; return (value < io.value ? -1 : (value == io.value ? 0 : 1)); diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/ConsolePrinterValue.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/ConsolePrinterValue.java index 8fd7bb12d..9402a7e44 100644 --- a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/ConsolePrinterValue.java +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/ConsolePrinterValue.java @@ -16,23 +16,21 @@ public ConsolePrinterValue() { private static Object[] getValues(List values) { return values.stream().map(Value::deref).map(v -> { - if (v instanceof IntegerValue) { - return ((IntegerValue) v).intValue(); - } - if (v instanceof BooleanValue) { + if (v instanceof RealValue || v instanceof FloatValue) { + return ((NumericValue) v).realValue(); + } else if (v instanceof UnsignedIntegerValue) { + return ((UnsignedIntegerValue) v).getValue(); + } else if (v instanceof BooleanValue) { return ((BooleanValue) v).getValue(); - } - if (v instanceof RealValue) { - return ((RealValue) v).getValue(); - } - if (v instanceof StringValue) { + } else if (v instanceof LongValue) { + return ((LongValue) v).getValue(); + } else if (v instanceof IntegerValue || v instanceof ByteValue || v instanceof ShortValue) { + return ((NumericValue) v).intValue(); + } else if (v instanceof StringValue) { return ((StringValue) v).getValue(); + } else { + return v.toString(); } - if (v instanceof UnsignedIntegerValue) { - return ((UnsignedIntegerValue) v).getValue(); - } - - return v.toString(); }).toArray(); } @@ -42,16 +40,16 @@ private static Map createMembers() { componentMembers.put("print", new FunctionValue.ExternalFunctionValue(fcargs -> { checkArgs(fcargs); - String formattedMsg = - String.format(((StringValue) fcargs.get(0).deref()).getValue(), getValues(fcargs.stream().skip(1).collect(Collectors.toList()))); + String formattedMsg = String.format(((StringValue) fcargs.get(0).deref()).getValue(), + getValues(fcargs.stream().skip(1).collect(Collectors.toList()))); System.out.print(formattedMsg); return new VoidValue(); })); componentMembers.put("println", new FunctionValue.ExternalFunctionValue(fcargs -> { checkArgs(fcargs); - String formattedMsg = - String.format(((StringValue) fcargs.get(0).deref()).getValue(), getValues(fcargs.stream().skip(1).collect(Collectors.toList()))); + String formattedMsg = String.format(((StringValue) fcargs.get(0).deref()).getValue(), + getValues(fcargs.stream().skip(1).collect(Collectors.toList()))); System.out.println(formattedMsg); return new VoidValue(); })); diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/EnumerationValue.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/EnumerationValue.java index 287298343..4c3d37afe 100644 --- a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/EnumerationValue.java +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/EnumerationValue.java @@ -2,6 +2,7 @@ public class EnumerationValue extends Value { + //TODO is this right? final Enum value; public EnumerationValue(Enum value) { @@ -22,4 +23,10 @@ public int compareTo(Value other) { return super.compareTo(other); } + + @Override + public String toString() { + return value.toString(); + } + } \ No newline at end of file diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/FloatValue.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/FloatValue.java index 1c6ff27d1..1fdcde66c 100644 --- a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/FloatValue.java +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/FloatValue.java @@ -15,7 +15,7 @@ public float getValue() { @Override public String toString() { - return "FloatValue{" + "value=" + value + '}'; + return "" + value; } @Override @@ -49,6 +49,16 @@ public double realValue() { return value; } + @Override + public double doubleValue() { + return value; + } + + @Override + public float floatValue() { + return value; + } + @Override public int compareTo(Value value) { @@ -65,4 +75,10 @@ public int compareTo(Value value) { return super.compareTo(value); } + + @Override + public boolean isNumericDecimal() { + return true; + } + } diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/IntegerValue.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/IntegerValue.java index 4821d5f16..fe5f32991 100644 --- a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/IntegerValue.java +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/IntegerValue.java @@ -13,7 +13,7 @@ public int getValue() { @Override public String toString() { - return "IntegerValue{" + "value=" + value + '}'; + return "" + value; } @Override @@ -31,13 +31,23 @@ public double realValue() { return value; } + @Override + public double doubleValue() { + return value; + } + + @Override + public float floatValue() { + return value; + } + @Override public int compareTo(Value other) { other = other.deref(); - if (other instanceof IntegerValue) { - IntegerValue io = (IntegerValue) other; - return (value < io.value ? -1 : (value == io.value ? 0 : 1)); + if (other instanceof IntegerValue || other instanceof ByteValue || other instanceof ShortValue) { + NumericValue io = (NumericValue) other; + return (value < io.intValue() ? -1 : (value == io.intValue() ? 0 : 1)); } return super.compareTo(other); diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/LoggerValue.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/LoggerValue.java index f78963e94..bb2cbaa4c 100644 --- a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/LoggerValue.java +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/LoggerValue.java @@ -21,16 +21,11 @@ public LoggerValue() { static Object[] getValues(List values) { return values.stream().map(Value::deref).map(v -> { - if (v instanceof IntegerValue) { - return ((IntegerValue) v).intValue(); - } - if (v instanceof BooleanValue) { - return ((BooleanValue) v).getValue(); - } - if (v instanceof RealValue) { - return ((RealValue) v).getValue(); - } - if (v instanceof StringValue) { + if (v.isNumericDecimal()) { + return ((NumericValue) v).doubleValue(); + } else if (v.isNumeric()) { + return ((NumericValue) v).intValue(); + } else if (v instanceof StringValue) { return ((StringValue) v).getValue(); } @@ -56,7 +51,7 @@ static Map createMembers() { throw new InterpreterException("Too few arguments"); } - IntegerValue level = (IntegerValue) fcargs.get(0).deref(); + NumericValue level = (NumericValue) fcargs.get(0).deref(); StringValue msg = (StringValue) fcargs.get(1).deref(); @@ -64,18 +59,25 @@ static Map createMembers() { String logMsg = String.format(msg.getValue(), getValues(fcargs.stream().skip(2).collect(Collectors.toList()))); - if (level.getValue() == 0) { - logger.trace(logMsg); - } else if (level.getValue() == 1) { - logger.debug(logMsg); - } else if (level.intValue() == 2) { - logger.info(logMsg); - } else if (level.intValue() == 3) { - logger.warn(logMsg); - } else if (level.getValue() == 4) { - logger.error(logMsg); + switch (level.intValue()) { + case 0: + logger.trace(logMsg); + break; + case 1: + logger.debug(logMsg); + break; + case 2: + logger.info(logMsg); + break; + case 3: + logger.warn(logMsg); + break; + case 4: + logger.error(logMsg); + break; } + return new VoidValue(); })); return componentMembers; diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/LongValue.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/LongValue.java index 3b12babb7..a33cc2418 100644 --- a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/LongValue.java +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/LongValue.java @@ -13,7 +13,7 @@ public long getValue() { @Override public String toString() { - return "LongValue{" + "value=" + value + '}'; + return "" + value; } @Override @@ -31,6 +31,16 @@ public double realValue() { return value; } + @Override + public double doubleValue() { + return value; + } + + @Override + public float floatValue() { + return value; + } + @Override public int compareTo(Value other) { other = other.deref(); diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/MathValue.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/MathValue.java index 9432eb57a..eae125899 100644 --- a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/MathValue.java +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/MathValue.java @@ -2,7 +2,6 @@ import org.intocps.maestro.interpreter.InterpreterException; import org.intocps.maestro.interpreter.ValueExtractionUtilities; -import org.intocps.maestro.interpreter.values.fmi.FmuValue; import java.util.HashMap; import java.util.List; @@ -16,10 +15,10 @@ public MathValue() { private static Map createMembers() { Map componentMembers = new HashMap<>(); componentMembers.put("isClose", new FunctionValue.ExternalFunctionValue(fcArgs -> { - double a = ((RealValue) fcArgs.get(0).deref()).realValue(); - double b = ((RealValue) fcArgs.get(1).deref()).realValue(); - double absoluteTolerance = ((RealValue) fcArgs.get(2).deref()).realValue(); - double relativeTolerance = ((RealValue) fcArgs.get(3).deref()).realValue(); + double a = ((NumericValue) fcArgs.get(0).deref()).realValue(); + double b = ((NumericValue) fcArgs.get(1).deref()).realValue(); + double absoluteTolerance = ((NumericValue) fcArgs.get(2).deref()).realValue(); + double relativeTolerance = ((NumericValue) fcArgs.get(3).deref()).realValue(); return new BooleanValue(Math.abs(a - b) <= (absoluteTolerance + relativeTolerance * Math.abs(b))); })); diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/NumericValue.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/NumericValue.java index d6741a2b7..62935ec7d 100644 --- a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/NumericValue.java +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/NumericValue.java @@ -2,10 +2,96 @@ public abstract class NumericValue extends Value { + + public static NumericValue valueOf(byte value) { + return new ByteValue(value); + } + + public static NumericValue valueOf(short value) { + if (value <= 0xff) { + return valueOf(Integer.valueOf(value).byteValue()); + } else { + return new ShortValue(Integer.valueOf(value).shortValue()); + } + } + + public static NumericValue valueOf(int value) { + if (value <= 0xff) { + return valueOf(Integer.valueOf(value).byteValue()); + } else if (value <= Short.MAX_VALUE) { + return new ShortValue(Integer.valueOf(value).shortValue()); + } else { + return new IntegerValue(value); + } + } + + public static NumericValue valueOf(long value) { + if (value <= Integer.MAX_VALUE) { + return valueOf((int) value); + } else { + return new LongValue(value); + } + } + + public static NumericValue valueOf(float value) { + if ((value % 1) == 0) { + //whole number + return valueOf((long) value); + } else { + return new FloatValue(Double.valueOf(value).floatValue()); + } + } + + public static NumericValue valueOf(double value) { + if ((value % 1) == 0) { + //whole number + return valueOf((long) value); + } + //We dont make a float as it results in precision loss so we prefer double + // else if (value <= Float.MAX_VALUE) { + // return new FloatValue(Double.valueOf(value).floatValue()); + // } + else { + return new RealValue(value); + } + } + + + public > NumericValue upCast(T targetType) { + + if (targetType.isAssignableFrom(this.getClass())) { + return this; + } else if (targetType == UnsignedIntegerValue.class) { + return new UnsignedIntegerValue(this.longValue()); + } else if (targetType == IntegerValue.class) { + return new IntegerValue(this.intValue()); + } else if (targetType == ShortValue.class) { + return new ShortValue(Integer.valueOf(this.intValue()).shortValue()); + } else if (targetType == LongValue.class) { + return new LongValue(this.longValue()); + } else if (targetType == FloatValue.class) { + return new FloatValue(new Double(this.realValue()).floatValue()); + } else if (targetType == RealValue.class) { + return new RealValue(this.realValue()); + } + + + return null; + + } + abstract public long longValue(); abstract public int intValue(); abstract public double realValue(); + abstract public double doubleValue(); + + abstract public float floatValue(); + + @Override + public boolean isNumeric() { + return true; + } } diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/RealTimeValue.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/RealTimeValue.java index fadf51ee4..f24436fa4 100644 --- a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/RealTimeValue.java +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/RealTimeValue.java @@ -10,7 +10,7 @@ public RealTimeValue() { super(createMembers()); } - private static Map createMembers(){ + private static Map createMembers() { Map componentMembers = new HashMap<>(); componentMembers.put("getRealTime", new FunctionValue.ExternalFunctionValue(fcArgs -> { long sysTime = System.currentTimeMillis(); @@ -18,17 +18,15 @@ private static Map createMembers(){ })); componentMembers.put("sleep", new FunctionValue.ExternalFunctionValue(args -> { long sleepTime; - if(args.get(0).deref() instanceof RealValue){ - sleepTime = (long)((RealValue) args.get(0).deref()).getValue(); - } - else if(args.get(0).deref() instanceof IntegerValue){ + if (args.get(0).deref() instanceof RealValue) { + sleepTime = (long) ((RealValue) args.get(0).deref()).getValue(); + } else if (args.get(0).deref() instanceof IntegerValue) { sleepTime = ((IntegerValue) args.get(0).deref()).getValue(); - } - else{ + } else { throw new InterpreterException("Sleep time is not a valid value."); } - if(sleepTime < 0){ + if (sleepTime < 0) { throw new InterpreterException("Sleep time cannot be a negative number."); } diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/RealValue.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/RealValue.java index d2a43ee8f..fd32e90d7 100644 --- a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/RealValue.java +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/RealValue.java @@ -15,7 +15,7 @@ public double getValue() { @Override public String toString() { - return "RealValue{" + "value=" + value + '}'; + return "" + value; } @Override @@ -49,6 +49,16 @@ public double realValue() { return value; } + @Override + public double doubleValue() { + return value; + } + + @Override + public float floatValue() { + return (float) value; + } + @Override public int compareTo(Value value) { @@ -58,11 +68,17 @@ public int compareTo(Value value) { RealValue ro = (RealValue) other; return (int) Math.round(Math.signum(this.value - ro.getValue())); - } else if (other instanceof IntegerValue) { - IntegerValue ro = (IntegerValue) other; - return (int) Math.round(Math.signum(this.value - ro.getValue())); + } else if (other instanceof NumericValue) { + NumericValue ro = (NumericValue) other; + return (int) Math.round(Math.signum(this.value - ro.intValue())); } return super.compareTo(value); } + + @Override + public boolean isNumericDecimal() { + return true; + } + } diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/ShortValue.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/ShortValue.java index 0bf61a1d4..18bd2b5f8 100644 --- a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/ShortValue.java +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/ShortValue.java @@ -13,7 +13,7 @@ public short getValue() { @Override public String toString() { - return "ShortValue{" + "value=" + value + '}'; + return "" + value; } @Override @@ -31,6 +31,16 @@ public double realValue() { return value; } + @Override + public double doubleValue() { + return value; + } + + @Override + public float floatValue() { + return value; + } + @Override public int compareTo(Value other) { other = other.deref(); diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/StringValue.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/StringValue.java index 6fb236280..e60a6e721 100644 --- a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/StringValue.java +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/StringValue.java @@ -22,4 +22,10 @@ public int compareTo(Value other) { return super.compareTo(other); } + + @Override + public String toString() { + return "\"" + value + "\""; + } + } diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/UndefinedValue.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/UndefinedValue.java index 2fffcb786..ce4dbf4cc 100644 --- a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/UndefinedValue.java +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/UndefinedValue.java @@ -1,6 +1,13 @@ package org.intocps.maestro.interpreter.values; public class UndefinedValue extends Value { + public UndefinedValue() { } + + @Override + public String toString() { + return "undefined"; + } + } diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/UnsignedIntegerValue.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/UnsignedIntegerValue.java index 8217fbdd8..f9228f587 100644 --- a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/UnsignedIntegerValue.java +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/UnsignedIntegerValue.java @@ -13,7 +13,7 @@ public long getValue() { @Override public String toString() { - return "IntegerValue{" + "value=" + value + '}'; + return "" + value; } @Override @@ -31,6 +31,16 @@ public double realValue() { return value; } + @Override + public double doubleValue() { + return value; + } + + @Override + public float floatValue() { + return value; + } + @Override public int compareTo(Value other) { other = other.deref(); diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/UpdatableValue.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/UpdatableValue.java index 43ca2f4bf..93873b7bb 100644 --- a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/UpdatableValue.java +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/UpdatableValue.java @@ -29,4 +29,15 @@ public void setValue(Value newValue) { this.value = newValue; } } + + @Override + public String toString() { + return "" + deref(); + } + + @Override + public boolean isUpdatable() { + return true; + } + } diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/Value.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/Value.java index 2195b0b5b..fa6abf58d 100644 --- a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/Value.java +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/Value.java @@ -7,6 +7,10 @@ public abstract class Value { + public T as(Class type) { + return type.cast(this); + } + public static void checkArgLength(List values, int size) { if (values == null) { throw new InterpreterException("No values passed"); @@ -32,4 +36,20 @@ public int compareTo(Value value) { public Value deref() { return this; } + + public boolean isNumeric() { + return false; + } + + public boolean isNumericDecimal() { + return false; + } + + public boolean isUpdatable() { + return false; + } + + // public abstract PType getType(); + + // public abstract Value cast(Value targetType) } diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/csv/CsvDataWriter.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/csv/CsvDataWriter.java index 68e717714..fad913799 100644 --- a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/csv/CsvDataWriter.java +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/csv/CsvDataWriter.java @@ -1,7 +1,10 @@ package org.intocps.maestro.interpreter.values.csv; import org.intocps.maestro.interpreter.InterpreterException; -import org.intocps.maestro.interpreter.values.*; +import org.intocps.maestro.interpreter.values.BooleanValue; +import org.intocps.maestro.interpreter.values.NumericValue; +import org.intocps.maestro.interpreter.values.StringValue; +import org.intocps.maestro.interpreter.values.Value; import org.intocps.maestro.interpreter.values.datawriter.DataFileRotater; import org.intocps.maestro.interpreter.values.datawriter.IDataListener; @@ -54,10 +57,10 @@ public void writeDataPoint(UUID uuid, double time, List dataPoint) { Value d = dataPoint.get(i).deref(); Object value = null; - if (d instanceof IntegerValue) { - value = ((IntegerValue) d).getValue(); - } else if (d instanceof RealValue) { - value = ((RealValue) d).getValue(); + if (d.isNumericDecimal()) { + value = ((NumericValue) d).doubleValue(); + } else if (d.isNumeric()) { + value = ((NumericValue) d).intValue(); } else if (d instanceof BooleanValue) { value = ((BooleanValue) d).getValue(); } else if (d instanceof StringValue) { diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/datawriter/DataWriterValue.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/datawriter/DataWriterValue.java index 86019ed42..1d061dc9d 100644 --- a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/datawriter/DataWriterValue.java +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/datawriter/DataWriterValue.java @@ -65,7 +65,7 @@ private static Map createMembers(List IDataListene Value id = fcargs.get(0).deref(); if (id instanceof DataWriterConfigValue) { - double time = ((RealValue) fcargs.get(1).deref()).getValue(); + double time = ((NumericValue) fcargs.get(1).deref()).realValue(); List arrayValue = fcargs.stream().skip(2).map(Value::deref).collect(Collectors.toList()); IDataListeners.forEach(dataListener -> dataListener.writeDataPoint(((DataWriterConfigValue) id).getUuid(), time, arrayValue)); } diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/fmi/Fmu3InstanceValue.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/fmi/Fmu3InstanceValue.java new file mode 100644 index 000000000..1e21d928d --- /dev/null +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/fmi/Fmu3InstanceValue.java @@ -0,0 +1,21 @@ +package org.intocps.maestro.interpreter.values.fmi; + +import org.intocps.fmi.jnifmuapi.fmi3.IFmi3Instance; +import org.intocps.maestro.interpreter.values.ExternalModuleValue; +import org.intocps.maestro.interpreter.values.Value; + +import java.io.OutputStream; +import java.util.Map; + +public class Fmu3InstanceValue extends ExternalModuleValue { + final OutputStream fmuLoggerOutputStream; + + public Fmu3InstanceValue(Map members, IFmi3Instance module, OutputStream fmuLoggerOutputStream) { + super(members, module); + this.fmuLoggerOutputStream = fmuLoggerOutputStream; + } + + public OutputStream getFmuLoggerOutputStream() { + return fmuLoggerOutputStream; + } +} diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/fmi/Fmu3StateValue.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/fmi/Fmu3StateValue.java new file mode 100644 index 000000000..cc348ecec --- /dev/null +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/fmi/Fmu3StateValue.java @@ -0,0 +1,14 @@ +package org.intocps.maestro.interpreter.values.fmi; + +import org.intocps.fmi.jnifmuapi.fmi3.Fmi3State; +import org.intocps.maestro.interpreter.values.ExternalModuleValue; + +import java.util.HashMap; + +public class Fmu3StateValue extends ExternalModuleValue { + + + public Fmu3StateValue(Fmi3State module) { + super(new HashMap<>(), module); + } +} diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/utilities/ArrayUtilValue.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/utilities/ArrayUtilValue.java index fef45886e..abbe7a3d8 100644 --- a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/utilities/ArrayUtilValue.java +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/utilities/ArrayUtilValue.java @@ -61,15 +61,15 @@ private static Map createMembers() { List from = getArrayValue(fcargs.get(0), RealValue.class); - int fromIndex = ((IntegerValue) fcargs.get(1).deref()).getValue(); - int fromCount = ((IntegerValue) fcargs.get(2).deref()).getValue(); + int fromIndex = ((NumericValue) fcargs.get(1).deref()).intValue(); + int fromCount = ((NumericValue) fcargs.get(2).deref()).intValue(); UpdatableValue to = (UpdatableValue) fcargs.get(3); - int toStartIndex = ((IntegerValue) fcargs.get(4).deref()).getValue(); + int toStartIndex = ((NumericValue) fcargs.get(4).deref()).intValue(); - ArrayValue toSource = (ArrayValue) to.deref(); + ArrayValue toSource = (ArrayValue) to.deref(); - RealValue[] values = new RealValue[toSource.getValues().size()]; + NumericValue[] values = new NumericValue[toSource.getValues().size()]; for (int i = 0; i < fromCount; i++) { values[toStartIndex + i] = from.get(i + fromIndex); } @@ -82,7 +82,7 @@ private static Map createMembers() { } - ArrayValue newValue = new ArrayValue<>(Arrays.asList(values)); + ArrayValue newValue = new ArrayValue<>(Arrays.asList(values)); to.setValue(newValue); diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/variablestep/VariableStepConfigValue.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/variablestep/VariableStepConfigValue.java index beacfbc1c..e92b36147 100644 --- a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/variablestep/VariableStepConfigValue.java +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/variablestep/VariableStepConfigValue.java @@ -1,11 +1,11 @@ package org.intocps.maestro.interpreter.values.variablestep; +import org.intocps.maestro.fmi.Fmi2ModelDescription; import org.intocps.maestro.fmi.FmiSimulationInstance; import org.intocps.maestro.framework.fmi2.ModelConnection; import org.intocps.maestro.interpreter.InterpreterException; import org.intocps.maestro.interpreter.values.*; import org.intocps.maestro.interpreter.values.derivativeestimator.ScalarDerivativeEstimator; -import org.intocps.maestro.fmi.Fmi2ModelDescription; import java.util.*; import java.util.stream.Collectors; @@ -14,14 +14,14 @@ public class VariableStepConfigValue extends Value { private final Map instances; + private final Double maxStepSize; + private final StepsizeCalculator stepsizeCalculator; + private final Map derivativeEstimators; private List portNames; private List dataPoints; private Double currTime = 0.0; private Double stepSize = 0.0; - private final Double maxStepSize; private StepValidationResult stepValidationResult; - private final StepsizeCalculator stepsizeCalculator; - private final Map derivativeEstimators; public VariableStepConfigValue(Map instances, Set constraints, StepsizeInterval stepsizeInterval, Double initSize, @@ -44,7 +44,7 @@ public void addDataPoint(Double time, List portValues) { dataPoints = convertValuesToDataPoint(portValues); } - public void addDerivatives(List> derivatives, double time) { + public void addDerivatives(List> derivatives, double time) { if (derivatives.size() != dataPoints.size()) { throw new InterpreterException("The size of the derivatives array should be match the size of the data points array"); } @@ -56,10 +56,10 @@ public void addDerivatives(List> derivatives, double time) { } for (int i = 0; i < dataPoints.size(); i++) { - List ders = derivatives.get(i); + List ders = derivatives.get(i); if (!ders.isEmpty()) { StepVal dataPoint = dataPoints.get(i); - dataPoint.ders = ders.stream().map(RealValue::getValue).collect(Collectors.toList()); + dataPoint.ders = ders.stream().map(NumericValue::realValue).collect(Collectors.toList()); } } } @@ -71,18 +71,18 @@ public double getStepSize() { Map> derivatives = new HashMap<>(); Map portValues = new HashMap<>(); fsi.config.scalarVariables.forEach( - sv -> (dataPoints.stream().filter(dp -> (dp.getName().contains((mi.key + "." + mi.instanceName + "." + sv.name)))).findFirst()) - .ifPresent(val -> { - if (!val.ders.isEmpty()) { - derivatives.putIfAbsent(sv, IntStream.range(0, val.ders.size()).boxed() - .collect(Collectors.toMap((i) -> i + 1, (i) -> val.ders.get(i)))); - } else { - ScalarDerivativeEstimator derEst = derivativeEstimators.get(sv); - derEst.advance(new Double[]{(Double) val.getValue(), null, null}, stepSize); - derivatives.putIfAbsent(sv, Map.of(1, derEst.getFirstDerivative(), 2, derEst.getSecondDerivative())); - } - portValues.putIfAbsent(sv, val.getValue()); - })); + sv -> (dataPoints.stream().filter(dp -> (dp.getName().contains((mi.key + "." + mi.instanceName + "." + sv.name)))) + .findFirst()).ifPresent(val -> { + if (!val.ders.isEmpty()) { + derivatives.putIfAbsent(sv, + IntStream.range(0, val.ders.size()).boxed().collect(Collectors.toMap((i) -> i + 1, (i) -> val.ders.get(i)))); + } else { + ScalarDerivativeEstimator derEst = derivativeEstimators.get(sv); + derEst.advance(new Double[]{(Double) val.getValue(), null, null}, stepSize); + derivatives.putIfAbsent(sv, Map.of(1, derEst.getFirstDerivative(), 2, derEst.getSecondDerivative())); + } + portValues.putIfAbsent(sv, val.getValue()); + })); currentDerivatives.put(mi, derivatives); currentPortValues.put(mi, portValues); }); @@ -146,12 +146,12 @@ private Map { Map portValues = new HashMap<>(); fsi.config.scalarVariables.forEach( - sv -> (dataPointsToMap.stream().filter(dp -> (dp.getName().equals((mi.key + "." + mi.instanceName + "." + sv.name)))).findFirst()) - .ifPresent(val -> { - // if key not absent something is wrong? - portValues.putIfAbsent(sv, val.getValue()); + sv -> (dataPointsToMap.stream().filter(dp -> (dp.getName().equals((mi.key + "." + mi.instanceName + "." + sv.name)))) + .findFirst()).ifPresent(val -> { + // if key not absent something is wrong? + portValues.putIfAbsent(sv, val.getValue()); - })); + })); values.put(mi, portValues); }); return values; @@ -180,14 +180,14 @@ public String getName() { return name; } - public Object getValue() { - return value; - } - public void setName(String name) { this.name = name; } + public Object getValue() { + return value; + } + public void setValue(Object value) { this.value = value; } diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/variablestep/VariableStepValue.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/variablestep/VariableStepValue.java index 60b06d315..1634fcecf 100644 --- a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/variablestep/VariableStepValue.java +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/variablestep/VariableStepValue.java @@ -9,9 +9,9 @@ import org.intocps.fmi.FmuResult; import org.intocps.fmi.IFmiComponent; import org.intocps.maestro.core.dto.VariableStepAlgorithmConfig; +import org.intocps.maestro.fmi.Fmi2ModelDescription; import org.intocps.maestro.fmi.FmiInstanceConfig; import org.intocps.maestro.fmi.FmiSimulationInstance; -import org.intocps.maestro.fmi.Fmi2ModelDescription; import org.intocps.maestro.framework.fmi2.ModelConnection; import org.intocps.maestro.interpreter.InterpreterException; import org.intocps.maestro.interpreter.ValueExtractionUtilities; @@ -145,7 +145,7 @@ private static Map createMembers(String algorithmAsJson) { Value cv = fcargs.get(0).deref(); if (cv instanceof VariableStepConfigValue) { VariableStepConfigValue variableStepConfigValue = (VariableStepConfigValue) cv; - double time = ((RealValue) fcargs.get(1).deref()).getValue(); + double time = ((NumericValue) fcargs.get(1).deref()).realValue(); List portValues = ValueExtractionUtilities.getArrayValue(fcargs.get(2), Value.class); variableStepConfigValue.addDataPoint(time, portValues); } else { @@ -157,7 +157,7 @@ private static Map createMembers(String algorithmAsJson) { checkArgLength(fcargs, 3); Value cv = fcargs.get(0).deref(); - double time = ((RealValue) fcargs.get(1).deref()).getValue(); + double time = ((NumericValue) fcargs.get(1).deref()).realValue(); if (cv instanceof VariableStepConfigValue) { VariableStepConfigValue variableStepConfig = (VariableStepConfigValue) cv; Value arrVal = fcargs.get(2).deref(); @@ -165,8 +165,8 @@ private static Map createMembers(String algorithmAsJson) { ArrayValue array = (ArrayValue) arrVal; if (array.getValues().stream().allMatch(v -> v.deref() instanceof ArrayValue)) { try { - List> ders = array.getValues().stream() - .map(subArr -> ((ArrayValue) subArr.deref()).getValues().stream().map(v -> (RealValue) v) + List> ders = array.getValues().stream() + .map(subArr -> ((ArrayValue) subArr.deref()).getValues().stream().map(v -> (NumericValue) v) .collect(Collectors.toList())).collect(Collectors.toList()); variableStepConfig.addDerivatives(ders, time); } catch (Exception e) { @@ -197,7 +197,7 @@ private static Map createMembers(String algorithmAsJson) { checkArgLength(fcargs, 2); Value cv = fcargs.get(0).deref(); if (cv instanceof VariableStepConfigValue) { - ((VariableStepConfigValue) cv).setEndTime(((RealValue) fcargs.get(1).deref()).getValue()); + ((VariableStepConfigValue) cv).setEndTime(((NumericValue) fcargs.get(1).deref()).realValue()); } else { throw new InterpreterException("Invalid arguments"); } @@ -209,7 +209,7 @@ private static Map createMembers(String algorithmAsJson) { Value cv = fcargs.get(0).deref(); if (cv instanceof VariableStepConfigValue) { VariableStepConfigValue variableStepConfigValue = (VariableStepConfigValue) cv; - double nextTime = ((RealValue) fcargs.get(1).deref()).getValue(); + double nextTime = ((NumericValue) fcargs.get(1).deref()).realValue(); boolean supportsRollBack = ((BooleanValue) fcargs.get(2).deref()).getValue(); List portValues = ValueExtractionUtilities.getArrayValue(fcargs.get(3), Value.class); return new BooleanValue(variableStepConfigValue.isStepValid(nextTime, portValues, supportsRollBack)); diff --git a/interpreter/src/test/java/org/intocps/maestro/interpreter/ExternalReflectCallHelperAutoTest.java b/interpreter/src/test/java/org/intocps/maestro/interpreter/ExternalReflectCallHelperAutoTest.java new file mode 100644 index 000000000..6b3fc9b90 --- /dev/null +++ b/interpreter/src/test/java/org/intocps/maestro/interpreter/ExternalReflectCallHelperAutoTest.java @@ -0,0 +1,223 @@ +package org.intocps.maestro.interpreter; + +import org.antlr.v4.runtime.CharStreams; +import org.intocps.fmi.FmuInvocationException; +import org.intocps.fmi.jnifmuapi.fmi3.Fmi3Instance; +import org.intocps.fmi.jnifmuapi.fmi3.Fmu3; +import org.intocps.maestro.ast.AEqualBinaryExp; +import org.intocps.maestro.ast.AFunctionDeclaration; +import org.intocps.maestro.ast.LexIdentifier; +import org.intocps.maestro.ast.analysis.AnalysisException; +import org.intocps.maestro.ast.node.*; +import org.intocps.maestro.core.messages.ErrorReporter; +import org.intocps.maestro.core.messages.IErrorReporter; +import org.intocps.maestro.interpreter.external.ExternalReflectCallHelper; +import org.intocps.maestro.interpreter.external.ExternalReflectModuleHelper; +import org.intocps.maestro.interpreter.external.IArgMapping; +import org.intocps.maestro.interpreter.external.TP; +import org.intocps.maestro.interpreter.values.*; +import org.intocps.maestro.parser.MablParserUtil; +import org.intocps.maestro.typechecker.TypeChecker; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.stream.Collectors; + +@Disabled +public class ExternalReflectCallHelperAutoTest { + public static ARootDocument getRuntimeModule(String module) throws IOException { + InputStream resourceAsStream = TypeChecker.getRuntimeModule(module); + if (resourceAsStream == null) { + return null; + } + ARootDocument parse = MablParserUtil.parse(CharStreams.fromStream(resourceAsStream)); + return parse; + } + + List parse(InputStream is) throws IOException, AnalysisException { + ARootDocument doc = MablParserUtil.parse(CharStreams.fromStream(is)); + IErrorReporter reporter = new ErrorReporter(); + TypeChecker typeChecker = new TypeChecker(reporter); + + List allModules = TypeChecker.getRuntimeModules(); + List documents = new ArrayList<>(); + documents.add(doc); + documents.add(MablParserUtil.parse(CharStreams.fromStream(new ByteArrayInputStream("simulation{}".getBytes(StandardCharsets.UTF_8))))); + + List imports = doc.getContent().stream().filter(m -> m instanceof AImportedModuleCompilationUnit) + .flatMap(m -> ((AImportedModuleCompilationUnit) m).getImports().stream()).map(LexIdentifier::getText).collect(Collectors.toList()); + if (imports != null) { + for (String module : imports) { + if (allModules.contains(module)) { + documents.add(getRuntimeModule(module)); + } + } + } + + boolean res = typeChecker.typeCheck(documents, new Vector<>()); + PrintWriter writer = new PrintWriter(System.err); + if (!res) { + reporter.printWarnings(writer); + reporter.printErrors(writer); + } + writer.flush(); + Assertions.assertTrue(res); + return doc.getContent().stream().filter(m -> m instanceof AImportedModuleCompilationUnit).map(AImportedModuleCompilationUnit.class::cast) + .collect(Collectors.toList()); + } + + @Test + + public void test() throws IOException, AnalysisException, NoSuchMethodException, FmuInvocationException { + String kk = "../src/main/resources/org/intocps/maestro/typechecker/FMI3.mabl"; + List modules = parse(new FileInputStream(kk)); + + + for (AImportedModuleCompilationUnit module : modules) { + + if (module.getModule().getName().getText().equals("FMI3")) { + // var fmu = new Fmu3(new File("/Users/kgl/data/au/into-cps-association/maestro/maestro/src/test/resources/singlewatertank-20sim.fmu")); + // ExternalReflectModuleHelper.createExternalModule(module.getModule(), fmu); + } else if (module.getModule().getName().getText().equals("FMI3Instance")) { + var fmu = new Fmu3(new File("..//maestro/src/test/resources/singlewatertank-20sim.fmu")); + Fmi3Instance inst = new Fmi3Instance(0, fmu); + ExternalReflectModuleHelper.createExternalModule(module.getModule(), inst, + fun -> !fun.getName().getText().equals("enterInitializationMode") && !fun.getName().getText() + .startsWith("get") && !fun.getName().getText().equals("setBinary")); + } + + } + } + + @Test + public void autoMapperTest() throws IOException, AnalysisException, NoSuchMethodException { + List modules = parse( + ExternalReflectCallHelperAutoTest.class.getResourceAsStream("interpreter_automapper.mabl")); + + + LinkedList functions = modules.get(0).getModule().getFunctions(); + + List helpers = functions.stream().map(f -> new ExternalReflectCallHelper(f, this, null)) + .collect(Collectors.toList()); + + helpers.forEach(System.out::println); + helpers.stream().map(h -> h.getSignature(true)).forEach(System.out::println); + + Interpreter interpreter = new Interpreter(null); + + final AEqualBinaryExp eq = new AEqualBinaryExp(new AIdentifierExp(new LexIdentifier("a", null)), + new AIdentifierExp(new LexIdentifier("b", null))); + for (AFunctionDeclaration f : functions) { + ExternalReflectCallHelper helper = new ExternalReflectCallHelper(f, this); + System.out.println(helper); + List args = buildArgs(f); + helper.build().evaluate(args); + List argsRef = buildArgs(f); + + for (int i = 0; i < helper.size(); i++) { + IArgMapping arg = helper.get(i); + + + if (arg.getDirection() == ExternalReflectCallHelper.ArgMapping.InOut.Output) { + Value a = (Value) args.get(i).as(UpdatableValue.class).deref().as(ArrayValue.class).getValues().get(0); + Value b = (Value) argsRef.get(i).as(UpdatableValue.class).deref().as(ArrayValue.class).getValues().get(0); + Context c = new Context(null); + c.put(new AIdentifierExp(new LexIdentifier("a", null)), a); + c.put(new AIdentifierExp(new LexIdentifier("b", null)), b); + Assertions.assertFalse(((BooleanValue) interpreter.caseAEqualBinaryExp(eq, c)).getValue(), "value should have changed"); + + c.put(new AIdentifierExp(new LexIdentifier("a", null)), b); + c.put(new AIdentifierExp(new LexIdentifier("b", null)), b); + Assertions.assertTrue(((BooleanValue) interpreter.caseAEqualBinaryExp(eq, c)).getValue(), "value should not have changed"); + + + } + } + } + } + + public List buildArgs(AFunctionDeclaration func) { + return func.getFormals().stream().map(AFormalParameter::getType).map(t -> { + + + boolean updatable = t instanceof AReferenceType; + if (t instanceof AReferenceType) { + t = ((AReferenceType) t).getType(); + } + + boolean array = t instanceof AArrayType; + Map.Entry tt = null; + try { + tt = ExternalReflectCallHelper.getReverseType(t); + } catch (ExternalReflectCallHelper.ExceptionUnknownTypeMapping e) { + throw new RuntimeException(e); + } + Value v = null; + switch (tt.getKey()) { + case Bool: + v = new BooleanValue(false); + break; + case Byte: + v = new ByteValue(0); + break; + case Float: + v = new FloatValue(0); + break; + case Int: + v = new IntegerValue(0); + break; + case Long: + v = new LongValue(0); + break; + case Real: + v = new RealValue(0); + break; + case Short: + v = new ShortValue(Short.parseShort("0")); + break; + case String: + v = new StringValue("hello"); + break; + } + + if (array) { + v = new ArrayValue<>(new Vector<>(List.of(v))); + } + if (updatable) { + v = new UpdatableValue(v); + } + return v; + }).collect(Collectors.toList()); + } + + public int myFunc1(int arg0, long[] arg1) { + return 1; + } + + public int myFunc2(int arg0, long[] arg1) { + arg1[0] = 1; + return 1; + } + + public int myFunc3(int arg0, long[] arg1) { + arg1[0] = 1; + return 1; + } + + public boolean identityBoolArrCStyle(boolean[] arg0) { + return true; + } + + public boolean identityBoolArr(boolean[] arg0) { + return true; + } + + public boolean identityBoolArrOut(boolean[] arg0) { + arg0[0] = true; + return true; + } +} diff --git a/interpreter/src/test/java/org/intocps/maestro/interpreter/ExternalReflectCallHelperTest.java b/interpreter/src/test/java/org/intocps/maestro/interpreter/ExternalReflectCallHelperTest.java new file mode 100644 index 000000000..aaa98e6ac --- /dev/null +++ b/interpreter/src/test/java/org/intocps/maestro/interpreter/ExternalReflectCallHelperTest.java @@ -0,0 +1,200 @@ +package org.intocps.maestro.interpreter; + +import org.antlr.v4.runtime.CharStreams; +import org.intocps.maestro.ast.AFunctionDeclaration; +import org.intocps.maestro.ast.analysis.AnalysisException; +import org.intocps.maestro.ast.node.*; +import org.intocps.maestro.core.messages.ErrorReporter; +import org.intocps.maestro.core.messages.IErrorReporter; +import org.intocps.maestro.interpreter.external.ExternalReflectCallHelper; +import org.intocps.maestro.interpreter.external.TP; +import org.intocps.maestro.interpreter.values.*; +import org.intocps.maestro.parser.MablParserUtil; +import org.intocps.maestro.typechecker.TypeChecker; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.io.PrintWriter; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Vector; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +public class ExternalReflectCallHelperTest { + + @Test + public void test() throws NoSuchMethodException { + + + ExternalReflectCallHelper helper = new ExternalReflectCallHelper("myFunc9", this); + + var caller = helper.addArg(TP.Int).addArg(TP.Long, 2).build(); + + List args = List.of(NumericValue.valueOf(2), + new ArrayValue<>(List.of(NumericValue.valueOf(1), NumericValue.valueOf(2), NumericValue.valueOf(3)))); + caller.evaluate(args); + + var rCaller = helper.addReturn(TP.Int).build(); + Assertions.assertEquals(1, ((NumericValue) rCaller.evaluate(args)).intValue()); + } + + @Test + public void testRet() throws NoSuchMethodException { + + ExternalReflectCallHelper helper = new ExternalReflectCallHelper("myFuncOut1", this); + + var caller = helper.addArg(TP.Long, 2, ExternalReflectCallHelper.ArgMapping.InOut.Output).build(); + + List args = List.of(new UpdatableValue( + new ArrayValue<>(new Vector<>(List.of(NumericValue.valueOf(1), NumericValue.valueOf(2), NumericValue.valueOf(3)))))); + caller.evaluate(args); + + var rCaller = helper.addReturn(TP.Int).build(); + Assertions.assertEquals(1, ((NumericValue) rCaller.evaluate(args)).intValue()); + Assertions.assertEquals(99, ((NumericValue) args.get(0).as(UpdatableValue.class).deref().as(ArrayValue.class).getValues().get(0)).intValue()); + } + + @Test + public void autoMapperTest() throws IOException, AnalysisException, NoSuchMethodException { + ARootDocument doc = MablParserUtil.parse( + CharStreams.fromStream(ExternalReflectCallHelperTest.class.getResourceAsStream("interpreter_automapper.mabl"))); + IErrorReporter reporter = new ErrorReporter(); + TypeChecker typeChecker = new TypeChecker(reporter); + boolean res = typeChecker.typeCheck(List.of(doc), new Vector<>()); + PrintWriter writer = new PrintWriter(System.err); + if (!res) { + reporter.printWarnings(writer); + reporter.printErrors(writer); + } + writer.flush(); + Assertions.assertTrue(res); + + LinkedList functions = ((AImportedModuleCompilationUnit) doc.getContent().get(0)).getModule().getFunctions(); + + List helpers = functions.stream().map(f -> new ExternalReflectCallHelper(f, this)).collect(Collectors.toList()); + + helpers.forEach(System.out::println); + helpers.stream().map(h -> h.getSignature(true)).forEach(System.out::println); + + AFunctionDeclaration func = functions.get(0); + + // AImportedModuleCompilationUnit im = (AImportedModuleCompilationUnit) doc.getContent().get(0); + // im.get + // ExternalReflectCallHelper helper = new ExternalReflectCallHelper(func, this); + // List args = List.of(NumericValue.valueOf(2), + // new ArrayValue<>(List.of(NumericValue.valueOf(1), NumericValue.valueOf(2), NumericValue.valueOf(3)))); + // System.out.println(helper); + // + // + // FunctionValue.ExternalFunctionValue call = helper.build(); + // call.evaluate(args); + // + // func = functions.get(1); + // helper = new ExternalReflectCallHelper(func, this); + // System.out.println(helper); + // args = List.of(NumericValue.valueOf(1), new UpdatableValue( + // new ArrayValue<>(new Vector<>(List.of(NumericValue.valueOf(1), NumericValue.valueOf(2), NumericValue.valueOf(3)))))); + // helper.build().evaluate(args); + + for (AFunctionDeclaration f : functions) { + ExternalReflectCallHelper helper = new ExternalReflectCallHelper(f, this); + System.out.println(helper); + helper.build().evaluate(buildArgs(f)); + } + } + + public List buildArgs(AFunctionDeclaration func) { + return func.getFormals().stream().map(AFormalParameter::getType).map(t -> { + + + boolean updatable = t instanceof AReferenceType; + if (t instanceof AReferenceType) { + t = ((AReferenceType) t).getType(); + } + + boolean array = t instanceof AArrayType; + Map.Entry tt = null; + try { + tt = ExternalReflectCallHelper.getReverseType(t); + } catch (ExternalReflectCallHelper.ExceptionUnknownTypeMapping e) { + throw new RuntimeException(e); + } + Value v = null; + switch (tt.getKey()) { + case Bool: + v = new BooleanValue(false); + break; + case Byte: + v = new ByteValue(1); + break; + case Float: + v = new FloatValue(1.1f); + break; + case Int: + v = new IntegerValue(1); + break; + case Long: + v = new LongValue(1); + break; + case Real: + v = new RealValue(3.33); + break; + case Short: + v = new ShortValue(Short.parseShort("1")); + break; + case String: + v = new StringValue("hello"); + break; + } + + if (array) { + final Value vv = v; + v = new ArrayValue<>(IntStream.range(1, 4).mapToObj(i -> vv).collect(Collectors.toList())); + } + if (updatable) { + v = new UpdatableValue(v); + } + return v; + }).collect(Collectors.toList()); + } + + public int myFunc9(int ints, long[] longs) { + Assertions.assertEquals(2, ints); + Assertions.assertArrayEquals(new long[]{1, 2, 3}, longs); + return 1; + } + + public int myFunc1(int ints, long[] longs) { + Assertions.assertEquals(1, ints); + Assertions.assertArrayEquals(new long[]{1, 1, 1}, longs); + return 1; + } + + public int myFuncOut1(long[] longs) { + longs[0] = 99; + return 1; + } + + public int myFunc2(int arg0, long[] arg1) { + return 1; + } + + public int myFunc3(long arg0, long[] arg1) { + return 1; + } + + public boolean identityBoolArrCStyle(boolean[] arg0) { + return true; + } + + public boolean identityBoolArr(boolean[] arg0) { + return true; + } + + public boolean identityBoolArrOut(boolean[] arg0) { + return true; + } +} diff --git a/interpreter/src/test/resources/org/intocps/maestro/interpreter/interpreter_automapper.mabl b/interpreter/src/test/resources/org/intocps/maestro/interpreter/interpreter_automapper.mabl new file mode 100644 index 000000000..c0c4e03b7 --- /dev/null +++ b/interpreter/src/test/resources/org/intocps/maestro/interpreter/interpreter_automapper.mabl @@ -0,0 +1,12 @@ +module Global { + int myFunc1( int a, long[] longs); + int myFunc2( int a, out long[] longs); + int myFunc3( uint a, out long[] longs); + bool[] identityBoolArrCStyle( bool a[]); + bool[] identityBoolArr( bool a[]); + bool identityBoolArrOut(out bool a[]); +} + +simulation +import Global; +{} \ No newline at end of file diff --git a/maestro-webapi/src/main/java/org/intocps/maestro/webapi/maestro2/Maestro2Broker.java b/maestro-webapi/src/main/java/org/intocps/maestro/webapi/maestro2/Maestro2Broker.java index b2e540a6b..9c111ae6e 100644 --- a/maestro-webapi/src/main/java/org/intocps/maestro/webapi/maestro2/Maestro2Broker.java +++ b/maestro-webapi/src/main/java/org/intocps/maestro/webapi/maestro2/Maestro2Broker.java @@ -9,6 +9,8 @@ import org.intocps.maestro.ast.LexIdentifier; import org.intocps.maestro.ast.analysis.AnalysisException; import org.intocps.maestro.ast.display.PrettyPrinter; +import org.intocps.maestro.ast.node.INode; +import org.intocps.maestro.ast.node.PType; import org.intocps.maestro.cli.ImportCmd; import org.intocps.maestro.core.Framework; import org.intocps.maestro.core.dto.MultiModel; @@ -17,15 +19,16 @@ import org.intocps.maestro.framework.fmi2.Fmi2SimulationEnvironment; import org.intocps.maestro.framework.fmi2.Fmi2SimulationEnvironmentConfiguration; import org.intocps.maestro.framework.fmi2.LegacyMMSupport; -import org.intocps.maestro.interpreter.DefaultExternalValueFactory; import org.intocps.maestro.interpreter.MableInterpreter; import org.intocps.maestro.interpreter.api.IValueLifecycleHandler; +import org.intocps.maestro.interpreter.extensions.SimulationControlDefaultLifecycleHandler; import org.intocps.maestro.interpreter.values.Value; import org.intocps.maestro.interpreter.values.simulationcontrol.SimulationControlValue; import org.intocps.maestro.plugin.JacobianStepConfig; import org.intocps.maestro.plugin.MasterModelMapper; import org.intocps.maestro.template.MaBLTemplateConfiguration; import org.intocps.maestro.template.ScenarioConfiguration; +import org.intocps.maestro.typechecker.TypeChecker; import org.intocps.maestro.webapi.maestro2.dto.InitializationData; import org.intocps.maestro.webapi.maestro2.dto.SigverSimulateRequestBody; import org.intocps.maestro.webapi.maestro2.dto.SimulateRequestBody; @@ -52,9 +55,9 @@ public class Maestro2Broker { final File workingDirectory; final ErrorReporter reporter; private final Supplier isStopRequsted; - private final Function>, List> flattenFmuIds = - map -> map.entrySet().stream().flatMap(entry -> entry.getValue().stream().map(v -> entry.getKey() + "." + v)) - .collect(Collectors.toList()); + private final Function>, List> flattenFmuIds = map -> map.entrySet().stream() + .flatMap(entry -> entry.getValue().stream().map(v -> entry.getKey() + "." + v)).collect(Collectors.toList()); + private Map.Entry> typeCheckResult; public Maestro2Broker(File workingDirectory, ErrorReporter reporter, Supplier isStopRequsted) { this.workingDirectory = workingDirectory; @@ -71,24 +74,24 @@ public Maestro2Broker(File workingDirectory, ErrorReporter reporter, Supplier void buildAndRunMasterModel(Map> livestreamVariables, WebSocketSession socket, T multiModel, SigverSimulateRequestBody body, File csvOutputFile) throws Exception { MasterModel masterModel = ScenarioLoader.load(new ByteArrayInputStream(body.getMasterModel().getBytes())); - Fmi2SimulationEnvironmentConfiguration simulationConfiguration = - new Fmi2SimulationEnvironmentConfiguration(MasterModelMapper.Companion.masterModelConnectionsToMultiModelConnections(masterModel), - multiModel.getFmus()); + Fmi2SimulationEnvironmentConfiguration simulationConfiguration = new Fmi2SimulationEnvironmentConfiguration( + MasterModelMapper.Companion.masterModelConnectionsToMultiModelConnections(masterModel), multiModel.getFmus()); simulationConfiguration.logVariables = multiModel.getLogVariables(); if (simulationConfiguration.logVariables == null) { simulationConfiguration.variablesToLog = new HashMap<>(); } Fmi2SimulationEnvironment simulationEnvironment = Fmi2SimulationEnvironment.of(simulationConfiguration, reporter); - ScenarioConfiguration configuration = - new ScenarioConfiguration(simulationEnvironment, masterModel, multiModel.getParameters(), multiModel.getGlobal_relative_tolerance(), - multiModel.getGlobal_absolute_tolerance(), multiModel.getConvergenceAttempts(), body.getStartTime(), body.getEndTime(), - multiModel.getAlgorithm().getStepSize(), Pair.of(Framework.FMI2, simulationConfiguration), multiModel.isLoggingOn(), - multiModel.getLogLevels()); + ScenarioConfiguration configuration = new ScenarioConfiguration(simulationEnvironment, masterModel, multiModel.getParameters(), + multiModel.getGlobal_relative_tolerance(), multiModel.getGlobal_absolute_tolerance(), multiModel.getConvergenceAttempts(), + body.getStartTime(), body.getEndTime(), multiModel.getAlgorithm().getStepSize(), Pair.of(Framework.FMI2, simulationConfiguration), + multiModel.isLoggingOn(), multiModel.getLogLevels()); String runtimeJsonConfigString = generateSpecification(configuration, null); - if (!mabl.typeCheck().getKey()) { + typeCheckResult = mabl.typeCheck(); + + if (!typeCheckResult.getKey()) { throw new Exception("Specification did not type check"); } @@ -114,8 +117,8 @@ public void buildAndRun(InitializationData initializeRequest, SimulateRequestBod //Initially resolve any FMUs to the local folder in case they are uploaded ImportCmd.resolveFmuPaths(Collections.singletonList(workingDirectory), initializeRequest.getFmus()); - Fmi2SimulationEnvironmentConfiguration simulationConfiguration = - new Fmi2SimulationEnvironmentConfiguration(initializeRequest.getConnections(), initializeRequest.getFmus()); + Fmi2SimulationEnvironmentConfiguration simulationConfiguration = new Fmi2SimulationEnvironmentConfiguration( + initializeRequest.getConnections(), initializeRequest.getFmus()); simulationConfiguration.logVariables = initializeRequest.getLogVariables(); if (simulationConfiguration.logVariables == null) { @@ -159,11 +162,10 @@ public void buildAndRun(InitializationData initializeRequest, SimulateRequestBod config.startTime = body.getStartTime(); config.endTime = body.getEndTime(); - MaBLTemplateConfiguration.MaBLTemplateConfigurationBuilder builder = - MaBLTemplateConfiguration.MaBLTemplateConfigurationBuilder.getBuilder().setFrameworkConfig(Framework.FMI2, simulationConfiguration) - .useInitializer(true, new ObjectMapper().writeValueAsString(initialize)).setFramework(Framework.FMI2) - .setLogLevels(removedFMUKeyFromLogLevels).setVisible(initializeRequest.isVisible()) - .setLoggingOn(initializeRequest.isLoggingOn()).setStepAlgorithmConfig(config); + MaBLTemplateConfiguration.MaBLTemplateConfigurationBuilder builder = MaBLTemplateConfiguration.MaBLTemplateConfigurationBuilder.getBuilder() + .setFrameworkConfig(Framework.FMI2, simulationConfiguration).useInitializer(true, new ObjectMapper().writeValueAsString(initialize)) + .setFramework(Framework.FMI2).setLogLevels(removedFMUKeyFromLogLevels).setVisible(initializeRequest.isVisible()) + .setLoggingOn(initializeRequest.isLoggingOn()).setStepAlgorithmConfig(config); MaBLTemplateConfiguration configuration = builder.build(); @@ -185,8 +187,8 @@ public void buildAndRun(InitializationData initializeRequest, SimulateRequestBod if (filesNotResolved.size() > 0) { errMsg = "Cannot resolve path to spec files: " + nonMablFiles.stream().map(File::getName).reduce("", (prev, cur) -> prev + " " + cur); } else if (nonMablFiles.size() > 0) { - errMsg = "Cannot load spec files: " + nonMablFiles.stream().map(File::getName).reduce("", (prev, cur) -> prev + " " + cur) + - ". Only mabl files should be " + "included as " + "external specs."; + errMsg = "Cannot load spec files: " + nonMablFiles.stream().map(File::getName) + .reduce("", (prev, cur) -> prev + " " + cur) + ". Only mabl files should be " + "included as " + "external specs."; } if (!errMsg.equals("")) { @@ -196,8 +198,8 @@ public void buildAndRun(InitializationData initializeRequest, SimulateRequestBod mabl.parse(initializeRequest.getExternalSpecs()); } // If fault injection is configured then the faultinject.mabl file should be included as an external spec. - if (initializeRequest.faultInjectConfigurationPath != null && !initializeRequest.faultInjectConfigurationPath.equals("") && - !didLocateFaultInjectionFile.get()) { + if (initializeRequest.faultInjectConfigurationPath != null && !initializeRequest.faultInjectConfigurationPath.equals( + "") && !didLocateFaultInjectionFile.get()) { throw new Exception("Remember to include FaultInject.mabl as an external spec"); } String runtimeJsonConfigString = generateSpecification(configuration, parameters); @@ -249,14 +251,15 @@ public void executeInterpreter(WebSocketSession webSocket, List csvFilte WebApiInterpreterFactory factory; if (webSocket != null) { factory = new WebApiInterpreterFactory(workingDirectory, webSocket, interval, webSocketFilter, new File(workingDirectory, "outputs.csv"), - csvFilter, config); + csvFilter, name -> TypeChecker.findModule(typeCheckResult.getValue(), name), config); } else { - factory = new WebApiInterpreterFactory(workingDirectory, csvOutputFile, csvFilter, config); + factory = new WebApiInterpreterFactory(workingDirectory, csvOutputFile, csvFilter, + name -> TypeChecker.findModule(typeCheckResult.getValue(), name), config); } // create and install the overrides' simulation control lifecycle handler that links this simulation to the current session @IValueLifecycleHandler.ValueLifecycle(name = "SimulationControl") - class WebSimulationControlDefaultLifecycleHandler extends DefaultExternalValueFactory.SimulationControlDefaultLifecycleHandler { + class WebSimulationControlDefaultLifecycleHandler extends SimulationControlDefaultLifecycleHandler { @Override public Either instantiate(List args) { return Either.right(new SimulationControlValue(isStopRequsted)); diff --git a/maestro-webapi/src/main/java/org/intocps/maestro/webapi/maestro2/interpreter/WebApiInterpreterFactory.java b/maestro-webapi/src/main/java/org/intocps/maestro/webapi/maestro2/interpreter/WebApiInterpreterFactory.java index cb43b1266..40bfeb36a 100644 --- a/maestro-webapi/src/main/java/org/intocps/maestro/webapi/maestro2/interpreter/WebApiInterpreterFactory.java +++ b/maestro-webapi/src/main/java/org/intocps/maestro/webapi/maestro2/interpreter/WebApiInterpreterFactory.java @@ -1,9 +1,12 @@ package org.intocps.maestro.webapi.maestro2.interpreter; import com.spencerwi.either.Either; +import org.intocps.maestro.ast.AModuleDeclaration; import org.intocps.maestro.ast.analysis.AnalysisException; import org.intocps.maestro.interpreter.DefaultExternalValueFactory; import org.intocps.maestro.interpreter.api.IValueLifecycleHandler; +import org.intocps.maestro.interpreter.extensions.BaseLifecycleHandler; +import org.intocps.maestro.interpreter.extensions.DataWriterLifecycleHandler; import org.intocps.maestro.interpreter.values.Value; import org.intocps.maestro.interpreter.values.csv.CsvDataWriter; import org.intocps.maestro.interpreter.values.datawriter.DataWriterValue; @@ -16,23 +19,24 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.function.Function; public class WebApiInterpreterFactory extends DefaultExternalValueFactory { public WebApiInterpreterFactory(File workingDirectory, WebSocketSession ws, double interval, List webSocketFilter, File csvOutputFile, - List csvFilter, + List csvFilter, Function resolver, InputStream config) throws IOException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException { - super(workingDirectory, config); + super(workingDirectory, resolver, config); this.lifecycleHandlers.put(DataWriterLifecycleHandler.class.getAnnotation(IValueLifecycleHandler.ValueLifecycle.class).name(), new WebDataWriterAndWebsocketLifecycleHandler(csvFilter, csvOutputFile, ws, webSocketFilter, interval)); } - public WebApiInterpreterFactory(File workingDirectory, File csvOutputFile, List csvFilter, + public WebApiInterpreterFactory(File workingDirectory, File csvOutputFile, List csvFilter, Function resolver, InputStream config) throws IOException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException { - super(workingDirectory, config); + super(workingDirectory, resolver, config); this.lifecycleHandlers.put(DataWriterLifecycleHandler.class.getAnnotation(IValueLifecycleHandler.ValueLifecycle.class).name(), new WebDataWriterLifecycleHandler(csvFilter, csvOutputFile)); } diff --git a/maestro/src/main/java/org/intocps/maestro/MablRuntimeDataGenerator.java b/maestro/src/main/java/org/intocps/maestro/MablRuntimeDataGenerator.java index 8e14547ee..e734f79b5 100644 --- a/maestro/src/main/java/org/intocps/maestro/MablRuntimeDataGenerator.java +++ b/maestro/src/main/java/org/intocps/maestro/MablRuntimeDataGenerator.java @@ -1,7 +1,7 @@ package org.intocps.maestro; import org.intocps.maestro.framework.core.ISimulationEnvironment; -import org.intocps.maestro.interpreter.DefaultExternalValueFactory; +import org.intocps.maestro.interpreter.extensions.MEnvLifecycleHandler; import java.util.Arrays; import java.util.HashMap; @@ -27,7 +27,7 @@ public Object getRuntimeData() { })); if (this.runtimeEnvironmentVariables != null) { - data.put(DefaultExternalValueFactory.MEnvLifecycleHandler.ENVIRONMENT_VARIABLES, this.runtimeEnvironmentVariables); + data.put(MEnvLifecycleHandler.ENVIRONMENT_VARIABLES, this.runtimeEnvironmentVariables); } return data; diff --git a/maestro/src/main/java/org/intocps/maestro/cli/ImportCmd.java b/maestro/src/main/java/org/intocps/maestro/cli/ImportCmd.java index 053944abe..7917ca792 100644 --- a/maestro/src/main/java/org/intocps/maestro/cli/ImportCmd.java +++ b/maestro/src/main/java/org/intocps/maestro/cli/ImportCmd.java @@ -237,6 +237,10 @@ private boolean importSg1(MablCliUtil util, List fmuSearchPaths, List TypeChecker.findModule(typeCheckResult.getValue(), name), c); } public boolean generateSpec(ScenarioConfiguration scenarioConfiguration) throws Exception { diff --git a/maestro/src/test/java/org/intocps/maestro/BuilderGetSetDerivativesTest.java b/maestro/src/test/java/org/intocps/maestro/BuilderGetSetDerivativesTest.java index 49faffb5d..f0c6fb959 100644 --- a/maestro/src/test/java/org/intocps/maestro/BuilderGetSetDerivativesTest.java +++ b/maestro/src/test/java/org/intocps/maestro/BuilderGetSetDerivativesTest.java @@ -80,22 +80,22 @@ public void getDerivativesTest() throws Exception { // Act // Get all ports fmuInstances.forEach((x, y) -> { - Set scalarVariablesToShare = - y.getPorts().stream().filter(p -> variablesOfInterest.stream().anyMatch(v -> v.equals(p.getMultiModelScalarVariableName()))) - .map(PortFmi2Api::getName).collect(Collectors.toSet()); + Set scalarVariablesToShare = y.getPorts().stream() + .filter(p -> variablesOfInterest.stream().anyMatch(v -> v.equals(p.getMultiModelScalarVariableName()))).map(PortFmi2Api::getName) + .collect(Collectors.toSet()); y.get(scalarVariablesToShare.toArray(String[]::new)); }); ASimulationSpecificationCompilationUnit program = builder.build(); // Assert - List specAsList = - Arrays.stream(PrettyPrinter.print(program).split("[\n\t]+")).filter(s -> !s.matches("[' '{}]")).collect(Collectors.toList()); + List specAsList = Arrays.stream(PrettyPrinter.print(program).split("[\n\t]+")).filter(s -> !s.matches("[' '{}]")) + .collect(Collectors.toList()); int derValOutSum = specAsList.stream().mapToInt(s -> s.toLowerCase().contains("dval_out") ? 1 : 0).sum(); int derOrderOutSum = specAsList.stream().mapToInt(s -> s.toLowerCase().contains("dorder_out") ? 1 : 0).sum(); int derRefOutSum = specAsList.stream().mapToInt(s -> s.toLowerCase().contains("dref_out") ? 1 : 0).sum(); - boolean setDerFuncIsPresent = - specAsList.stream().filter(s -> s.contains("pump.getRealOutputDerivatives")).collect(Collectors.toList()).size() == 1; + boolean setDerFuncIsPresent = specAsList.stream().filter(s -> s.contains("pump.getRealOutputDerivatives")).collect(Collectors.toList()) + .size() == 1; Assertions.assertEquals(expected_derValOutSum, derValOutSum); Assertions.assertEquals(expected_derOrderOutSum, derOrderOutSum); @@ -135,9 +135,9 @@ public void shareDerivativesTest() throws Exception { // Act // Get all ports and share them fmuInstances.forEach((x, y) -> { - Set scalarVariablesToShare = - y.getPorts().stream().filter(p -> variablesOfInterest.stream().anyMatch(v -> v.equals(p.getMultiModelScalarVariableName()))) - .map(PortFmi2Api::getName).collect(Collectors.toSet()); + Set scalarVariablesToShare = y.getPorts().stream() + .filter(p -> variablesOfInterest.stream().anyMatch(v -> v.equals(p.getMultiModelScalarVariableName()))).map(PortFmi2Api::getName) + .collect(Collectors.toSet()); Map> portsToShare = y.get(scalarVariablesToShare.toArray(String[]::new)); @@ -147,8 +147,8 @@ public void shareDerivativesTest() throws Exception { ASimulationSpecificationCompilationUnit program = builder.build(); // Assert - List specAsList = - Arrays.stream(PrettyPrinter.print(program).split("[\n\t]+")).filter(s -> !s.matches("[' '{}]")).collect(Collectors.toList()); + List specAsList = Arrays.stream(PrettyPrinter.print(program).split("[\n\t]+")).filter(s -> !s.matches("[' '{}]")) + .collect(Collectors.toList()); int derShareSum = specAsList.stream().mapToInt(s -> s.toLowerCase().contains("dershare") ? 1 : 0).sum(); Assertions.assertEquals(expected_derShareSum, derShareSum); @@ -189,9 +189,9 @@ public void setDerivativesTest() throws Exception { // Act // Get all ports and share them fmuInstances.forEach((x, y) -> { - Set scalarVariablesToShare = - y.getPorts().stream().filter(p -> variablesOfInterest.stream().anyMatch(v -> v.equals(p.getMultiModelScalarVariableName()))) - .map(PortFmi2Api::getName).collect(Collectors.toSet()); + Set scalarVariablesToShare = y.getPorts().stream() + .filter(p -> variablesOfInterest.stream().anyMatch(v -> v.equals(p.getMultiModelScalarVariableName()))).map(PortFmi2Api::getName) + .collect(Collectors.toSet()); Map> portsToShare = y.get(scalarVariablesToShare.toArray(String[]::new)); @@ -207,13 +207,13 @@ public void setDerivativesTest() throws Exception { ASimulationSpecificationCompilationUnit program = builder.build(); // Assert - List specAsList = - Arrays.stream(PrettyPrinter.print(program).split("[\n\t]+")).filter(s -> !s.matches("[' '{}]")).collect(Collectors.toList()); + List specAsList = Arrays.stream(PrettyPrinter.print(program).split("[\n\t]+")).filter(s -> !s.matches("[' '{}]")) + .collect(Collectors.toList()); int derValOutSum = specAsList.stream().mapToInt(s -> s.toLowerCase().contains("sinkrealdval_in") ? 1 : 0).sum(); int derOrderOutSum = specAsList.stream().mapToInt(s -> s.toLowerCase().contains("sinkintdorder_in") ? 1 : 0).sum(); int derRefOutSum = specAsList.stream().mapToInt(s -> s.toLowerCase().contains("sinkuintdref_in") ? 1 : 0).sum(); - boolean setDerFuncIsPresent = - specAsList.stream().filter(s -> s.toLowerCase().contains("sink.setrealinputderivatives")).collect(Collectors.toList()).size() == 1; + boolean setDerFuncIsPresent = specAsList.stream().filter(s -> s.toLowerCase().contains("sink.setrealinputderivatives")) + .collect(Collectors.toList()).size() == 1; Assertions.assertEquals(expected_derValOutSum, derValOutSum); Assertions.assertEquals(expected_derOrderOutSum, derOrderOutSum); @@ -228,9 +228,8 @@ class getSetDerivativesInMabl { private final Path sinkMDPath = Paths.get(dirPath.toString(), "mocked_fmus", "sink_modelDescription.xml"); private File getWorkingDirectory(File base) throws IOException { - String s = "target/" + base.getAbsolutePath().substring( - base.getAbsolutePath().replace(File.separatorChar, '/').indexOf("src/test/resources/") + - ("src" + "/test" + "/resources/").length()); + String s = "target/" + base.getAbsolutePath().substring(base.getAbsolutePath().replace(File.separatorChar, '/') + .indexOf("src/test/resources/") + ("src" + "/test" + "/resources/").length()); File workingDir = new File(s.replace('/', File.separatorChar)); if (workingDir.exists()) { @@ -286,8 +285,8 @@ public IFmu instantiate(File sessionRoot, URI uri) throws Exception { .setRealInputDerivatives(new long[]{1, 1, 2, 2}, new int[]{1, 2, 1, 2}, new double[]{11, 12, 21, 22}); } - final InputStream md = - new ByteArrayInputStream(IOUtils.toByteArray(new File(modelDescriptionPath.replace('/', File.separatorChar)).toURI())); + final InputStream md = new ByteArrayInputStream( + IOUtils.toByteArray(new File(modelDescriptionPath.replace('/', File.separatorChar)).toURI())); when(fmu.getModelDescription()).thenReturn(md); return fmu; } @@ -331,9 +330,9 @@ public void test() throws Exception { // Act // Get all ports and share them fmuInstances.forEach((x, y) -> { - Set scalarVariablesToShare = - y.getPorts().stream().filter(p -> variablesOfInterest.stream().anyMatch(v -> v.equals(p.getMultiModelScalarVariableName()))) - .map(PortFmi2Api::getName).collect(Collectors.toSet()); + Set scalarVariablesToShare = y.getPorts().stream() + .filter(p -> variablesOfInterest.stream().anyMatch(v -> v.equals(p.getMultiModelScalarVariableName()))) + .map(PortFmi2Api::getName).collect(Collectors.toSet()); Map> portsToShare = y.get(scalarVariablesToShare.toArray(String[]::new)); @@ -378,8 +377,11 @@ public void test() throws Exception { Assertions.fail(); } - Assertions.assertDoesNotThrow(() -> new MableInterpreter(new DefaultExternalValueFactory(workingDirectory, - IOUtils.toInputStream(mabl.getRuntimeDataAsJsonString(), StandardCharsets.UTF_8))).execute(mabl.getMainSimulationUnit())); + var tcRes = mabl.typeCheck(); + + Assertions.assertDoesNotThrow(() -> new MableInterpreter( + new DefaultExternalValueFactory(workingDirectory, name -> TypeChecker.findModule(tcRes.getValue(), name), + IOUtils.toInputStream(mabl.getRuntimeDataAsJsonString(), StandardCharsets.UTF_8))).execute(mabl.getMainSimulationUnit())); } } } diff --git a/maestro/src/test/java/org/intocps/maestro/BuilderTest.java b/maestro/src/test/java/org/intocps/maestro/BuilderTest.java index ff4291c49..1685e145a 100644 --- a/maestro/src/test/java/org/intocps/maestro/BuilderTest.java +++ b/maestro/src/test/java/org/intocps/maestro/BuilderTest.java @@ -20,6 +20,7 @@ import org.intocps.maestro.framework.fmi2.api.mabl.variables.VariableFmi2Api; import org.intocps.maestro.interpreter.DefaultExternalValueFactory; import org.intocps.maestro.interpreter.MableInterpreter; +import org.intocps.maestro.typechecker.TypeChecker; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -37,8 +38,8 @@ public class BuilderTest { public void wt() throws Exception { InputStream is = this.getClass().getClassLoader().getResourceAsStream("buildertester/buildertester.json"); - Fmi2SimulationEnvironmentConfiguration simulationEnvironmentConfiguration = - Fmi2SimulationEnvironmentConfiguration.createFromJsonString(new String(Objects.requireNonNull(is).readAllBytes())); + Fmi2SimulationEnvironmentConfiguration simulationEnvironmentConfiguration = Fmi2SimulationEnvironmentConfiguration.createFromJsonString( + new String(Objects.requireNonNull(is).readAllBytes())); Fmi2SimulationEnvironment env = Fmi2SimulationEnvironment.of(simulationEnvironmentConfiguration, new IErrorReporter.SilentReporter()); @@ -66,8 +67,8 @@ public void wt() throws Exception { // Create the two FMUs FmuVariableFmi2Api controllerFMU = builder.getDynamicScope() .createFMU("controllerFMU", env.getModelDescription("{controllerFMU}"), env.getUriFromFMUName("{controllerFMU}")); - FmuVariableFmi2Api tankFMU = - builder.getDynamicScope().createFMU("tankFMU", env.getModelDescription("{tankFMU}"), env.getUriFromFMUName("{tankFMU}")); + FmuVariableFmi2Api tankFMU = builder.getDynamicScope() + .createFMU("tankFMU", env.getModelDescription("{tankFMU}"), env.getUriFromFMUName("{tankFMU}")); // Create the controller and tank instanes ComponentVariableFmi2Api controller = controllerFMU.instantiate("controller"); @@ -143,14 +144,14 @@ public void wt() throws Exception { mabl.parse(Collections.singletonList(specFile)); - mabl.typeCheck(); + var tcRes = mabl.typeCheck(); mabl.verify(Framework.FMI2); if (reporter.getErrorCount() > 0) { reporter.printErrors(new PrintWriter(System.err, true)); Assertions.fail(); } mabl.dump(workingDirectory); - new MableInterpreter(new DefaultExternalValueFactory(workingDirectory, + new MableInterpreter(new DefaultExternalValueFactory(workingDirectory, name -> TypeChecker.findModule(tcRes.getValue(), name), IOUtils.toInputStream(mabl.getRuntimeDataAsJsonString(), StandardCharsets.UTF_8))).execute(mabl.getMainSimulationUnit()); } diff --git a/maestro/src/test/java/org/intocps/maestro/ConsolePrinterInterfaceTest.java b/maestro/src/test/java/org/intocps/maestro/ConsolePrinterInterfaceTest.java index 09b359050..c49c2715f 100644 --- a/maestro/src/test/java/org/intocps/maestro/ConsolePrinterInterfaceTest.java +++ b/maestro/src/test/java/org/intocps/maestro/ConsolePrinterInterfaceTest.java @@ -63,7 +63,7 @@ public void printTest() throws Exception { @Test public void printRawValuesTest() throws Exception { int intTestVal = 1; - double doubleTestVal = 1.0; + double doubleTestVal = 1.1; boolean booleanTestVal = true; String stringTestVal = "a string"; @@ -113,7 +113,7 @@ public void printLnTest() throws Exception { String booleanMsg = "Boolean value: "; String allValues = "All values: "; int intTestVal = 1; - double doubleTestVal = 1.0; + double doubleTestVal = 1.1; boolean booleanTestVal = true; String stringTestVal = "a string"; diff --git a/maestro/src/test/java/org/intocps/maestro/DefaultLoaderFactoryTest.java b/maestro/src/test/java/org/intocps/maestro/DefaultLoaderFactoryTest.java index c101767b3..bad5a5cd0 100644 --- a/maestro/src/test/java/org/intocps/maestro/DefaultLoaderFactoryTest.java +++ b/maestro/src/test/java/org/intocps/maestro/DefaultLoaderFactoryTest.java @@ -7,10 +7,8 @@ import org.intocps.maestro.interpreter.DefaultExternalValueFactory; import org.intocps.maestro.interpreter.MableInterpreter; import org.intocps.maestro.interpreter.api.IValueLifecycleHandler; -import org.intocps.maestro.interpreter.values.ExternalModuleValue; -import org.intocps.maestro.interpreter.values.FunctionValue; -import org.intocps.maestro.interpreter.values.IntegerValue; -import org.intocps.maestro.interpreter.values.Value; +import org.intocps.maestro.interpreter.extensions.JavaClasspathLoaderLifecycleHandler; +import org.intocps.maestro.interpreter.values.*; import org.intocps.maestro.parser.MablParserUtil; import org.intocps.maestro.typechecker.TypeChecker; import org.junit.jupiter.api.Assertions; @@ -29,16 +27,15 @@ public class DefaultLoaderFactoryTest { @Test public void javaClasspathLoadMissingArgTest() throws AnalysisException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, IOException { String moduleDef = "module A{}"; - String spec = "simulation \n" + "import A;\n" + "{\n" + "A obj = load(\"" + - DefaultExternalValueFactory.JavaClasspathLoaderLifecycleHandler.class.getAnnotation(IValueLifecycleHandler.ValueLifecycle.class) - .name() + "\");}"; + String spec = "simulation \n" + "import A;\n" + "{\n" + "A obj = load(\"" + JavaClasspathLoaderLifecycleHandler.class.getAnnotation( + IValueLifecycleHandler.ValueLifecycle.class).name() + "\");}"; ErrorReporter reporter = new ErrorReporter(); TypeChecker tc = new TypeChecker(reporter); ARootDocument parse = MablParserUtil.parse(CharStreams.fromString(moduleDef + spec), reporter); boolean tcRes = tc.typeCheck(Arrays.asList(parse), new Vector<>()); - Throwable thrown = Assertions.assertThrows(AnalysisException.class, () -> new MableInterpreter(new DefaultExternalValueFactory(new File("target"), - null)).execute(parse)); + Throwable thrown = Assertions.assertThrows(AnalysisException.class, + () -> new MableInterpreter(new DefaultExternalValueFactory(new File("target"), tc::findModule, null)).execute(parse)); Assertions.assertEquals("Load failed", thrown.getMessage()); } @@ -48,9 +45,8 @@ public void javaClasspathLoadTest() throws AnalysisException, InvocationTargetEx String clz = MyCustomAValue.class.getName(); String moduleDef = "module A{}"; - String spec = "simulation \n" + "import A;\n" + "{\n" + "A obj = load(\"" + - DefaultExternalValueFactory.JavaClasspathLoaderLifecycleHandler.class.getAnnotation(IValueLifecycleHandler.ValueLifecycle.class) - .name() + "\",\"" + clz + "\");}"; + String spec = "simulation \n" + "import A;\n" + "{\n" + "A obj = load(\"" + JavaClasspathLoaderLifecycleHandler.class.getAnnotation( + IValueLifecycleHandler.ValueLifecycle.class).name() + "\",\"" + clz + "\");}"; ErrorReporter reporter = new ErrorReporter(); TypeChecker tc = new TypeChecker(reporter); @@ -58,7 +54,7 @@ public void javaClasspathLoadTest() throws AnalysisException, InvocationTargetEx boolean tcRes = tc.typeCheck(Arrays.asList(parse), new Vector<>()); MyCustomAValue.staticValue = 0; - new MableInterpreter(new DefaultExternalValueFactory(new File("target"), null)).execute(parse); + new MableInterpreter(new DefaultExternalValueFactory(new File("target"), tc::findModule, null)).execute(parse); Assertions.assertEquals(999, MyCustomAValue.staticValue.intValue()); } @@ -67,9 +63,8 @@ public void javaClasspathLoadWithArgsTest() throws AnalysisException, Invocation String clz = MyCustomAValue.class.getName(); String moduleDef = "module A{}"; - String spec = "simulation \n" + "import A;\n" + "{\n" + "A obj = load(\"" + - DefaultExternalValueFactory.JavaClasspathLoaderLifecycleHandler.class.getAnnotation(IValueLifecycleHandler.ValueLifecycle.class) - .name() + "\",\"" + clz + "\",1000);}"; + String spec = "simulation \n" + "import A;\n" + "{\n" + "A obj = load(\"" + JavaClasspathLoaderLifecycleHandler.class.getAnnotation( + IValueLifecycleHandler.ValueLifecycle.class).name() + "\",\"" + clz + "\",1000);}"; ErrorReporter reporter = new ErrorReporter(); TypeChecker tc = new TypeChecker(reporter); @@ -77,7 +72,7 @@ public void javaClasspathLoadWithArgsTest() throws AnalysisException, Invocation boolean tcRes = tc.typeCheck(Arrays.asList(parse), new Vector<>()); MyCustomAValue.staticValue = 0; - new MableInterpreter(new DefaultExternalValueFactory(new File("target"), null)).execute(parse); + new MableInterpreter(new DefaultExternalValueFactory(new File("target"), tc::findModule, null)).execute(parse); Assertions.assertEquals(1000, MyCustomAValue.staticValue.intValue()); } @@ -86,9 +81,8 @@ public void javaClasspathLoadAndCallTest() throws AnalysisException, InvocationT String clz = MyCustomAValue.class.getName(); String moduleDef = "module A{ int getA();}"; - String spec = "simulation \n" + "import A;\n" + "{\n" + "A obj = load(\"" + - DefaultExternalValueFactory.JavaClasspathLoaderLifecycleHandler.class.getAnnotation(IValueLifecycleHandler.ValueLifecycle.class) - .name() + "\",\"" + clz + "\"); int v = obj.getA();}"; + String spec = "simulation \n" + "import A;\n" + "{\n" + "A obj = load(\"" + JavaClasspathLoaderLifecycleHandler.class.getAnnotation( + IValueLifecycleHandler.ValueLifecycle.class).name() + "\",\"" + clz + "\"); int v = obj.getA();}"; ErrorReporter reporter = new ErrorReporter(); TypeChecker tc = new TypeChecker(reporter); @@ -96,7 +90,7 @@ public void javaClasspathLoadAndCallTest() throws AnalysisException, InvocationT boolean tcRes = tc.typeCheck(Arrays.asList(parse), new Vector<>()); MyCustomAValue.staticValue = 0; - new MableInterpreter(new DefaultExternalValueFactory(new File("target"), null)).execute(parse); + new MableInterpreter(new DefaultExternalValueFactory(new File("target"), tc::findModule, null)).execute(parse); Assertions.assertEquals(999, MyCustomAValue.staticValue.intValue()); } @@ -105,7 +99,7 @@ public static class MyCustomAValue extends ExternalModuleValue { static Integer staticValue; public MyCustomAValue(Value module) { - super(makeMembers(((IntegerValue) module).getValue()), ((IntegerValue) module).getValue()); + super(makeMembers(((NumericValue) module).intValue()), ((NumericValue) module).intValue()); } public MyCustomAValue() { diff --git a/maestro/src/test/java/org/intocps/maestro/DocumentationGettingStartedExamplesTest.java b/maestro/src/test/java/org/intocps/maestro/DocumentationGettingStartedExamplesTest.java index 4f83a77af..ad1b80d09 100644 --- a/maestro/src/test/java/org/intocps/maestro/DocumentationGettingStartedExamplesTest.java +++ b/maestro/src/test/java/org/intocps/maestro/DocumentationGettingStartedExamplesTest.java @@ -7,6 +7,7 @@ import org.intocps.maestro.core.messages.IErrorReporter; import org.intocps.maestro.interpreter.DefaultExternalValueFactory; import org.intocps.maestro.interpreter.MableInterpreter; +import org.intocps.maestro.typechecker.TypeChecker; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -40,14 +41,14 @@ public void part1() throws Exception { mabl.setVerbose(true); mabl.parse(sourceFiles); - mabl.typeCheck(); + var tcRes = mabl.typeCheck(); mabl.verify(Framework.FMI2); if (reporter.getErrorCount() > 0) { reporter.printErrors(new PrintWriter(System.err, true)); assert (false); } else { reporter.printWarnings(new PrintWriter(System.out, true)); - new MableInterpreter(new DefaultExternalValueFactory(workingDirectory, + new MableInterpreter(new DefaultExternalValueFactory(workingDirectory, name -> TypeChecker.findModule(tcRes.getValue(), name), IOUtils.toInputStream(mabl.getRuntimeDataAsJsonString(), StandardCharsets.UTF_8))).execute(mabl.getMainSimulationUnit()); FullSpecTest.compareCsvResults(new File(testFilesDirectory, "expectedoutputs.csv"), new File(workingDirectory, "outputs.csv")); } diff --git a/maestro/src/test/java/org/intocps/maestro/FullSpecCppTest.java b/maestro/src/test/java/org/intocps/maestro/FullSpecCppTest.java index 6bb894033..c0e6cd542 100644 --- a/maestro/src/test/java/org/intocps/maestro/FullSpecCppTest.java +++ b/maestro/src/test/java/org/intocps/maestro/FullSpecCppTest.java @@ -14,7 +14,6 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Disabled; import java.io.File; import java.io.IOException; @@ -79,7 +78,8 @@ protected boolean getMablVerbose() { } @Override - protected void postProcessSpec(String name, File directory, File workingDirectory, Mabl mabl, ARootDocument spec) throws Exception { + protected void postProcessSpec(String name, File directory, File workingDirectory, Mabl mabl, ARootDocument spec, + Map value) throws Exception { if (!beforeExecuted) { configureBaseProject(); } @@ -139,8 +139,8 @@ protected void postProcessSpec(String name, File directory, File workingDirector spec.apply(new DepthFirstAnalysisAdaptor() { @Override public void caseALoadExp(ALoadExp node) { - if (node.getArgs().size() == 3 && node.getArgs().get(0) instanceof AStringLiteralExp && - ((AStringLiteralExp) node.getArgs().get(0)).getValue().equals("FMI2")) { + if (node.getArgs().size() == 3 && node.getArgs().get(0) instanceof AStringLiteralExp && ((AStringLiteralExp) node.getArgs() + .get(0)).getValue().equals("FMI2")) { if (node.getArgs().get(2) instanceof AStringLiteralExp) { fmus.add(new File(((AStringLiteralExp) node.getArgs().get(2)).getValue())); } @@ -168,8 +168,8 @@ public void caseALoadExp(ALoadExp node) { } pb = new ProcessBuilder(simProjectSimFile.getAbsolutePath(), "-runtime", runtimeFileTest.getAbsolutePath()); - File simulationWorkingDir = - directory.getAbsoluteFile().getParentFile().getParentFile().getParentFile().getParentFile().getParentFile().getParentFile(); + File simulationWorkingDir = directory.getAbsoluteFile().getParentFile().getParentFile().getParentFile().getParentFile() + .getParentFile().getParentFile(); System.out.println("Simulation working dir: " + simulationWorkingDir); pb.directory(simulationWorkingDir); Assertions.assertTrue(CMakeUtil.runProcess(pb, true), "Simulation did not complete without errors (" + name + ")"); diff --git a/maestro/src/test/java/org/intocps/maestro/FullSpecTest.java b/maestro/src/test/java/org/intocps/maestro/FullSpecTest.java index cc2293ca2..def742811 100644 --- a/maestro/src/test/java/org/intocps/maestro/FullSpecTest.java +++ b/maestro/src/test/java/org/intocps/maestro/FullSpecTest.java @@ -8,6 +8,8 @@ import org.apache.commons.io.IOUtils; import org.intocps.maestro.ast.analysis.AnalysisException; import org.intocps.maestro.ast.node.ARootDocument; +import org.intocps.maestro.ast.node.INode; +import org.intocps.maestro.ast.node.PType; import org.intocps.maestro.core.Framework; import org.intocps.maestro.core.dto.FixedStepAlgorithmConfig; import org.intocps.maestro.core.messages.ErrorReporter; @@ -30,10 +32,7 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; -import java.util.Arrays; -import java.util.LinkedList; -import java.util.List; -import java.util.Objects; +import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -83,9 +82,31 @@ public static void assertResultEqualsDiff(InputStream actual, InputStream expect // Compute diff. Get the Patch object. Patch is the container for computed deltas. Patch patch = DiffUtils.diff(original, revised); + System.err.println("Diff"); for (Delta delta : patch.getDeltas()) { - System.err.println(delta); - Assertions.fail("Expected result and actual differ: " + delta); + StringBuilder sb = new StringBuilder(); + switch (delta.getType()) { + + case CHANGE: + sb.append("--- CHANGE ---\n"); + break; + case DELETE: + sb.append("--- DELETE ---\n"); + break; + case INSERT: + sb.append("--- INSERT ---\n"); + break; + } + + sb.append(original.stream().skip(delta.getOriginal().getPosition() - 1).map(l -> " " + l).limit(1).collect(Collectors.joining("\n"))); + sb.append("\n"); + sb.append(delta.getOriginal().getLines().stream().map(l -> ">" + l).limit(3).collect(Collectors.joining("\n"))); + sb.append("\n"); + sb.append("--- \n"); + sb.append(revised.stream().skip(delta.getOriginal().getPosition() - 1).map(l -> " " + l).limit(1).collect(Collectors.joining("\n"))); + sb.append("\n"); + sb.append(delta.getRevised().getLines().stream().map(l -> "<" + l).limit(3).collect(Collectors.joining("\n"))); + Assertions.fail("Expected result and actual differ: \n" + sb); } } @@ -101,7 +122,7 @@ public static void compareCsvResults(File expectedCsvFile, File actualCsvFile) t boolean actualOutputsCsvExists = actualCsvFile.exists(); boolean expectedOutputsCsvExists = expectedCsvFile.exists(); if (actualOutputsCsvExists && expectedOutputsCsvExists) { - assertResultEqualsDiff(new FileInputStream(actualCsvFile), new FileInputStream(expectedCsvFile)); + assertResultEqualsDiff(new FileInputStream(expectedCsvFile), new FileInputStream(actualCsvFile)); } else { StringBuilder sb = new StringBuilder(); @@ -147,27 +168,28 @@ public void test(String name, File directory) throws Exception { mabl.setReporter(reporter); mabl.setVerbose(getMablVerbose()); - ARootDocument spec = generateSpec(mabl, directory, workingDirectory); - postProcessSpec(name, directory, workingDirectory, mabl, spec); + Map.Entry> res = generateSpec(mabl, directory, workingDirectory); + postProcessSpec(name, directory, workingDirectory, mabl, res.getKey(), res.getValue()); } protected boolean getMablVerbose() { return true; } - protected void postProcessSpec(String name, File directory, File workingDirectory, Mabl mabl, ARootDocument spec) throws Exception { - interpretSpec(directory, workingDirectory, mabl, spec); + protected void postProcessSpec(String name, File directory, File workingDirectory, Mabl mabl, ARootDocument spec, + Map types) throws Exception { + interpretSpec(directory, workingDirectory, mabl, spec, types); } - protected void interpretSpec(File directory, File workingDirectory, Mabl mabl, ARootDocument spec) throws Exception { - new MableInterpreter(new DefaultExternalValueFactory(workingDirectory, + protected void interpretSpec(File directory, File workingDirectory, Mabl mabl, ARootDocument spec, Map types) throws Exception { + new MableInterpreter(new DefaultExternalValueFactory(workingDirectory, name -> TypeChecker.findModule(types, name), IOUtils.toInputStream(mabl.getRuntimeDataAsJsonString(), StandardCharsets.UTF_8))).execute(spec); compareCSVs(new File(directory, "expectedoutputs.csv"), new File(workingDirectory, "outputs.csv")); } @NotNull - private ARootDocument generateSpec(Mabl mabl, File directory, File workingDirectory) throws Exception { + private Map.Entry> generateSpec(Mabl mabl, File directory, File workingDirectory) throws Exception { File specFolder = new File(workingDirectory, "specs"); specFolder.mkdirs(); @@ -190,16 +212,16 @@ private ARootDocument generateSpec(Mabl mabl, File directory, File workingDirect postParse(mabl); if (useTemplate) { - Fmi2EnvironmentConfiguration simulationConfiguration = - new ObjectMapper().readValue(new File(directory, "env.json"), Fmi2EnvironmentConfiguration.class); + Fmi2EnvironmentConfiguration simulationConfiguration = new ObjectMapper().readValue(new File(directory, "env.json"), + Fmi2EnvironmentConfiguration.class); Fmi2SimulationEnvironmentConfiguration simulationEnvironmentConfiguration = Fmi2SimulationEnvironmentConfiguration.createFromJsonString( new String(Files.readAllBytes(Paths.get(new File(directory, "env.json").getAbsolutePath())))); - MaBLTemplateConfiguration.MaBLTemplateConfigurationBuilder builder = - MaBLTemplateConfiguration.MaBLTemplateConfigurationBuilder.getBuilder().useInitializer(testJsonObject.initialize, "{}") - .setFramework(Framework.FMI2).setFrameworkConfig(Framework.FMI2, simulationEnvironmentConfiguration); + MaBLTemplateConfiguration.MaBLTemplateConfigurationBuilder builder = MaBLTemplateConfiguration.MaBLTemplateConfigurationBuilder.getBuilder() + .useInitializer(testJsonObject.initialize, "{}").setFramework(Framework.FMI2) + .setFrameworkConfig(Framework.FMI2, simulationEnvironmentConfiguration); Fmi2SimulationEnvironment environment = Fmi2SimulationEnvironment.of(simulationEnvironmentConfiguration, mabl.getReporter()); if (testJsonObject.useLogLevels) { @@ -207,8 +229,7 @@ private ARootDocument generateSpec(Mabl mabl, File directory, File workingDirect } if (testJsonObject.simulate && simulationConfiguration.algorithm instanceof Fmi2EnvironmentConfiguration.FixedStepAlgorithmConfig) { - Fmi2EnvironmentConfiguration.FixedStepAlgorithmConfig a = - (Fmi2EnvironmentConfiguration.FixedStepAlgorithmConfig) simulationConfiguration.algorithm; + Fmi2EnvironmentConfiguration.FixedStepAlgorithmConfig a = (Fmi2EnvironmentConfiguration.FixedStepAlgorithmConfig) simulationConfiguration.algorithm; JacobianStepConfig algorithmConfig = new JacobianStepConfig(); algorithmConfig.startTime = 0.0; @@ -225,7 +246,7 @@ private ARootDocument generateSpec(Mabl mabl, File directory, File workingDirect } mabl.expand(); - mabl.typeCheck(); + var tcRes = mabl.typeCheck(); mabl.verify(Framework.FMI2); @@ -240,7 +261,7 @@ private ARootDocument generateSpec(Mabl mabl, File directory, File workingDirect mabl.dump(workingDirectory); Assertions.assertTrue(new File(workingDirectory, Mabl.MAIN_SPEC_DEFAULT_FILENAME).exists(), "Spec file must exist"); Assertions.assertTrue(new File(workingDirectory, Mabl.MAIN_SPEC_DEFAULT_RUNTIME_FILENAME).exists(), "Spec file must exist"); - return mabl.getMainSimulationUnit(); + return Map.entry(mabl.getMainSimulationUnit(), tcRes.getValue()); } protected void postParse(Mabl mabl) throws AnalysisException { diff --git a/maestro/src/test/java/org/intocps/maestro/MaBLTemplateGeneratorTest.java b/maestro/src/test/java/org/intocps/maestro/MaBLTemplateGeneratorTest.java index 25e159767..8e754359e 100644 --- a/maestro/src/test/java/org/intocps/maestro/MaBLTemplateGeneratorTest.java +++ b/maestro/src/test/java/org/intocps/maestro/MaBLTemplateGeneratorTest.java @@ -24,6 +24,7 @@ import org.intocps.maestro.plugin.JacobianStepConfig; import org.intocps.maestro.template.MaBLTemplateConfiguration; import org.intocps.maestro.template.MaBLTemplateGenerator; +import org.intocps.maestro.typechecker.TypeChecker; import org.intocps.maestro.util.MablModuleProvider; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -94,8 +95,8 @@ public void caseAVariableDeclaration(AVariableDeclaration node, AtomicBoolean fo } assert instanceMappingStmUntyped instanceof AInstanceMappingStm; var instanceMappingStm = (AInstanceMappingStm) instanceMappingStmUntyped; - foundMapping.set(instanceMappingStm.getIdentifier().getText().contains(FAULTINJECT_POSTFIX) && - instanceMappingStm.getName().equalsIgnoreCase("wtinstance")); + foundMapping.set(instanceMappingStm.getIdentifier().getText().contains(FAULTINJECT_POSTFIX) && instanceMappingStm.getName() + .equalsIgnoreCase("wtinstance")); } } @@ -177,8 +178,8 @@ public void caseACallExp(ACallExp node) throws AnalysisException { if (lastArg instanceof ABoolLiteralExp && !((ABoolLiteralExp) lastArg).getValue()) { if (node.getMethodName().getText().equals("initialize")) { flagInitialize.set(true); - } else if (node.getMethodName().getText().equals("fixedStepSizeTransfer") || - node.getMethodName().getText().equals("fixedStepSize")) { + } else if (node.getMethodName().getText().equals("fixedStepSizeTransfer") || node.getMethodName().getText() + .equals("fixedStepSize")) { flagFixedStep.set(true); } } @@ -369,7 +370,7 @@ public void generateSingleWaterTankTemplateMEnv() throws Exception { mabl.setVerbose(true); mabl.parse(CharStreams.fromString(PrettyPrinter.print(aSimulationSpecificationCompilationUnit))); mabl.expand(); - mabl.typeCheck(); + var tcRes = mabl.typeCheck(); mabl.verify(Framework.FMI2); mabl.setRuntimeEnvironmentVariables((Map) configData.get("parameters")); mabl.dump(workingDir); @@ -383,7 +384,7 @@ public void generateSingleWaterTankTemplateMEnv() throws Exception { reporter.printWarnings(new PrintWriter(System.out, true)); } - new MableInterpreter(new DefaultExternalValueFactory(workingDir, + new MableInterpreter(new DefaultExternalValueFactory(workingDir, name -> TypeChecker.findModule(tcRes.getValue(), name), IOUtils.toInputStream(mabl.getRuntimeDataAsJsonString(), StandardCharsets.UTF_8))).execute(mabl.getMainSimulationUnit()); } @@ -393,8 +394,8 @@ public void generateSingleWaterTankFawultInjectTemplate() throws Exception { final double endTime = 10.0; final double stepSize = 0.1; File configurationDirectory = Paths.get("src", "test", "resources", "specifications", "full", "initialize_singleWaterTank").toFile(); - File faultInjectionFile = - Paths.get("src", "test", "resources", "org", "into-cps", "maestro", "faultinjection", "dummyfaultinjectfile.xml").toFile(); + File faultInjectionFile = Paths.get("src", "test", "resources", "org", "into-cps", "maestro", "faultinjection", "dummyfaultinjectfile.xml") + .toFile(); Fmi2SimulationEnvironmentConfiguration simulationEnvironmentConfiguration = Fmi2SimulationEnvironmentConfiguration.createFromJsonString( new String(Files.readAllBytes(Paths.get(new File(configurationDirectory, "env.json").getAbsolutePath())))); simulationEnvironmentConfiguration.faultInjectInstances = Map.of("crtlInstance", "constraintid"); diff --git a/maestro/src/test/java/org/intocps/maestro/TemplateGeneratorFromScenarioTest.java b/maestro/src/test/java/org/intocps/maestro/TemplateGeneratorFromScenarioTest.java index 73275f693..4e51cfb12 100644 --- a/maestro/src/test/java/org/intocps/maestro/TemplateGeneratorFromScenarioTest.java +++ b/maestro/src/test/java/org/intocps/maestro/TemplateGeneratorFromScenarioTest.java @@ -16,6 +16,7 @@ import org.intocps.maestro.interpreter.DefaultExternalValueFactory; import org.intocps.maestro.interpreter.MableInterpreter; import org.intocps.maestro.template.ScenarioConfiguration; +import org.intocps.maestro.typechecker.TypeChecker; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; @@ -65,46 +66,37 @@ public void generateMaBLSpecFromExecutableScenario(String name, File directory) // Setup values from JSON Fmi2SimulationEnvironmentConfiguration simulationConfiguration = new Fmi2SimulationEnvironmentConfiguration( - jsonMapper.readValue(jsonMapper.treeAsTokens(executableMM.get("multiModel").get("connections")), new TypeReference<>() { - }), jsonMapper.readValue(jsonMapper.treeAsTokens(executableMM.get("multiModel").get("fmus")), new TypeReference<>() { - })); + jsonMapper.readValue(jsonMapper.treeAsTokens(executableMM.get("multiModel").get("connections")), new TypeReference<>() {}), + jsonMapper.readValue(jsonMapper.treeAsTokens(executableMM.get("multiModel").get("fmus")), new TypeReference<>() {})); - Map parameters = - jsonMapper.readValue(jsonMapper.treeAsTokens(executableMM.get("multiModel").get("parameters")), new TypeReference<>() { - }); + Map parameters = jsonMapper.readValue(jsonMapper.treeAsTokens(executableMM.get("multiModel").get("parameters")), + new TypeReference<>() {}); Double relTol = jsonMapper.readValue(jsonMapper.treeAsTokens(executableMM.get("executionParameters").get("convergenceRelativeTolerance")), - new TypeReference<>() { - }); + new TypeReference<>() {}); Double absTol = jsonMapper.readValue(jsonMapper.treeAsTokens(executableMM.get("executionParameters").get("convergenceAbsoluteTolerance")), - new TypeReference<>() { - }); - Integer convergenceAttempts = - jsonMapper.readValue(jsonMapper.treeAsTokens(executableMM.get("executionParameters").get("convergenceAttempts")), - new TypeReference<>() { - }); - Double startTime = - jsonMapper.readValue(jsonMapper.treeAsTokens(executableMM.get("executionParameters").get("startTime")), new TypeReference<>() { - }); - Double endTime = jsonMapper.readValue(jsonMapper.treeAsTokens(executableMM.get("executionParameters").get("endTime")), new TypeReference<>() { - }); - Double stepSize = - jsonMapper.readValue(jsonMapper.treeAsTokens(executableMM.get("executionParameters").get("stepSize")), new TypeReference<>() { - }); + new TypeReference<>() {}); + Integer convergenceAttempts = jsonMapper.readValue( + jsonMapper.treeAsTokens(executableMM.get("executionParameters").get("convergenceAttempts")), new TypeReference<>() {}); + Double startTime = jsonMapper.readValue(jsonMapper.treeAsTokens(executableMM.get("executionParameters").get("startTime")), + new TypeReference<>() {}); + Double endTime = jsonMapper.readValue(jsonMapper.treeAsTokens(executableMM.get("executionParameters").get("endTime")), + new TypeReference<>() {}); + Double stepSize = jsonMapper.readValue(jsonMapper.treeAsTokens(executableMM.get("executionParameters").get("stepSize")), + new TypeReference<>() {}); MasterModel masterModel = ScenarioLoader.load(new ByteArrayInputStream(executableMM.get("masterModel").textValue().getBytes())); // Setup scenarioConfiguration Fmi2SimulationEnvironment simulationEnvironment = Fmi2SimulationEnvironment.of(simulationConfiguration, errorReporter); - ScenarioConfiguration scenarioConfiguration = - new ScenarioConfiguration(simulationEnvironment, masterModel, parameters, relTol, absTol, convergenceAttempts, startTime, endTime, - stepSize, Pair.of(Framework.FMI2, simulationConfiguration), false, Map.of()); + ScenarioConfiguration scenarioConfiguration = new ScenarioConfiguration(simulationEnvironment, masterModel, parameters, relTol, absTol, + convergenceAttempts, startTime, endTime, stepSize, Pair.of(Framework.FMI2, simulationConfiguration), false, Map.of()); // ACT // This calls TemplateGeneratorFromScenario.generateTemplate which is the method to test mabl.generateSpec(scenarioConfiguration); mabl.expand(); - mabl.typeCheck(); + var tcRes = mabl.typeCheck(); mabl.verify(Framework.FMI2); // ASSERT @@ -119,7 +111,7 @@ public void generateMaBLSpecFromExecutableScenario(String name, File directory) mabl.dump(workingDirectory); Assertions.assertTrue(new File(workingDirectory, Mabl.MAIN_SPEC_DEFAULT_FILENAME).exists(), "Spec file must exist"); Assertions.assertTrue(new File(workingDirectory, Mabl.MAIN_SPEC_DEFAULT_RUNTIME_FILENAME).exists(), "Spec file must exist"); - new MableInterpreter(new DefaultExternalValueFactory(workingDirectory, + new MableInterpreter(new DefaultExternalValueFactory(workingDirectory, n -> TypeChecker.findModule(tcRes.getValue(), n), IOUtils.toInputStream(mabl.getRuntimeDataAsJsonString(), StandardCharsets.UTF_8))).execute(mabl.getMainSimulationUnit()); diff --git a/maestro/src/test/java/org/intocps/maestro/TransitionTest.java b/maestro/src/test/java/org/intocps/maestro/TransitionTest.java index cf73d4a20..4f1a4c3e8 100644 --- a/maestro/src/test/java/org/intocps/maestro/TransitionTest.java +++ b/maestro/src/test/java/org/intocps/maestro/TransitionTest.java @@ -1,8 +1,10 @@ package org.intocps.maestro; +import org.intocps.maestro.ast.AModuleDeclaration; import org.intocps.maestro.ast.node.ARootDocument; import org.intocps.maestro.cli.MablCliUtil; import org.intocps.maestro.interpreter.*; +import org.intocps.maestro.typechecker.TypeChecker; import org.junit.Assert; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assumptions; @@ -126,7 +128,7 @@ public void transfer(Interpreter interpreter, ITTransitionInfo info) { } }; - new MableInterpreter(new DefaultExternalValueFactory(stageOutput.toFile(), c), tm).execute(util.getMainSimulationUnit()); + new MableInterpreter(new DefaultExternalValueFactory(stageOutput.toFile(), util::findModule, c), tm).execute(util.getMainSimulationUnit()); // check that the two stages was taken Assertions.assertTrue(stageOutput.resolve("outputs.csv").toFile().exists()); @@ -166,5 +168,9 @@ public MablCliUtilTesting(File workingDirectory, File debugOutputFolder, Mabl.Ma public ARootDocument getMainSimulationUnit() { return super.mabl.getMainSimulationUnit(); } + + public AModuleDeclaration findModule(String name) { + return TypeChecker.findModule(typeCheckResult.getValue(), name); + } } } diff --git a/maestro/src/test/java/org/intocps/maestro/VariableStepTest.java b/maestro/src/test/java/org/intocps/maestro/VariableStepTest.java index abc7dc2f4..266396b71 100644 --- a/maestro/src/test/java/org/intocps/maestro/VariableStepTest.java +++ b/maestro/src/test/java/org/intocps/maestro/VariableStepTest.java @@ -7,6 +7,7 @@ import org.intocps.maestro.core.messages.IErrorReporter; import org.intocps.maestro.interpreter.DefaultExternalValueFactory; import org.intocps.maestro.interpreter.MableInterpreter; +import org.intocps.maestro.typechecker.TypeChecker; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -23,8 +24,8 @@ public class VariableStepTest { public void variableStepSizeMablTest() throws Exception { File testFilesDirectory = new File(Objects.requireNonNull(VariableStepTest.class.getClassLoader().getResource("variable_step")).getPath()); - List sourceFiles = Collections - .singletonList(new File(testFilesDirectory.toPath().resolve("variableStepSizeMablTest").resolve("variableStepTest.mabl").toString())); + List sourceFiles = Collections.singletonList( + new File(testFilesDirectory.toPath().resolve("variableStepSizeMablTest").resolve("variableStepTest.mabl").toString())); File specificationDirectory = new File("target", "variable_step/spec"); File workingDirectory = new File("target", "variable_step/working"); @@ -37,14 +38,14 @@ public void variableStepSizeMablTest() throws Exception { mabl.setVerbose(true); mabl.parse(sourceFiles); - mabl.typeCheck(); + var tcRes = mabl.typeCheck(); mabl.verify(Framework.FMI2); if (reporter.getErrorCount() > 0) { reporter.printErrors(new PrintWriter(System.err, true)); assert (false); } else { reporter.printWarnings(new PrintWriter(System.out, true)); - new MableInterpreter(new DefaultExternalValueFactory(workingDirectory, + new MableInterpreter(new DefaultExternalValueFactory(workingDirectory, name -> TypeChecker.findModule(tcRes.getValue(), name), IOUtils.toInputStream(mabl.getRuntimeDataAsJsonString(), StandardCharsets.UTF_8))).execute(mabl.getMainSimulationUnit()); FullSpecTest.compareCsvResults( @@ -69,8 +70,8 @@ public void invalidDerivativesArraySizeTest() { } private void interpretMablSpec(Function> generateSourceFilesFunc) throws Exception { - List sourceFiles = generateSourceFilesFunc - .apply(new File(Objects.requireNonNull(VariableStepTest.class.getClassLoader().getResource("variable_step")).getPath())); + List sourceFiles = generateSourceFilesFunc.apply( + new File(Objects.requireNonNull(VariableStepTest.class.getClassLoader().getResource("variable_step")).getPath())); IErrorReporter reporter = new ErrorReporter(); File specificationDirectory = new File("target", "variable_step/spec"); @@ -83,7 +84,7 @@ private void interpretMablSpec(Function> generateSourceFilesFun mabl.setVerbose(true); mabl.parse(sourceFiles); - mabl.typeCheck(); + var tcRes = mabl.typeCheck(); mabl.verify(Framework.FMI2); if (reporter.getErrorCount() > 0) { reporter.printErrors(new PrintWriter(System.err, true)); @@ -91,8 +92,7 @@ private void interpretMablSpec(Function> generateSourceFilesFun } reporter.printWarnings(new PrintWriter(System.out, true)); - new MableInterpreter( - new DefaultExternalValueFactory(workingDirectory, IOUtils.toInputStream(mabl.getRuntimeDataAsJsonString(), StandardCharsets.UTF_8))) - .execute(mabl.getMainSimulationUnit()); + new MableInterpreter(new DefaultExternalValueFactory(workingDirectory, name -> TypeChecker.findModule(tcRes.getValue(), name), + IOUtils.toInputStream(mabl.getRuntimeDataAsJsonString(), StandardCharsets.UTF_8))).execute(mabl.getMainSimulationUnit()); } } diff --git a/maestro/src/test/java/org/intocps/maestro/WatertankApiTest.java b/maestro/src/test/java/org/intocps/maestro/WatertankApiTest.java index b33ae5251..560b063b7 100644 --- a/maestro/src/test/java/org/intocps/maestro/WatertankApiTest.java +++ b/maestro/src/test/java/org/intocps/maestro/WatertankApiTest.java @@ -22,6 +22,7 @@ import org.intocps.maestro.framework.fmi2.api.mabl.variables.FmuVariableFmi2Api; import org.intocps.maestro.interpreter.DefaultExternalValueFactory; import org.intocps.maestro.interpreter.MableInterpreter; +import org.intocps.maestro.typechecker.TypeChecker; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -41,11 +42,11 @@ public void test() throws Exception { DynamicActiveBuilderScope ds = builder.getDynamicScope(); - FmuVariableFmi2Api controllerFmu = - ds.createFMU("controllerFmu", "FMI2", Paths.get("src", "test", "resources", "watertankcontroller-c.fmu").toUri().toASCIIString()); + FmuVariableFmi2Api controllerFmu = ds.createFMU("controllerFmu", "FMI2", + Paths.get("src", "test", "resources", "watertankcontroller-c.fmu").toUri().toASCIIString()); - FmuVariableFmi2Api tankFmu = - ds.createFMU("tankFmu", "FMI2", Paths.get("src", "test", "resources", "singlewatertank-20sim.fmu").toUri().toASCIIString()); + FmuVariableFmi2Api tankFmu = ds.createFMU("tankFmu", "FMI2", + Paths.get("src", "test", "resources", "singlewatertank-20sim.fmu").toUri().toASCIIString()); ComponentVariableFmi2Api controller = controllerFmu.instantiate("controller"); @@ -132,8 +133,8 @@ private void check(ASimulationSpecificationCompilationUnit program, String runti } mabl.dump(workingDirectory); - new MableInterpreter(new DefaultExternalValueFactory(workingDirectory, IOUtils.toInputStream(runtimeData, StandardCharsets.UTF_8))).execute( - mabl.getMainSimulationUnit()); + new MableInterpreter(new DefaultExternalValueFactory(workingDirectory, name -> TypeChecker.findModule(tcRef.getValue(), name), + IOUtils.toInputStream(runtimeData, StandardCharsets.UTF_8))).execute(mabl.getMainSimulationUnit()); MablCppCodeGenerator cppCodeGenerator = new MablCppCodeGenerator(workingDirectory); cppCodeGenerator.generate(mabl.getMainSimulationUnit(), tcRef.getValue()); diff --git a/pom.xml b/pom.xml index ad58bbf8c..c5dce8ffa 100644 --- a/pom.xml +++ b/pom.xml @@ -24,7 +24,7 @@ 11 11 2.17.1 - 1.3.6-SNAPSHOT + 1.3.7-SNAPSHOT 1.0.10 1.5.0 2.13.5 diff --git a/typechecker/src/main/java/org/intocps/maestro/typechecker/TypeCheckVisitor.java b/typechecker/src/main/java/org/intocps/maestro/typechecker/TypeCheckVisitor.java index caf99433f..d86911014 100644 --- a/typechecker/src/main/java/org/intocps/maestro/typechecker/TypeCheckVisitor.java +++ b/typechecker/src/main/java/org/intocps/maestro/typechecker/TypeCheckVisitor.java @@ -32,6 +32,36 @@ public TypeCheckVisitor(IErrorReporter errorReporter) { astFactory = new MableAstFactory(); } + static SNumericPrimitiveType detectType(int value) { + if (value <= 0xff) { + return new AByteNumericPrimitiveType(); + } else if (value <= Short.MAX_VALUE) { + return new AShortNumericPrimitiveType(); + } else { + return new AIntNumericPrimitiveType(); + } + } + + static SNumericPrimitiveType detectType(long value) { + if (value <= Integer.MAX_VALUE) { + return detectType((int) value); + } else { + return new ALongNumericPrimitiveType(); + } + } + + static SNumericPrimitiveType detectType(double value) { + + if ((value % 1) == 0) { + //whole number + return detectType((long) value); + } else if (value <= Float.MAX_VALUE) { + return new AFloatNumericPrimitiveType(); + } else { + return new ARealNumericPrimitiveType(); + } + } + @Override public PType createNewReturnValue(INode node, Context info) throws AnalysisException { return null; @@ -47,7 +77,6 @@ public PType defaultPInitializer(PInitializer node, Context ctxt) throws Analysi return super.defaultPInitializer(node, ctxt); } - @Override public PType caseAErrorStm(AErrorStm node, Context ctxt) throws AnalysisException { return store(node, new AVoidType()); @@ -113,7 +142,7 @@ public PType caseAArrayIndexExp(AArrayIndexExp node, Context ctxt) throws Analys for (PExp index : node.getIndices()) { PType type = index.apply(this, ctxt); - if (!typeComparator.compatible(AIntNumericPrimitiveType.class, type)) { + if (!typeComparator.compatible(new AIntNumericPrimitiveType(), type)) { errorReporter.report(-5, "Array index must be an integer actual: " + type, null); } } @@ -145,12 +174,6 @@ public PType caseALoadExp(ALoadExp node, Context ctxt) throws AnalysisException if (node.getArgs() == null || node.getArgs().isEmpty()) { errorReporter.report(-5, "Wrong number of arguments to load. At least a type is required: " + node, null); } else { - // PType argType = node.getArgs().get(0).apply(this, ctxt); - - // PExp typeArg = node.getArgs().get(0); - // if (!(typeArg instanceof AStringLiteralExp)) { - // errorReporter.report(-5, "First argument must be a string.: " + node, null); - // } PExp loaderNameArg = node.getArgs().get(0); if (!(loaderNameArg instanceof AStringLiteralExp)) { @@ -227,7 +250,11 @@ public PType caseAArrayInitializer(AArrayInitializer node, Context ctxt) throws PType elementType = node.getExp().get(i).apply(this, ctxt); if (!typeComparator.compatible(type, elementType)) { //is ok - errorReporter.warning(0, "Array initializer types mixed. Expected: " + type + " but found: " + elementType, null); + if (!(node.parent() instanceof AVariableDeclaration && + ((AVariableDeclaration) node.parent()).getType() instanceof AUnknownType)) { + //we only print this id the variable type is known + errorReporter.warning(0, "Array initializer types mixed. Expected: " + type + " but found: " + elementType, null); + } type = newAUnknownType(); } } @@ -621,16 +648,31 @@ public PType checkNumeric(SBinaryExp node, Context ctxt) throws AnalysisExceptio return MableAstFactory.newARealNumericPrimitiveType(); } else if (right instanceof ARealNumericPrimitiveType) { return MableAstFactory.newARealNumericPrimitiveType(); + } else if (left instanceof AFloatNumericPrimitiveType) { + return MableAstFactory.newARealNumericPrimitiveType(); + } else if (right instanceof AFloatNumericPrimitiveType) { + return MableAstFactory.newARealNumericPrimitiveType(); } else if (left instanceof AUIntNumericPrimitiveType) { return MableAstFactory.newAUIntNumericPrimitiveType(); } else if (right instanceof AUIntNumericPrimitiveType) { return MableAstFactory.newAUIntNumericPrimitiveType(); - } else if (left instanceof AIntNumericPrimitiveType) { - return MableAstFactory.newAIntNumericPrimitiveType(); - } else if (right instanceof AIntNumericPrimitiveType) { + } else { return MableAstFactory.newAIntNumericPrimitiveType(); } - return null; + // if (left instanceof AIntNumericPrimitiveType) { + // return MableAstFactory.newAIntNumericPrimitiveType(); + // } else if (right instanceof AIntNumericPrimitiveType) { + // return MableAstFactory.newAIntNumericPrimitiveType(); + // } else if (left instanceof AShortNumericPrimitiveType) { + // return MableAstFactory.newAIntNumericPrimitiveType(); + // } else if (right instanceof AShortNumericPrimitiveType) { + // return MableAstFactory.newAIntNumericPrimitiveType(); + // } else if (left instanceof AByteNumericPrimitiveType) { + // return MableAstFactory.newAIntNumericPrimitiveType(); + // } else if (right instanceof AByteNumericPrimitiveType) { + // return MableAstFactory.newAIntNumericPrimitiveType(); + // } + // return null; } public PType checkNumericComparizon(SBinaryExp node, Context ctxt) throws AnalysisException { @@ -668,22 +710,22 @@ public PType caseAStringLiteralExp(AStringLiteralExp node, Context ctxt) throws @Override public PType caseARealLiteralExp(ARealLiteralExp node, Context ctxt) throws AnalysisException { - double value = node.getValue(); - if (Math.round(value) == value) { - if (value < 0) { - return store(node, MableAstFactory.newIntType()); - } else if (value == 0) { - - //nat - return store(node, MableAstFactory.newIntType()); - } else { - //natone - return store(node, MableAstFactory.newIntType()); - } - } else { - return store(node, MableAstFactory.newRealType()); // Note, "1.234" is really "1234/1000" (a rat) - } - + // double value = node.getValue(); + // if (Math.round(value) == value) { + // if (value < 0) { + // return store(node, MableAstFactory.newIntType()); + // } else if (value == 0) { + // + // //nat + // return store(node, MableAstFactory.newIntType()); + // } else { + // //natone + // return store(node, MableAstFactory.newIntType()); + // } + // } else { + // return store(node, MableAstFactory.newRealType()); // Note, "1.234" is really "1234/1000" (a rat) + // } + return store(node, detectType(node.getValue())); } @Override @@ -699,16 +741,8 @@ public PType caseAUIntLiteralExp(AUIntLiteralExp node, Context ctxt) throws Anal @Override public PType caseAIntLiteralExp(AIntLiteralExp node, Context ctxt) throws AnalysisException { - int value = node.getValue(); - if (value < 0) { - return store(node, MableAstFactory.newIntType()); - } else if (value == 0) { - //nat - return store(node, MableAstFactory.newIntType()); - } else { - //natone - return store(node, MableAstFactory.newIntType()); - } + + return store(node, detectType(node.getValue())); } @Override @@ -921,10 +955,13 @@ public PType caseANotEqualBinaryExp(ANotEqualBinaryExp node, Context ctxt) throw } private ABooleanPrimitiveType checkEquality(INode node, PType left, PType right) { - //Commutative - if (!typeComparator.compatible(left, right) && !typeComparator.compatible(right, left)) { - errorReporter.report(-5, "Left and right part of expression are not compatible: " + node, null); + //first check for numbers as we can always compare these + if (!typeComparator.compatible(SNumericPrimitiveType.class, left) && !typeComparator.compatible(SNumericPrimitiveType.class, right)) { + //Commutative + if (!typeComparator.compatible(left, right) && !typeComparator.compatible(right, left)) { + errorReporter.report(-5, "Left and right part of expression are not compatible: " + node, null); + } } return store(node, MableAstFactory.newABoleanPrimitiveType()); } @@ -948,8 +985,8 @@ public PType caseABreakStm(ABreakStm node, Context ctxt) throws AnalysisExceptio @Override public PType caseAArrayStateDesignator(AArrayStateDesignator node, Context ctxt) throws AnalysisException { PType indexType = node.getExp().apply(this, ctxt); - if (!(indexType instanceof AIntNumericPrimitiveType)) { - errorReporter.report(-5, "Index has to be of int type." + node, null); + if (!typeComparator.compatible(new AIntNumericPrimitiveType(), indexType)) { + errorReporter.report(-5, "Index has to be of int type: '" + indexType + "' node " + node, null); } // Peel of the array type PType targetType = node.getTarget().apply(this, ctxt); diff --git a/typechecker/src/main/java/org/intocps/maestro/typechecker/TypeChecker.java b/typechecker/src/main/java/org/intocps/maestro/typechecker/TypeChecker.java index a5ee6c0f3..57d8915e4 100644 --- a/typechecker/src/main/java/org/intocps/maestro/typechecker/TypeChecker.java +++ b/typechecker/src/main/java/org/intocps/maestro/typechecker/TypeChecker.java @@ -1,7 +1,9 @@ package org.intocps.maestro.typechecker; +import org.intocps.maestro.ast.AModuleDeclaration; import org.intocps.maestro.ast.PDeclaration; import org.intocps.maestro.ast.analysis.AnalysisException; +import org.intocps.maestro.ast.node.AImportedModuleCompilationUnit; import org.intocps.maestro.ast.node.ARootDocument; import org.intocps.maestro.ast.node.INode; import org.intocps.maestro.ast.node.PType; @@ -44,4 +46,14 @@ public boolean typeCheck(List documents, List tcResult, String name) { + return tcResult.keySet().stream().filter(AImportedModuleCompilationUnit.class::isInstance) + .map(im -> ((AImportedModuleCompilationUnit) im).getModule()).filter(m -> m.getName().getText().equals(name)).findFirst() + .orElse(null); + } } diff --git a/typechecker/src/main/java/org/intocps/maestro/typechecker/TypeComparator.java b/typechecker/src/main/java/org/intocps/maestro/typechecker/TypeComparator.java index 438621e3e..b372ec7eb 100644 --- a/typechecker/src/main/java/org/intocps/maestro/typechecker/TypeComparator.java +++ b/typechecker/src/main/java/org/intocps/maestro/typechecker/TypeComparator.java @@ -1,10 +1,14 @@ package org.intocps.maestro.typechecker; import org.intocps.maestro.ast.node.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.List; +import java.util.Vector; public class TypeComparator { + final static Logger logger = LoggerFactory.getLogger(TypeComparator.class); public synchronized boolean compatible(Class to, PType from) { if (to == AUnknownType.class) { @@ -51,6 +55,45 @@ public synchronized boolean compatible(PType to, PType from) { return compatible(((AReferenceType) to).getType(), ((AReferenceType) from).getType()); } + /* + * #primitive + = {boolean} + | {string} + | #numeric + ; + +#numeric + = {real} + | {int} + | {uInt} + | {float} + | {short} + | {byte} + | {long} + ; + * + * _Bool < char < short < int < long < long long + * + * float < double < long double +*/ + //ABooleanPrimitiveType.class, + Class types[] = new Class[]{AByteNumericPrimitiveType.class, AShortNumericPrimitiveType.class, AIntNumericPrimitiveType.class, + AUIntNumericPrimitiveType.class, ALongNumericPrimitiveType.class, AFloatNumericPrimitiveType.class, ARealNumericPrimitiveType.class}; + + // Class typesDecimal[] = new Class[]{AFloatNumericPrimitiveType.class, ARealNumericPrimitiveType.class}; + List primitiveTypeRanks = new Vector<>(); + + for (Class type : types) { + primitiveTypeRanks.add(type); + } + int toIndex = primitiveTypeRanks.indexOf(to.getClass()); + int fromIndex = primitiveTypeRanks.indexOf(from.getClass()); + if (toIndex > -1 && fromIndex > -1 && fromIndex <= toIndex) { + // logger.info("Type compatability {} -> {} OK", from.getClass().getSimpleName(), to.getClass().getSimpleName()); + return true; + } + + //numbers if (to instanceof ARealNumericPrimitiveType && (from instanceof ARealNumericPrimitiveType || from instanceof AIntNumericPrimitiveType)) { return true; diff --git a/typechecker/src/main/resources/org/intocps/maestro/typechecker/FMI3.mabl b/typechecker/src/main/resources/org/intocps/maestro/typechecker/FMI3.mabl index ddeb5ba35..f6064a471 100644 --- a/typechecker/src/main/resources/org/intocps/maestro/typechecker/FMI3.mabl +++ b/typechecker/src/main/resources/org/intocps/maestro/typechecker/FMI3.mabl @@ -2,13 +2,13 @@ module FMI3 import FMI2Component; import FMI3Instance; import FMI2; { - FMI3Instance instantiateCoSimulation(string instanceName, string instantiationToken, string resourceLocation, bool visible, bool loggingOn, + FMI3Instance instantiateCoSimulation(string instanceName, bool visible, bool loggingOn, bool eventModeUsed, bool earlyReturnAllowed, uint[] requiredIntermediateVariables); //, ILogMessageCallback logMessage,IIntermediateUpdateCallback intermediateUpdate - FMI2Component instantiateCoSimulationWrapAsFmi2(string instanceName, string instantiationToken, string resourceLocation, bool visible, bool loggingOn, + FMI2Component instantiateCoSimulationWrapAsFmi2(string instanceName, bool visible, bool loggingOn, bool eventModeUsed, bool earlyReturnAllowed, uint[] requiredIntermediateVariables);//, ILogMessageCallback logMessage,IIntermediateUpdateCallback intermediateUpdate - void freeInstance(FMI2Component comp); + //void freeInstance(FMI2Component comp); void freeInstance(FMI3Instance comp); } @@ -17,8 +17,8 @@ import FMI2; -module FMUS3tate{} -module FMI3Instance import FMUS3tate;{ +module FMU3State{} +module FMI3Instance import FMU3State;{ /** @@ -59,59 +59,59 @@ module FMI3Instance import FMUS3tate;{ /* getting and setting variable values */ /* tag::getters[] */ - int getFloat32(uint valueReferences[], int nValueReferences, float values[], int nValues); + int getFloat32(uint valueReferences[], float values[]); - int getFloat64(uint valueReferences[], int nValueReferences, real values[], int nValues); + int getFloat64(uint valueReferences[], real values[]); - int getInt8(uint valueReferences[], int nValueReferences, byte values[], int nValues); + int getInt8(uint valueReferences[], byte values[]); - int getUInt8(uint valueReferences[], int nValueReferences, byte values[], int nValues); + int getUInt8(uint valueReferences[], byte values[]); - int getInt16(uint valueReferences[], int nValueReferences, short values[], int nValues); + int getInt16(uint valueReferences[], short values[]); - int getUInt16(uint valueReferences[], int nValueReferences, short values[], int nValues); + int getUInt16(uint valueReferences[], short values[]); - int getInt32(uint valueReferences[], int nValueReferences, int values[], int nValues); + int getInt32(uint valueReferences[], int values[]); - int getUInt32(uint valueReferences[], int nValueReferences, int values[], int nValues); + int getUInt32(uint valueReferences[], int values[]); - int getInt64(uint valueReferences[], int nValueReferences, long values[], int nValues); + int getInt64(uint valueReferences[], long values[]); - int getUInt64(uint valueReferences[], int nValueReferences, long values[], int nValues); + int getUInt64(uint valueReferences[], long values[]); - int getBoolean(uint valueReferences[], int nValueReferences, bool values[], int nValues); + int getBoolean(uint valueReferences[], bool values[]); - int getString(uint valueReferences[], int nValueReferences, string values[], int nValues); + int getString(uint valueReferences[], string values[]); - int getBinary(uint valueReferences[], int nValueReferences, byte values[][], int nValues); + int getBinary(uint valueReferences[], byte values[][]); /* end::getters[] */ /* tag::setters[] */ - int setFloat32(uint valueReferences[], int nValueReferences, float values[], int nValues); + int setFloat32(uint valueReferences[], float values[]); - int setFloat64(uint valueReferences[], int nValueReferences, real values[], int nValues); + int setFloat64(uint valueReferences[], real values[]); - int setInt8(uint valueReferences[], int nValueReferences, byte values[], int nValues); + int setInt8(uint valueReferences[], byte values[]); - int setUInt8(uint valueReferences[], int nValueReferences, byte values[], int nValues); + int setUInt8(uint valueReferences[], byte values[]); - int setInt16(uint valueReferences[], int nValueReferences, short values[], int nValues); + int setInt16(uint valueReferences[], short values[]); - int setUInt16(uint valueReferences[], int nValueReferences, short values[], int nValues); + int setUInt16(uint valueReferences[], short values[]); - int setInt32(uint valueReferences[], int nValueReferences, int values[], int nValues); + int setInt32(uint valueReferences[], int values[]); - int setUInt32(uint valueReferences[], int nValueReferences, int values[], int nValues); + int setUInt32(uint valueReferences[], int values[]); - int setInt64(uint valueReferences[], int nValueReferences, long values[], int nValues); + int setInt64(uint valueReferences[], long values[]); - int setUInt64(uint valueReferences[], int nValueReferences, long values[], int nValues); + int setUInt64(uint valueReferences[], long values[]); - int setBoolean(uint valueReferences[], int nValueReferences, bool values[], int nValues); + int setBoolean(uint valueReferences[], bool values[]); - int setString(uint valueReferences[], int nValueReferences, string values[], int nValues); + int setString(uint valueReferences[], string values[]); - int setBinary(uint valueReferences[], int nValueReferences, long sizes[], byte array_name[][], int nValues); + int setBinary(uint valueReferences[], long sizes[], byte array_name[][]); /* end::setters[] */ /* getting Variable Dependency Information */ @@ -126,15 +126,15 @@ module FMI3Instance import FMUS3tate;{ /* getting and setting the internal FMU state */ /* tag::getFMUState[] */ - int getFMUState(out FMUS3tate FMUState); + int getFMUState(out FMU3State FMU3State); /* end::getFMUState[] */ /* tag::setFMUState[] */ - int setFMUState(FMUS3tate FMUState); + int setFMUState(FMU3State FMU3State); /* end::setFMUState[] */ /* tag::FreeFMUState[] */ - int freeFMUState(out FMUS3tate FMUState); + int freeFMUState(out FMU3State FMU3State); /* end::FreeFMUState[] */ /* tag::SerializedFMUStateSize[] */ @@ -287,7 +287,7 @@ module FMI3Instance import FMUS3tate;{ /* tag::DoStep[] */ int doStep(real currentCommunicationPoint, real communicationStepSize, bool nosetFMUStatePriorToCurrentPoint, - bool[] eventHandlingNeeded, bool[] terminateSimulation, bool[] earlyReturn, real[] lastSuccessfulTime); + out bool eventHandlingNeeded,out bool terminateSimulation,out bool earlyReturn,out real lastSuccessfulTime); /* end::DoStep[] */ /*************************************************** From 17b79cbb3e04320108576a5fc8c0ba584f4eb4c6 Mon Sep 17 00:00:00 2001 From: Kenneth Lausdahl Date: Tue, 23 May 2023 22:02:02 +0200 Subject: [PATCH 03/54] changed ubuntu version --- .github/workflows/maven.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index a82ca325c..2ba7ad5c2 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -30,7 +30,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ ubuntu-latest, windows-2019, macos-latest ] + os: [ ubuntu-20.04, windows-2019, macos-latest ] steps: @@ -134,7 +134,7 @@ jobs: deploy: needs: build - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v2 From 7f4d284e52cf740faeeef3d3dd09747499a2a56f Mon Sep 17 00:00:00 2001 From: Kenneth Lausdahl Date: Tue, 23 May 2023 23:35:51 +0200 Subject: [PATCH 04/54] changed fmi to version 1.3.6-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c5dce8ffa..ad58bbf8c 100644 --- a/pom.xml +++ b/pom.xml @@ -24,7 +24,7 @@ 11 11 2.17.1 - 1.3.7-SNAPSHOT + 1.3.6-SNAPSHOT 1.0.10 1.5.0 2.13.5 From 225f3ef4ab666718de262559fa813838550b484c Mon Sep 17 00:00:00 2001 From: Kenneth Lausdahl Date: Wed, 24 May 2023 09:58:00 +0200 Subject: [PATCH 05/54] added test for fmi3 --- .../org/intocps/maestro/Fmi3ModuleTest.java | 32 ++++++++++++++ .../test/resources/fmi3/basic/fmi3_basic.mabl | 40 ++++++++++++++++++ .../resources/fmi3/basic/fmi3functiontest.fmu | Bin 0 -> 9089 bytes 3 files changed, 72 insertions(+) create mode 100644 maestro/src/test/resources/fmi3/basic/fmi3_basic.mabl create mode 100644 maestro/src/test/resources/fmi3/basic/fmi3functiontest.fmu diff --git a/maestro/src/test/java/org/intocps/maestro/Fmi3ModuleTest.java b/maestro/src/test/java/org/intocps/maestro/Fmi3ModuleTest.java index 2542b8b56..060125014 100644 --- a/maestro/src/test/java/org/intocps/maestro/Fmi3ModuleTest.java +++ b/maestro/src/test/java/org/intocps/maestro/Fmi3ModuleTest.java @@ -2,9 +2,17 @@ import org.junit.jupiter.params.provider.Arguments; +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; +import java.util.List; import java.util.Objects; +import java.util.stream.Collectors; import java.util.stream.Stream; public class Fmi3ModuleTest extends FullSpecTest { @@ -13,4 +21,28 @@ private static Stream data() { return Arrays.stream(Objects.requireNonNull(Paths.get("src", "test", "resources", "fmi3").toFile().listFiles())) .filter(n -> !n.getName().startsWith(".")).map(f -> Arguments.arguments(f.getName(), f)); } + + protected List getSpecificationFiles(File specFolder) { + + List specFiles = Arrays.stream(Objects.requireNonNull(specFolder.listFiles((file, s) -> s.toLowerCase().endsWith(".mabl")))) + .collect(Collectors.toList()); + + //lets make sure we have replaced any relative URIs for fmu loading + for (File f : specFiles) { + Path path = f.toPath(); + Charset charset = StandardCharsets.UTF_8; + + String content = null; + try { + content = Files.readString(path, charset); + content = content.replace("src/test/resources/fmi3/basic", new File("src/test/resources/fmi3/basic").getAbsolutePath()); + Files.write(path, content.getBytes(charset)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + + return specFiles; + } } diff --git a/maestro/src/test/resources/fmi3/basic/fmi3_basic.mabl b/maestro/src/test/resources/fmi3/basic/fmi3_basic.mabl new file mode 100644 index 000000000..b2fc690f3 --- /dev/null +++ b/maestro/src/test/resources/fmi3/basic/fmi3_basic.mabl @@ -0,0 +1,40 @@ +simulation +import FMI3; +{ + FMI3 x1 =null; + try + { + x1 = load("FMI3", "{FMI3_TEST_TOKEN}", "file:src/test/resources/fmi3/basic/fmi3functiontest.fmu"); + if (x1 == null) + { + error; + } + + string instanceName="fmi3functiontest"; + + bool visible=true; + bool loggingOn=true; + bool eventModeUsed=true; + bool earlyReturnAllowed=true; + uint requiredIntermediateVariables[2]={1,2}; + + FMI3Instance instance = x1.instantiateCoSimulation( instanceName, visible, loggingOn, eventModeUsed, earlyReturnAllowed, requiredIntermediateVariables); + if (instance == null) + { + error "instance not created"; + } + uint sv[3]={0,1,2}; + int i1 = 1; + float f1 = 1; + byte b1 = 2; + byte valu8[3]={100,0,0}; + instance.setUInt8(sv,valu8); + + x1.freeInstance(instance); + + } + finally + { + unload(x1); + } +} \ No newline at end of file diff --git a/maestro/src/test/resources/fmi3/basic/fmi3functiontest.fmu b/maestro/src/test/resources/fmi3/basic/fmi3functiontest.fmu new file mode 100644 index 0000000000000000000000000000000000000000..3ab653c8277cc533d6b8d02a73307389c8f4e291 GIT binary patch literal 9089 zcmb_?bx<8&vn@_=65NAJaCg_>PSD^S+}$ z6uFJZF+5aNAn>0=uvtUVRE&OJ>wm?=%M>-kD$>*+ut=(+>O6TBom0bu<<8=wZhok! zen~HFIndNKjgG3`{Z3!RlyXOq*Tq1HZLT_ZP+G5hGn0|g>2rC3CNlpZ{K|%SIg^{g zVL9_SlhMwxH@zYB#(RChD$cnQ8n53r6Jpbp8jm(48qXYVQyY#MQ8?exlxU_Vn=_kW zAd4>3*UTUPL4JAJ#vCv^g?a_r!F`CY~FSyxsuH$h&F zgwn5C3^k$Dm6S#j7d)mW4m)z@uZIA_ylIx9dC{|FFY^ul{2p()k3~ahAQsuiN$I=f zX`=_GO7ot5Q_gAT8CvOj4T*1pqAyLW(%_iY{80i&A0g;85f%N$ zlKyU(337-yLX8n3j-{hvE3657nsF3=RtM4-^pj2PzzFDMjIB@K5`RM&s9@C>K206D zb|kkpx}3Of_vj5&SKBxmjq3Et}H*m){N}($zcZ8?0fHaz5@igvLF3$5DSJw`amTc|MCCTu~gP^SqlkLq%mPgt~}siy)42w@=re(RcZ;Jrrf%g1Kqm0o+%z z4?u}!cFsKhKsYQAZQV><;&JoFlcH+b4{IS_vBCfvYnuypW}o&J9T9gSJAIMV=B?Bl z+OqoJ=8+DEPqD#v}|IU3(s`hJ8 zW9Qwy;>x3hE!#bl>wA>rD7(Q>K(tS51_t{kuH**h;-d|N+!=>zbb13*h6*Hs)LaW* zWGQtp$3TbUy6usGd$7aOG0*m72zqQNP<_ecBm4DnYiq%_t}b*TK|CCkZuQqzc#68k zC+?Sdw2|{nrP#Ai2?VXlM2OBRJP2-RoP@h6M)zO|MAwi21Xi~XH(jK+^qYs;xK=JgdtyQ8Z{tp!R!oM{_fX06Mmvzvi6IfX0~h868A~H8bdOkgd_2EZeLI8c zHD(GN*RQmk%!kflcG{^2F?_2MjoZr%X+7VTbV3_(Q^4(;8)59Lb}8r>IQ~7LeHD_I z?eJeKdy6?Gq!(50hBrx4{*$Wk(Rd69WYo&=@sFVfm1nrj`srLP_Y|c2^bE&5Z)#*X z&7yOHf4?yDfxjNdTD+c{9vcayz*Ec!y}XNgFUhRpIv1wSc2dhOeo~}ylJ^B*^!`&$ zQTA%wkI$f9ykbQ=GUehNACrowpVH4*_GWX_PxZL&B7n#Yy*Lw^^I>J+iHy$PmFi~n z%OkpPWmJkJ2z}^4HQ78JakN$-d+tMnaD@@Dwq;&<^J_T0tVnxxFbxJ{>G*7x)pazc zqW^+YQmKH|wKy%6`A&;krY)MBAEc=ajB*&^q%IGK=0C3PLs&g@zqLrH1n< zhLeuu5UqaBJk}0V*e|r6Sf|;Y7oh>v7*^NPKzLCk`m9H5s#=P8ZH7HJc z_s)X+@Lwm>s+Ae`L*6f&nDe?dPkV<-jW5x+b*w0szAJTWJ@>Y$?ctj!8RKQd@Q`U@ z!t9&2>5P0OC1$u%tn3Brl7evGQOXzjg70ll@5{1uVl>4Y+w7mOtyxRo~yRTQH52VdXANsCk4$q#jO z@>L+|d5~ppDicwSQ|k>kq^->cj!N^V?*f&z`b|gkLFopP=PlUdAl|n;dO^Y@&tx{( z5oM)aXspiSwZIVOOlaBn>iR;hq7QkpjCML%mm@xhXM7%6f&WEKUFx`d1r zh9U&)OjRCun)xLR45ke2WlaU5&`^V{nvWHjmJA4V@H5mXE9-DZVJ0IM|m=s1r8&21?o9 zNmpn_tkLM-3lrO8GhyfQ+c)DQz4T8V7|a>kW4Gu7Mal_UQ{w6Y?0$7{z$UQJsy3%@ z$D!XYN>{jlj{g}hv#OTvD}j^5F;g0yevug|5fu?mP?JM7y4U;s^NQ{(LKlx%P{bD; zAh7nkHCqq^_|^~JbG^@1TM2(2k0v4z)_5Ij$$~X*L-jlLk=eG>63R)(228EQ_JG8W1ja>wIbscA1AZeqXc-xM8T6->g@{xk`RP=!7q{=8{91~YMTd@w` zG{g3hN*R+8SK(c%BHKVzNGS!>>N^zq?ql-(XvmCJgg4}Ms2DNLb z!)@U4u9Mdoz$-x|*LmA+NpuAN_4CEYCDS~8F&vxGifs@iAM`N$scaEwL_Rv`!5Ajv z_W{T>6?n+zEZ8DiPe^E|;6POAGF%^&_Hnrk9dDB02)H2osd6{s#AzN`{_7-i37jM z;|QRd(dO+EuIWr#(~Ottm+3!^3{oQ>peek0up!yd23`x1QD!5{sWcJvofeI{Z^Hz` zLoCn@@v;&->Ff<6oade71vce3Yo|^g&KvF>*S+!W0~B_aB%GqTYGbLLqUoKYgMdOG z?Dtqo{SCa@iCeK`)Y=xQO_>n>d@qM9_W0~~JkVPu!?=;F9|wi*+*VTZ&fhztdKY=M zMSP!gIo_IAWzE}oqBiXk;yVU$-?Lj^w@vQjQ=yl#wn=gGD!GU|(=XgynQQbXMX1wK z{kD>F5@iPyUy2aCx}&dd0n*e2N{tx6X=9LX&BIH!t5&@isD0}a%gJJm{%EpdbkScw z#^1@ek{?_VHv`0RFOK+o?Mb`d(pcYER3F|{C*D41yjAPwtZsy!9e0IRAB!Yk&>VZo z7tbVL`vjeCP`S>4gggTr+R|6~k4)No!!c&ZjcO>p+17rLe7^BGoO|vxpL=B{RJ1b? z)V-($sZ4AYvj^Bv>SmoHbY}y+%sH!jL~_^j7ySI%=Cv}fy>csN-;7@QnZKvjw8>u7 z()-7~GMnmd_I%S4@n#(~x|w?tc<{V8lx4azpaU=astDzlpH8)Bp2_NuDcz!fCbD(q z)?YDs=8xU#lu^~YB%lVj?uNKrr=5MA+CmYQz416%20-kI$Cr93an82Di+d}$Kin&s z{nye{Z=~yAW}nA5*bKNMK6Rc&aOWcSzIyJ%Sf3Q)jlJ0Y`Ez*1pWDjgU^11SKcz;T zhipjBzVE?31JcfxroLYIw)Yl*e=d_bil}X!zl8(ndjhrcUUDIEq0v){w?*5PdI5rL zo^LX&Z!&a{0G@-lY0Dlm7m|`2z(M;Z!^LRUae?T>9TB1vDR<~=k5zt4k6HZlTF+ZH z(-Qju7IHaP_qMx2uRp&>1*-GJS1c;NyMkOo*P*_dULW<% zE@_P!iChv+?=u~VvpeTo+{sm!-09zrJPYFK?RdAlzw5XOTd}um?xxPE?_dG4$oy-=`7<&;oV4nO?PWLur{11;G|kYZPLv#nxGN%jkiv zBBUkFl`Z4ecg6iGBT-luX z%(6<$`S?UOk9fao;rB&!INFVq^|`D{AZmbnT1oF=+vP!F!D)>}^!5%$k|wu$@LpM^ zP>I;Ph>R>QqdBLXk2hw!kkv}fSt!9*_(|%C_ktU{UxpdfUdoyus2nF1+#Qf#OrkT9 z+ZdMqGv(?i_W)!aFX9lZ99^H;JUGXX$y1agGO;gaS;T3dC{JU_vALCK%kWV}0725H zLu9^jWF7YY7YEr-Jr^&ck(e9C=BMuQ(oN5oKGD0!#!5kE9Pf{;;9V^LsH657&DW{f zX!A`0=+eXarusU`b8b(P{!xZf9gt4>l`J~@)@A~~^#H9!h5OC6_G`e59iTpd-^bCh zVzr6W)Hhght4QDa-MsqREn69WZ~6O2g-lI`qgKFu`Ko#0)&k82MVuyvNwY*{Uqyt7 z0oAm#z`}XF2!^NoOS5QoZxjJ{=fUV(HqiW4d4#$7k$&N=dmB?&U++Py^*4}NMx4&u-WWW%NqgFfxEN7mtDN7X(V&rm*VmdNwx_C@~c zYar1)k@|KezPfD{-6hM3=|$7t8Rs5$?3x@WT`&fBZ+sXVTX6RMqjGa^tSs3qq(BY! zg|2Fv-)By9PY58;9i8j%KP*$~qGY8OmmTZ7%s1h{FY}n$m@w)y&b+%H9X933tLWwZ zhB3Fyi|%~?!6JHS6yITqK34wp=q1)5>P44yG*{%^Dmd6ZouGOnUx-0(tL_d14SMQ4 zj~Aol;5Cx_sXg6aYkrpc)`k8Bg8tH#;=d^^lD065bK4mH#(JkrCeH6YSk=WtYSZDC zlL4CD=u?aJ+LNcH-B|7YDd;{Z!(+GB^HZ?!m!w4!U(uAF_MhVtrfYr6Y#nv8Y&{ak zMK3@5G_nVQ5UCNtfyO0$%P#BhZxw>hg`Y4338j_m3i|V8<^zJ#*STtaUr}X>7Y$F! z^lzEY2AYSCu6;s;ODC0awRk$xb16*wI_D1(@a2lW^Q*8NR69R!d?M7JszYecvC@!$ zC4^o%VD9bhm`Ra=Y)Tg<5k<#L{u+x4uUMfdv`Lx7q606rRX}P8b2ZOxbQ*u*yn7OC zBqHqcsDlVPH_oEmKk9Fxb@HqRQM**(N6Im}_@tK^xZEtL_& zwCiiCqxt66RQ>v9K4)*L9`Xrln)l3LCdGc0^$Ch^yybcf67wX-W-n`3!Dbn<+|IrM zGgW!jt{5zo&>ORD@EHMWf$DuUM|osebb0ZV`&r zADqLY%}IR+v0 zfdd2v`%6{Qq=-R7y>$|KMGE*{>;^%z`*}SRPbbNS{>s5bdA5Y}U_( zP{ZfAIJgM29O5X1zO2>Ov3(kJ2BlBCJul7_G5F)y+LgQ7iT6yK;s`@SK$~K(tlFK2 z&gC?Cv4?O<_rT%0T_{LbYy8W`+_u{Xnd;dCia6;Rw&tOJDx@+HA5oT-E|wV}WKu%? z0m#4e@lki42)fZ(KbP=r`a)D_yq`xtKFl5?eFtfKP4J4E25p}uOryTAUr)v)?A7~{ zbI%Ph&bY@o*y_L-=9M?Cihzh@j4;#S@`xI2{P9V20hZPh$t<14XqJ6>;9z}uIhS_ zB9s^;l0{4=05C-Ei^|GTjlJX6Nv5{p@NYl$z2fSKh9)W}7%2ga0;}py=65YY!&V~g zJfF7j;kv~FiaQg$C36RmkuVo$;A<}?8$Ppml9QQFg9B@SDSht$!Dt)q|AK8D?jNTp zMOMopa30=$+95JSmo?<}-z%n=}_) zJ~tAyDdC+UW+>5wRG?Taug6_()j=7~MO9ic>}iEckxXl76%qQhgA8lF zwx7+|6LD>8zvekP@SqCX0}bxQEE6@Ni-GX5k~1-!Ppitb@{Z-`UemC|6h$eKG$UW4z^t~S z7(Zvs@oy(K@ zw#={joq|d{?^=%g%J!Nzz{j*CXa$4L96Tq97Q*nm1(Z5Emo;edd8fyfma;t7kCbj# z%e=f$DcY`q6XYcM*O4{J*>FKa4uCvJ?)@$ceduKY4OgS^a=Wj;?Um}cxXovkHn9I; z`NjsmZN8HdH%93~j9YUfsnMkbI%=!HnE_Wnf_AK1^CUr$I9YJ`kaWe4*eN+lDBD3k zFISiJQ(SE$ImSUytVXCZ$$s<>^tH#>`9>P@BJGW5Sx;g_!D>i~VW}O2<=x3)eCf?$ zBH}eu4NgD*>n`K9+Nb+zL#e2=!eYI+~&Y zP>~cnX%cWIV$F#Z5b|}jo&(?b8^3=ks0u}3IS@(3nvAlDXow-nL{|(OH{;Aw%x@rR z!-UvavlF6OgwzjM!31C8(6ngvfl*Glej7;1!e?J@Uw+CQdYrQ!(c^P?$NI`W!{hY0 z#mE&B$i>m|C; z)6dXwz-!<IP8s2F2JzF2GKi*=O7VhjQEk?Br6Jo7r}Pd!BNlI`6KQZHh# zzq0(P`krLRH~8kr{N^c}{w99bv@iB&F*LPQXge87rvhC#$JE$r1hHcY` z=+8Pl((-Pd8AHg5uGjc_5_=FvddX92%^=X_U6G(ss^aP&RY@Rm!%WdE9sn3&-IzoGwiKhYtTLWIshCmo6w%*5kS~W9UH(FyOlK3n=o=Izqh5l2P^{7E<6O3fcOTJeT@l$gK(wj z+02fzJDfohNTnj#yN;`a1>bJEBxsD>(B0x=h7#6?`5f_h`od#U(VFNB!*Emlus&Ut zgjTf$jjt!rP0WK;$_IX4(5I9(q{!jWc&IbV`>hR4d_CigH&EeJ`P7D_=^f2Cj)pZI zL}Gm?Eys{Cs1+`k%7U2$$rSzU&Rlbyh-&bgn(rV}xhIT3lu9$dM?LBD0vKMcXWnM2 z51xv#4_mNmn2OW{VabYJi3TNGtwCdE?yk5=SYcMV2Ddmk4Avnmk-}HTRXQjrJ8eR< zRW?!OP)UoSe$ShGgFG{12hB&@GO=3iyH0Uv{pU#26qvDv)s9eyJUSKu1y$R;d6bl_ z@>{i(Y8)Kn2oCgnX0=5m%8crDQxN-be0?bzL8tH7uLFsZ8hrNqpb=PXx)vifi;l1f z$JWxYPJ{Os?ow@QI6L-f5uJX4j;$Ej7w*kE4V5E_1_bhb^EpLB8uaJYYJ~d5O**(b z@)Br<)&gXry5shu2YWz|I?g(2Zi>hf10>PnTQDo1;vF9^{0D^4Q1zG zW^OBK?qcc;aQxdWW%jhQ{o5w}d;hQfjs0uG+ImT=+}Qp{+E$R{spLwe$r-4ObLOmz zCV&9+y@3r`2%(-c^-7q<^_CA+49hQGTMPC(l#e+#e@10S_m&K~oEQVm!#cq|0y^{s zQXc4heWi-5Q~l`WI|mBIz3Ky|aNspnG}mVj+57E{8>GH-v<{Yhz^vQ#^BCQ$5@oso z-6;YRIHm`o7=^qSDp%l)L|uk!_s5*Pc+`O8WuTSZ8;mlF*F)qx*DNbsXn(YK)GVB+ zkt|ZgA<8iH6oPBeYZp!JWQk?k>1!~Ea#6u^caT-9tRY( zk(3hsMuiiO{5+$QP5hEUu{pPwzVo<~uX8zZ_B0zi(^UC29z>`J7uuFT>ghO$`VThO zRC~gRc`<$@VSFQFjkgP82g*Dm&UvgG1xW{J6Yg<%G%4iMw8D&AjlG6(w7-s*`_!8x zL^|>nzX6qxoO@L+BCZrvpQuB9-b*1_=H9s$lN*wYCs{B`P1NP)&dC!50qH{&e;c*j zAh}XJCQe*A;^oh{MM1BHI7soKp#+4_xm5-WRHV{}|0sGBd?K2;g@r>EiBHkpkGcuciDx5r9r`r^1*o(7AAih&zK~Ts$$;#?}PUn$}Xw0oPA-i}( z%!DynWwhrb_@-!kS%2Lk&Q6C&E+A;;E>Yh+T%3LSPRb2tG}^zi1<)tSRE*t#G?1P2 zF8RBjO4x$sCW&$ayrOvb`slCi_p3C#?8Sy0rpS2F^Ay6bj?+N3(U_>XI*IF_H)t!f zf;=u;8Bvr*~#eF$k0e+nOBB!R< z;g6b&nY!ILS=a0)PjOo$m38U5(p>x7DU@=!tz?DvIlJ`g_NYr*=*HKnYfhATop#m@ zX7wAfo|W$E8zRjI(uar!sxQ%SOG0SUL|0jlaG#{jEDWSB3B zb&}Mq0*JOhD;1P>Q<4|$d@a!z!inPoJkcvD>#}89xqtwaEW4bsPUM92&)7qBISKW8 z&x>EG)W+CXy3Z9O&chzX=6{-D*=?h6u}SPF|D0SWJY3ypu;<^guv+?cP`um;_)5rT zU&HGAeq)(_9pxR&AsfdG8~q0(NV<~k$7?%B;YRr+-!Su&oim)|<5y#!Dr4RIUZ#Dm z+Phq1doKGP z+LUX{A+#4+JeKPRc!jye^~rTJRa;lR4nH0-ROF#yuwno2+K~U=H87#h#r}H#P>TEu z_MfyO|ANu}6ZY@oj(_I Date: Thu, 25 May 2023 11:26:48 +0200 Subject: [PATCH 06/54] updated with windows and linux --- .../resources/fmi3/basic/fmi3functiontest.fmu | Bin 9089 -> 52788 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/maestro/src/test/resources/fmi3/basic/fmi3functiontest.fmu b/maestro/src/test/resources/fmi3/basic/fmi3functiontest.fmu index 3ab653c8277cc533d6b8d02a73307389c8f4e291..76bf62909ad2fb0ae926607311a3b6f777cd7794 100644 GIT binary patch delta 51858 zcmbrlWpLg=*Cl9Xh?!zLX2;BoF*7qWQ_L~Q%#fIwnVFfHneCXF`LQSOw_CNdQv*My z>q@t8>zZN3AU>LSLOfR!GnDTGq$of`e|k6%&4Xc z4+gpaY;Vd$?qKTbfd~c;^#BeA28H=A`TwI}5c>a9;DCMolZ*THzrZao|5NZET{^t~ zkidcc2TWF^Hn92?4D5Ol42=FiUhAY?I8|G$^a5PV^*i%!UyqlM zy4qvDsIickB7Mc!8BxWU6K#NE#)`4WA~AOkH}Zj(67BrSC+7BT!o1nFoHvbLUq9AA zSWhP3sZqCzr-`zD_2AL=Co+x0wi`CSnNwngcNw)qltiWa0l$Oq6)mU{&Eq&?r3cY=L|7BC#hUdY0nO*uf!i{Qu z+A)RT0GR=gQ{n4T<|vf}t#zppak%#FP%f7oC&$i^0pm=Mg7{vgH-UO?qWOVeb+H#Z z*BdLu3hVWkM>cP63Y*=ym+)xmLtxHjF2Cfs)#&B)g~C>x@rK4d41o_OMrfHMFWo6` zCcIeJbzOTKxh+C;c)!-X3`JNHeYm4Yr-t;v|I70CRLT0@$JmyO7T3oWB%V!Wd%ye; zT17`O09bG#F7M79-Sg~oX3`^Vm?L;1Td*k{{t%w9Y!ISU3!ODaz=Daoh#_6`3wS7i+g(l6JOEQxoF`$L_X%Q_ukuV0) zOkyBX^g{o3B^hsXm)bX{Uud#rX@9#%*GBdY>34XB38NNrc6EAu%KUw^_&YjJD<`yE3|MTQwdA(ELy<06DeyCjc*oI z)U?)*XuyqmfCmYburDL~#MB^4NgnEE1dwuw{oSOafclOv``v)9Nr^os2-mG8hI*RR=D+IcIF7!;gztp#!Rj^-Yy^!h1RL5de)XTLgG|L9m zD)yZvU-tv+gsIC5x4zK4*c*c3=U|-A2b6J7bO|z}IbbSNHY&1cdaSOnyr5dD$N;ZO za4_mj54f5uFC9FmbKPM9gR(_0%l%Y09 za}hLE9uoA`GWiIk??mAH9~sPd#qU8sKOlbT=ZEM{*XVXnB`>Ds#qnaYrI!MJ+^V;n z3%NA}SpFRvni%JXq+@rbE|wQ<8Ho6HW7uKUmi@aqErTu%Ero13PlQWvTk~%y*nzD( zCjYupmv?vfr!QaV&~^kR7#W8?z z)XZ);(;PzH7QmLh^sG*#)&zhh7H)kGd!K@c_anE66Ffh~3vUeY9sX-(zXsPHHS(2h zsEq@NoxcOrvfE4UEW*!Gg z*IIlc6GA!GvaY`cnlDW()E|X&mfU3xr#E0#>(0os1?`xg_CE5#YZUhOfeH8zyr(2? z&P3C7-Pvl&Nty`Fhh;a-O*qW;ekn-Zt_y*gwlC<7Y-D>@<45+bkA!jPkPUR#CZT?8 z#GK731%t>J44wguvJ?Y-u7Y-ouA*a^N1tptk+lQZOjN>#(s;Cx0>>Yo>0ks`rB>|_ zOq69Jlg!zyqvq z_;++PZ3P9kL9)VvDqm=z{8wzh%OIxE`>J%K60~ZpHMlXj4y^Z<_z<>XNWJ&hVFnk_u=XWq?a9_sq8Ke|6TQ)DXxGUT|pe+enfp;3k-N;Djz8rv?)$W%yB9S zRGRTcyOWa9w~mnzsDC8Zn7p~L6;Gn? z#1mt+5KB(A5cj=xpS8ndb&G^<`M8N?5}#*Sa<$bBr5(3K)FXbdJsboEK}tT|0I&@(c;Ig zFt%DJt<2OgZF0ivcr9Jpb9FtrK$NeK1(t{8-uxpNhL<0fmKQvgdEs3D(((B5J5c@> z88SMR#$I+;8|YlJcj3J6&9_<1M$F3+O8KGu`(}0}+#pP?U|)^$MNQq>b6YVX%2a@Z zDIHfp8Dl8$ctA&^$*1hv5Ab&<`}F;LuLl zz*aY33hpibCa8SQ@M<(18xMiC={{d_dxHwG=+*q~$YkD=LO|aTp~XJ#4()4DEDvRK zOk%2sZ^DbDVUGI%5+8fK_3OPXHzYy75=<5aGo&)`jD4h7fVkH=U%O7q*i2#T|`LMFV%( z%^g(y)h;*huDETYTWz=wpV$YLk+;~kC5X};&?cUU0nvJBTZbE>7inJc8O>eJN?SA( z28ch7##C#2pGtI-S`hGaMCFViF1|2j`TC%EtttHptQz6k5Ysw71p(&v5A=r2t!EK1v@(fHn>b4(=8Pd0=G zPca)G1gRj-p_Nb11>gfc6*PIOT38%To&O-tk^f0|%O*VDNl^-|)PAMzowi_555#V4 z9jKI6xyvT5mxIpJ&aup(it0Gqwz#~KW4b!4qgS>TQ&pE6Q-68|Z4y2(P8KzRQf@_yksMy8Nx%PGDL)0q9(t26xE#pL;Oc@9(Kl zUat8zS0kWR=3wj74AN!|ck$Ki(&K?z?F6)}KK1)4QT>`(O@r{|XOYuxUP=``;%vHR z_sQaA(`xEKCNC-vR*@ISkrw}9{4{sYE1rF(kAtulD-{=o=9_rh3QBnr3Pn;Ii2WpU>qd?C-sV66ZKfhJ|z7zwPH2%B-6fzW%kO zHXq%6HVf}OQGIFdh1nQ4#eA}-2S?09M2__VaF)XwYtOW{k6!z7Z&Z8x{~la4y?OM# zLg*2E8Gh}>!Fgo0vce#ZM06*PrDNEEfF^i!ir&Lt!tr(m2`CV6aztRe%^0W+5He%g z`si-R9^7R_yI+O0)teOZ*DRzU{GxaNRape?E>SzGPQ{bY*l*J?V;S2(Ne>IY0a#=x!|Q$o8>!}Dd^6_lrkYB;^9fD@b#Age$OQHI0_T9 zMHN{K7K~clA;#RtvHOYJ2FFBz4g=t{9gnKnlWF3sFnwipI-WB2xEi2PgdOpgb?{M^ zc-1_#XA~YoUbbQ7j0UYU0`^mL@*Wh~TMIIL^+QzhJ|@ z2yj{C=t3R3-?ohPW|gN6epu%MVLq_TowW#aYV4OGw(^w3?3T%F=wad=pbVdpY@>R( zUbr?ZdmS*_$BZO@4tg-%0D^eyi9^MrZ|%L`HgwZ{>A35v-QZc4IwZZZh0++XSiPyu zTC&W4e|Gk|Ds75|;*M?ElWi90VtTHz*~-bqeYB9kg^%uSY2dG?mBoPmhCGiMKS!Ua zR8$WL80@`m{07;C`9_QpQqoKW5TtKQ{m4#{4B7ZBy>CXl0cmZh0%e88_Ynoo=2bYl;$IhgjlxBrbomY<7J0Bd?j!10;O;O7oocNJvh`E6Zt z+UBG+DC?^D=;8hy1Nh||mPK526n)OpJY7)x{G+-`%G-k0sm zQLMQz51aMMz7E^v4z{1kix(m20h=m%7t&-m-9oZNo%0RW;Xvy^P1S&I-78Ulr|W=~ zD>t8fP@hAkRrbq5_ASFemmti{C`i4_pr zt=~NOD|e;f9k7zI^s^UcpUbA=fJ0GnMftEHQJ9dSckg;-GvTzHu9qfJ<=eD|whqcs z?%XYuY~U{&>+(wbk|AZYM%$*@h*_8xvc*Jkb&7=Ky6^~9QQCS{Ub^(Z>^)vK8R|B2 z^gNRHUBg7#bz=;w+M5%(Nb<$~QkMpZu5f1dO!*saSU|NM1NfSZqbl4Kix&l(q~Wk#SK}0# z5R*YBIi%t6+~@VnhoJxAOA_!u#Q&$zL=w(%=O~jXkSue+_v<$;q(&0xX!KPbm`2- zKoxbp+VEECeFFFR%@Vdo<-EDOM$M0;x>M`W;1t>nbz0`-FlNf66fJoO4Xb4?Kd_=&uH=1x5Ou^HLYt( zQUNDbG{a=~^~n3(bBp^2GT)3h5F*!`0E#$3E_L3nzuNW7-?0%`(Q6En#3`2M{?;kG zN(w;zWb}KYzjwL|75-1k7l!im=f(0o_ILoVed#oyeYf_kV!yBfy}W+Nd^ia52!Hm+Bt&1w3OnC6>WKwUGtU|joIsm*g;O?GF7Qm3u=86@Mye* zpi>Cz0vW9Y+=|Ann?G^!RiW!3H-^1qBL$MWz$4KYxc9*Wib-5hsKiyIztF12Ot9KU3`!y${POqjdJ#s0~ym3!JP zRLfLZ`hkQUZ!4HMG190x3bt#T0DbKw%(-NYCHjU-GldW=GVP3TLaq{cxJ41PdJ z4g&?lDmBUXx`;10`0BDq_(<`&lN{R)Q>m$}tVa`5FGL|r08<+WDaV8j zX1bo--tTg5{MhS4{!9?%iyh8%&t7kqWwY+QQSH&UcNEle~=J;Fzc6)DK}QL zGN82WCo=7I*jRoU4+2+?25gg#o{PS=wq7At897Dn2d67%y#=oy9PLjlYbeZ#yMHPk zg{>S>3Tq<}c?%V6MiQYDt4LXMYOFJgnD3H0Ey(pDDtnCTF;=yZIcdu?%S60DZrrxK z%UvB1RntVa$mrH^0X{V$UNlyNP`p3P}EAk1jfzs0fAr11b4vmaF z9_Ug%c8L>@MjyQ;uQewH1!r<`evn0R~h9elq!Sb%7&r-*16|=4O2&^*b*-O9~F3Lf{Ioj#-nPeOMPlo)`jKr zW70>hu~$-~^VBGd9O2EKlYgoPtaURe}G{zIUUQVjb$kyEU0^RTBx1 zS9bc3SN-~Ld%nU1Zm)6Y#Xak~{zp_6PCN7ZZacIEY5ef8UHgTLDTQ$p-}S>;9d`sf z$i0^(`Zl|M)ovGmeO4iEe5Y^rj!8bJeT+IYpMDI zv=}SSuz-vPcwGI9qeJ80VHobk30GZnZnS&omPEGgiwASbw_}5Zd(` z=H!w{$`ysh-A4~XfCGVoGuUu*p;_wzrxo9>aMG>-MR%;xSk#OmAF(ID`1}Z+o)5Ia z@*d{nYH*8hfZDhc5Nq#{x<|GHb6sFhe4z&ptJpo3%N6;E<7ZOx$;8E7;qjdd?uCY4 z0;E&}N4o_lFIef(etD%e=+&EQff*Y}z=N3$_BM?9S#kln4bzWumiT_3`Vy^qmL>d;C}p=rSeYHLSOLA#Pt}o$Jkq1jHwV12y;lB5zO!2Ls%Jc zG!4n9?#kLxxjVq68VjgSwV00JH?K?D@H@A}}65}2XA!TM1+8D}c*aaG%u9vGS(C0vyk z;KYzey%^fWj|zb*kP#NWRwKa#uQe6|T;19?5RM#W&jOA)5;tT!m`gVBTw#x1J%oVf zRpSoQ{j!y(?hQ8Qkp_w;mD}pGU$nx?b47Hqt@rGZ;Ht;aP_ylOad^}Yd#9i4@wwDbFEvtv_r#|o3PM4VTDqF%PFUzHNovw#nk%}L4$1+! zamtahhKJ_l*s1)XH1IO3Dy0>&G%5f(cKvrXRRKF?7U@iyRk1wj&Jpqj9&IgU*_4(b zmW9^vxFoi+cq23?A-dZYNvUS3tlNm5&`wgVY41bKqJV#Ei-5|!vX_3&cx8SP^evba zEED3qmMrTFQs%6z=^RC!^-{Y3bn>gWB_m@NcB7%zfoe%fK-94T77eog_&87`scmIX zSxyncH@yZs5bP|Te|bu0Ji-%6a>f=?afe$cyDzx57IPoIde1T#C$Jj4WIDz`AFo{- z@rxTn-ThC}CR4=V(pN+lnGxKk-^>#vCMhCAH9=8I--#p*rMg{mH-D736L7e5(p}nX zZfw@Hv>Um(=LfVCByMa{AIY$aYZ-1@z^^Lx=a-Xw9WiaE)r7dz`t zpGo%@JuX8h*1KTm;XA>9#MpR7GTizdLOv+qf2HkW|M%Li2N#C{2OGVumA$LS|551u zf3({FXvI#9ME>tIU|=KJU|`?>=X}6FLUTJSR&!T-6BjE7dlxfj7Y1jC|DBk8u8pXx zy4beO>X(-ncqPF}cmo}P5EeEqinobP%^elX7Xb$;+l$nTGzU5V+c=H7gOJ~Y*KIMz zEbDabL|olEh_OK@Mvq=WVNAm084%h(Eg?VBvGMVm&N`4a`*nG>wLPtu-q`*5y7cs1 z?NHgc`W(dI*`{5HUO+39Lifc=8aKZ98-w~djUNSE=8grhYhOk{{oIZ4`m6Z|warM& zx7!@C44b!@JNv}HCEXNZ&XtYn?&V*XWBBMK-np;b0@E6G7PkH_a4}#G2Ll2}n>=b; zc1$R!173(08rH2Y4!9bzzr1-huk9%=AE+v|x`z#DVr)i?S+*|~y_(~?-;8v5cbg3) zibe5EbvAgi`ODQP=T3*=~=VfEHi3n?t!fg9@Dt z5aw(;j63H`va!ioU9}+w0u?=DX#yq3tLu z?Dq;$iJ9x{YswpL6wjZ$W=!Z8sC1Ee z`xth+;x^jhI^W?wu>5_Xbw)wo%J(`MG=On1{88?^M`A-U0eg9$-<>ctFLunGKI-4% zWT(vfUjJRzE&oFitDiQMRV&bA`di3n5F!J?O<)P|xhF}v9sQU-dzHa$iSrPf|1oPB zEBKQ?)ah@H@n!9k;EFvX!geHMqHsw!!QWN?n}NKKbad2k*`%pnAuGaN#H(Ko z&U$m%yLJH7?eB zmz`fvGCMUXF3XIL?Jy;xVyLen!O9c6o|)dnD(la~%cayb-KgX=M=I;BY%D%>K6klg z)@T|nrWWE|l=++LOF>cEerXe}URwDee-#hG=2TRgYNoSrn|TCkdHGLQ3M{g$O-z=21K z<1Y7pVk2~}o>kVfqfUTzImK+8)%-*{DwU%g^Ys2l{vRtd{O>uekjSi)l(kD}OeF!&=~)(|H8C*{ z=zsr`I~A>_ed8xcfZ!V*p!MQIha>WWVT6Z@wF^vUTQnYJHBX^%(zX}R-FSdIgqZ$i zLz1dh3VTcEElLFG{PtTFZmi>e%ku=w^Ca=Vtn+q`_HNGWpitwm@M%ouDl=LC&wp%- zma&tHks6&Odl9hhViv65L0gT=pxNgiPwHOKP*ces_J}7bWZ2 z8aFo1Zl=Sn7vcH+)MtJ1t+xEhNaJd}3PpU)ub5m#$vhVgm$IOCl^xUc7Dx;n~llkW>U(a_3Zq8e4~s{wtFQ3Q_D6(jgA25DAPEN19$ zA24Ijbcn!e^KFE=#oJlF;MPdx`G$8CO zuT$#%c!PgW;u1`$QGw5Ua}5#+cSgujM}*^nESl;=LzV}AGk|{XTasJ^MQk3ZfL+u@ zb`3Vb27Dr(7Ln4yU`GD8TBKpc^7H(7PCOs3;aALV^@ij&(e_GVm*bqxt1)myw@iWo z7}BX?<8qOstQ;F3Z_EbcqWN4KETDWajE6^DZP?{0{E<tYOxt5o4X;gIIADapQk}gcuTH0MSsJFU)<5C zd5ovr`Hq00yqVWYgReT8Uo_;Hmq!CmAvpk_xl4q0u3@Egk6;wR*ZU=?Q(#m-*;b*n zdWNu8giHRg9nmC*pKTaQ2Vj&uXONs=uf_UFx|-<*zfgyGyeMmUpA{;vT*ylOJ<%ip zZQ81^K?2enX$LHb6HIrhKwHh`44Ty`h~F(hg36~MW_BTghn>BNERXB}cVFa;dDfTW zPmM&$mY{y#>puIxn?5oOmvC#=(4izeMb=v5SVIWH5*pL}u?GvV3>?2NQt`Uv8k-%F z{T=;r{zAdle!SLjr4ZDaZBY%j0%_eFxv8kIvYu=zxWg2re*CzSPUF((X804<=qE4I z1*CnmFagR1wx!XdD?yH&UlWgv3ls``ahA(vincU6#nxz8wZ(t~K5Xq}7Y&-Awp=)s zY!%^f3SHMwm;qD^25^0ZCg`4sE|^IUf6WSq+D?f^3~hU56brdqyTnS!%Qs(}DL1T| z5_8dW8AC27CvAt02mih_-xlb2IB6DN=bEAWsWHm4hB4OXo1to~RjO`B05{2@zPbMO zN2-q5{BH?OF@I52op|8|78?mu8*A%mq_5;Qp)44xcd%M_D*#qF&FwNpSPS+Z)Eu%7 zwVhB;A#DRuT91BXj@ASIdKfBN7EWB%SOT%p(+1NY^v>WeR8@Rk=QzTU)6_@Ea2G1C z*msZY_Z2Z;(@6X~Uv1{>KN-Cn;>HY66W}U>EF5nfHa}deY$r!@Olv@v61QwvSrz@G z9HRGZ?2QA;gn-A!G+Xd=$AH_6=J9>Rrm6 zo=l1ulw4>F?@jaQKMANUkzb(~6_*eTg3Gc7VIr6~biL_SNGW))eV`)LXK9 zaFD?|)>cF^!tRXO_X;}*`XB<1kox3<=-gPt3&i{*3_$rv-<$xlq#t5Sp{PNXR?|xa zU^$5`2Eov?%X{@}Rma>v8g=ew>2J6s37J-vCwFjU-h1#E4LuvIx$MwYXzx?3F|ygT zo$6kb74}{R!4#bv2Im(3SQg#@vfGZR3jmq3;iDb-U`0#PWIcq`c5P%`3~ zZA+zdQ@~t+In~_Ic(L3#g8)MC<=SyA(5^Ta{+tEVqo<)dx94%!D&?)=8vQf3$JAo= z(id}YXh>=+=C*Rln@ucYQvzF>3#Kk&3*NC1z{@18ASk2PazbiFL`EN1N#8)EXZV^& z39xn#uQBGc`|%}7b#vI#s`33Zdx0fBPHdq=Tv^oXViZbhwhYutuzTcr z>iP*`)@b9W3pI(balysTUK^t^9IO(=L%@w`ur9f2?eP=M2q|n}durTbfiXftg*~U( zl6!vdV4L|5Y!EDTF>3AiCnGzg3u3esXVdu< zb#rMaM8^R{|72aBwjb`Re`b7;n&d*1Q!y}EqZJ6q!;9fD(V>Mf z()0}N5uOOShcM}h-e#dK@3iuEx-oDPZdtdT`BZa1NMFOokS5;Em1Z&ODnF_m98efO zi!MWdlt5?2eg#wXN>WPfjDa&5-*CI(KvB9a_vgNcnrZ8A#*rnj8={0xtP zTXtt{!piKDSHk;;ySl)dUxA{8vRcjN(W;vj`2#vn#F6E!RVd@ul_bOmh_xqr~ z%yKJhb7-M6ndSSY#4TN=;NRFnL^ARuecpW2(oi5NV`5x^%p++i>&2pW!3=8k3ZK9D zbGh$I5OkJr`EHT#k(9(vqg95O#&PIO>2RfbvN{p`eF39bYti zv>Utay09_3eOHvigC@200pRZ-(#7$zX?Q=-qol zR@>yeWIO7M`$V_<(=1B<>}kkN##f%w{e41ntfy4{JhGV+i}aI8q#>lg^9H_g_G`N~JnAfRzuZ4yH*v6rD9U+8y+$cY5w>KvzW5O$iy<*t7R&>NVB`YJ(Xw zWgIi@NAA|gpj1dm%*v7F;6kE0c4u>-6eRwE(ajNLQTHAcHwuFARceZ7Gzpr;=&=;E zI4&v7>yM7d6wO?sy*ye3xz3m&O?Ux67%A3T{a@l#S)-t`79QQ3O z;4<*qD(2K_p}HEdmQN!emcE_Bnm;USSnW?%C_heVQN6G6TI6lJPf5VehJE^cnHCv9 zl_rV+dE=u4?>-jFtd#1=d#POSowp)bpax9M!A`xHwwKI^#XiOh)o@?;vOOmJvq&R8 zSdp%$GH5{qZzv!;wu-f#w$B4az-p&kc(z*HU*5jDwN%^CChrh?Dai9%^i!}uAF4Yi zwWo)o)_}ZRboRWo;i@3_@9B>j_lP@&gP&q`JZU-rB*usP9m7)H%kmb}=Qb#&BM>ig z+VZ8N`#EWv_j2j(;~M)`U%*fN^%hLv3T>O_j$u!Lk&FEb!M95}h>0?rz_I`1Df&o6 z;-J%q?Fyg4Y<+&fFvf2soyu^T{)^&Tc1U}vpn}i>r!)k@=j>LakcLvhNmna8)IM5> zWSOTZ9Q*kUnEsZWFop$$(lJOZUEw%x#0?IFMIl`>$M+d|LA0sQ zuu9om%=-62NBYkG#uovkTzQqdO+SndKlKTBo(UZQtg{ZfN()$yufM{XkmWy}%Dd_knt;-LkUOEsB4R0- z1EXuyXY*j$=f{=)gN^j@Go#bL7>Lb16)7dVVn8eJx}vW=y%<(=twYuPvGjTGeFJ;` zqQ*OiQ*)HU6E1hRuAf!C-jKR<-KrD=nr>ck_5mnZ;j$&xyfP&=H2A#p@AFOx#X9GW zK)fIr88n}C>5q8x_j;u~1BcTcTH^I~Ds+PeyT+=*24u9)JT9@*zxo=Cz{drbI-|70 zLUi}F=q&B}cEc~T)Izv%Y4AJgW>X)3CH}{_dc1iD;`zM#!MttkE~^Stm!%mCzP~Ko*eShOwQOtU^W%;2qOpYi!-|c?RZs&7ZBF zwfMtJYpc`yFi?Bxad4TXZOYb1S`nQNvRLM}yXCbv z@$$MF#6L*wcX0Ge--2D|ObGGpfI7O>0FL*GHHQJ;N%dI-06~I!%%VTpo+4HuJkU6_ z71_@1eM&9%srM_3F(Kt(i>enCKc~_Fui2c?rK*HyB zmM_G~=iXdp1YCLjwwN!zu`T_k05liGXL+y|-e3CHzxdD>qMDRD{FUY)4SzCF=JO++ z+m{H9qa-G2l^kVh=yW059ZhpZ)$+I`$?^g7tR^zc*o$2j;O5Z~yPTH7p7;#ksjdEPo`&ZqU9Tq@Aw4sDO~w9*{pm#Ben9erCok zDBs8eEF~w|5S`>-7A@uD7hSxAvHw!>sp);&oG_#9FTK7E6PJtBq^B?!BOO2rvuRYN znJM^Q>Y=KVe;AH$TJ-67Ag|8;G1y1(oqj;n-?YHBHff67q@MK8GYw6#flV77Ug#gG zi&I&y(%=QAmjn$}#6MTGWwfiw7s}R5S>c7QKvw!=dRJ0YkIe|(zXUxDJQ ztYNmAO5minqnIXRrYbyozK~ez)eL7GvkktSO~AemFo9Ix89;j)mxe8OoK5z3PgeHZ z;qU?_eWh+2Zflu88xpD&{k}U_VP5ZoM}8W4cDri6KQ<{X;;cgr&k6_j~u8fSW20jgddO;5o5u>kh7-C3iMgYBe2+l! zlho#H`G=`FtMZvahYE&MXJnZf{6j?~zywN2%y#C!ec1%x3i>cRX+7SK#XAVx-xX)Icg(Rac?pE;2@BxpybRkWdE>NRrv7uf7c_?79q*l2 zZMm=I4GFJ>4Ix@iUu@k7uL1vbzxihK`iq`CocdLw9h3FC)jV%8PZ&)UJ~*HP(ic${ zEK)x}z!Aa`!x6uRu*5D@;JS)%hEXv=unWn@@Q8K>*7wHZ7;?A^!N>5xW(Jm{3&m$A z^I`_}W0_!vIEPw~H&>x6bq?Go=N0?jKhZ&i*khdG7;^h6NZ`7Ea|V`Z0}|x_9B<8d z?+^PVO#J-8I|F+O;JiY8LI6HH{{K=1Jy2iCL2omRstNsXxu|>|V6Q!>0)7HDXClXt zM{fTJFNKdGr+J}#b`pE?gdK3^7x{s=%utQ3R2EcDf4{|y1aesI4Grx3y_#N;ao}KIIT+|G3TUZ9jN3d#G>|KQy zFTaBxpB|o_8nPJ+;%r*;zti=h%|A(3(U3ASYJ5S}E!kz)%Gd~B26A6U!{)YHWVE1kvNTpCdF|@MK9X{!K z)k+lScRl#q;DL^CobvM*(GhJ=vi+zzal=V9=RLu!yT$I2owzLP z%m3`v8{2S;NcR8>IHPnyddr}Ez&&GeKN~N+Nncy6pSrgx38JfzycXL&7IWycpP~95 zAg-QkaeS}^Dg<_;Id6Cn7}#E)^;WMQP6@()@JzTCuRq_wYzyBGf7LYqJB;^^cHMm8 zxXd`T;k68mUwT77KcvV^H{2AbJivY`0B%R~JH((XTlK~p3Ud(rXBqD&`L2QU5ieY9 zYscD!+@R|MW+r<-{W`kuUhU1cWfN(kXP59lFi@ZZTPBM zv)7*O>p@NzU3;BhFHn84t0v8sZj)2*Bp{zppH`bvaz9)CQC1q#yX3oWBe25*T#wtmE7ybkd3!n6o@pl@VUzZ@E=_5H(!!5tB?#Yu z#LwV=HRi+qugik(xCkGlwAr-{f|nr5gPCeDU@r9D<~t0KS_r}eauXGF)`;IbZa3R= z;SOU{AE`As0y9Rba@NmLQ zMkYb6vMK_f_}K44OwSZ|BGk}f;r*u%lV|R~!|?Ao+h%{;^yuJ_V@Xs70?Myfm}6-HPGXJ>qmvhe*`= z+*9z`a6%-t5I&;04sK`j5{zWJ>47=C2R?&fp!&VyJ08e(?BOWkZH(4i#aH^E)mjRb zQG0imFO^Rr7V#{>E85pG`G^2C&A`a?TB;||W9iWDoinR&e)}W8d-dSI(Q(effd|2! zkIjv>@y51oC%dt2Tff-0jg4(P8{2j^wv)H--d$bY-Mhc0YHGS?YHDh#y8GLoz$jmf zROA$>mPbR@-^wp2#qa3p-oKTpl95%Y$@^-%#_WwY)(^#489PPzg-_xB90(|}v;R3D zjrJI%X8_obkUQQ*Er3Vr!l+hFSC4QehLyu&@vnw)2^zfOTP7qNoU50yQVk{fqiNo7 zflww7;kexXgG`8*>3e2bujhB=sxQ}9im}^M)LVr_{rOY5i2*RSl43(}O>6(B~!rL92#;SR+sYrkTJG}g(hUgG=o z#&P@zU(SU?xZM>Ave&`Q0n2xf_ltGD+t$@5k0OYm;B5gOmnH=(c= z?@`iN(vM_`?<3tS+}ufP7Z zbPaFJy_~K`*7aN0t^0mv=WXl#^sTqL@D}}gmt)U`OFZG@*uD&KmK+;NOxt}wn>+91 z+rdPy_g%nSxw~^C^7hbS2cKLR=(cqjj{bCEfbI?~k5r1!nXi!V`c zta3Bg@D@vFZ?R|OAT;>#w!U?PVZs2+^f(Nxjc`oe^TFFwcXCd_6J zb+-5Ce4)vHMlb^1V+VWz-VBKXF6?}S)3>Llx62wca=tz2xGX@<8v>FH5eJaIr9 z=7*I$AJcakt6scw#Z3Vn#^F8XAyf+!ItWT47x>lOcDn_u4VbT3ztoo1*q-rBCw0{! zsp>=!&d(9J?2reu7aGT;ttLz{NjB+|f)d?^FWJGi-;OyJUMC;@HjCJBM@4qY-jZ0a z_(h{~DIl_^QDd?pTNMO3E@B5WX`$*RpUB?5$iDB)UU(tjS3v_y)qBYIiDo^dniIMh zJp#!{5NgkXlQi$q{`P~$G>#*#Zius+UX0gV2TJZA#=Z!}g>bb#@}2znlcHct&9heU z+r=6C71nhpI$(pxQOxq~zc?|82KwnlJ7x5p*Vre{BAb#@R0I5Bs14l6H}Il<6!8T= zfcErI;l`rIQp^L`Xi*0~{+ae=DYB@M1)8jB=4^MFhK*sfH`?G6%b7al*01Ww$<=p@ z*rLsj`HX5>ITnUjsO0Wk#0?g<=m zTro%eXV&LomwVBdmegaGFcNG|q7x%Ug~!Ei?4&2&U8}&Zb>O0E9*Zhp#h9~<+U#3N zm024^#j=w%Y@)*kw(S_%1=J+kE0hH*w_!jAr}uqSg(f5Na7N_-1cAPZbgl|+G2c8h z+20pq^Ym8rQVRBV_bMTogcSDmfg=P1lGI1Y&Eg*-Yh$Bb5uJRyYeRIHOXC#5o>J*2 z1ZCs>r>1}dGioWAkMuGF!rVAmh!-U(;iYrH-CH0XsNU ztlmDg8t^70n!n4%;7t+U&W0*}7&|@7L6kYDB*@w?MbhKNMKCPl%0Z`q&r3y2zN^vZ zEP2b-MKQ!jQ8XI2FOq2Hz)A?41&c)ZF5yeE(R2ffRtV`zvJ_Me337HzXacQ8n6Pm{ z=V~Mgs@|^`pf9IZ5ev z!b0M4>Pw1ey;Dk+Baol8l(b>UIKsB?h@NJRYl0bC?p!=$%HwpsQzj@*?jF2jN?}j$ zf}Ma{vyIeM>#Vaom#^=ANYxZ63QKnKwMo-Y(45V+(Ik$4>rU=`NF8}DoBoXuG2TEV z;rF+)TbbZXHV2>X?cN)VAzL8FkF4a*4b!Kap|4IketkOj7p-0O^b-T;?FaKL(D}*1 z7(;i5^M;TA;!7Z)2Yh7@BiDV{q29lA!;X;j?TUeIk)GUrV8krB z*%`m~pxwXlN7WI|%e){*zLu`t99lT~_`X-<{cFYNLc*Af{PfB?#alN~Tdk8(M0uMg zgz)LMoxZ^_Ae5&CGV`XN5;jf;0OU&v?O0x&NlBtAV`VkIKHWd3NW4mHD;#SRXb2_E2ar zh~~@wJsnG%`0o}38fL}xvc5*!q2t5Xd$oZCq9;kk`o)SymJb4Jkho)vDb=jIX`;xB zB_nXFkY*<1(0p?n}9;P)5szxhm={}-PL`@fOxx>?v7+qwNu;#0`$e+zB; zPmlj41pZHt^qkWkOx_?MiLsy{wEu@k;J=i`|I6k7BLz0Lw*DVl;Q!Ay=h}$gDq_t& zu!u>q33+~~8|2p!m}*SF^*#KW*CMfWD_}(ZAtC)EI$$u+TsDK%Bx$J$yOmiNXmB*pU5k!_cNvFZ@Cc9Gn+7JXB)4DUruXle_aBO*}1w7o-^D}uLAxJf4~K0RQVVvS=9=jY2t z19DyZ*=*=IVCpzxQ*hwFJms;E@u4jQOp{~={eONl0#CZn8ioiYXtkH1nrlOCi_)?+ zv)E%AeefwSWQaXA(gulB%|M-f_2eHvs8^cmKkS}~_qs1Dg;BA3u0KUfjJ=RIe*JBC zuDvZp;1kQj^_S;F1a@7ZGH^d9e}IV(4Co2L#@ao0Xolot!@d;b>FvnFm4Jx|fnCfiH%Wj}5|&W0#l8 zE8@H6^x@jy(TBFcIntYotZ@zJgGo6Z`m*q`CZ7lW%=_w0Uno!y}*@$9#tZ0h~W^)zwKaDGUcAw>qcn!h!h_IN(5rN+%cl8A2lp2JT_ zjJpt3MQp{5dGG`)uAf>ki@XUu#`aCCbC84JI(pC#EkaWK$>=E^)uEZCJ0;(sxvd+5 zGS;BVhLXx*&h>;Lxe&){rxu`?pt05`2CFGdu&FOk9}+6yjoFNrYM?7pS%3-xeS(eY z=I1m)izOOOpBC@Gc$MI9nimov`jS%$%Ot z+kXr;J*xO{R*pTaL>>hsdOp&&t0lAs(Imfo(I+J4ACI*-M$q{i&Hz7E#yrP&m?60z zW|i2*RG>(h%Q|V~XLr0@8r^2bJ8?2ZpM$E?X-KQv?4XpL99~AILk4=2HQ=W)yVuC{ zsz5*POOWf#`mb*U#h#G7oUsC^;h%@Ks?zP8waZ;nVu9x4qeoUZs=RJCw?A>7$&p-b z{1PRkPS1>rsU_|drNCN!7YDL0bPoMOhJC0L2TqaDUnGS1_@voS)4-&QwilEGnk}R* zsY@*}wrIa4mVsQMEdtFg*G@G#8#RBvV7+!v>aC=XbkgDvb|>efG$uA5kc2jPN@hMJ zs-d@ve0L=|z3L=IFKUw8l1}JY_FcZF!?uhe#2vm8L`vAA2ll zW*6eKsQc~VdvOs_f5tO|U^fT4TFo)}0O!U7^KX8jT7oqxeI!i9J_WHMDo55}yNmesreKW!L z<0emVVNzNDgy+YF1QxUmMJmrvXGS$Sn3T}^(ZR%r2UJXjg7rj)_@@>WnBIaLc*SzGA4jWlHc!oMvn15XAcPkYRg zNph|?zuS+fTYNlwgGsRN`Ni{}UO`?06y0nbz>3D?yV!~4<*7(ib+x?`nHfc`yn%w4 zDIhBxL{?`O^5wTqOso9rz*jY`+$hwv0Hp!1688sOWw&6_tntU}Dk_0J8|FDK>f$ED z5{L5>Sz0ko+Q`;eGA$Un#3bhYq862)IHj(HAZQw6C%3#ozixVR#4CC0+6v=YT9On~ zh7`DZHCGiJtG|)E+_5|KXdVUv_Yh|{CV(3U-gcBzGRgRzcNtElg6L4T6bzj;HR+i8 z2xlGL1xvg1r=M~UI|^jm+>XU$%NuA)-GqyTooTR_eBxP*-z6@5HIE}p+a+n{gEq(2 zt%To(TxA<<1|1tRcG&c6Cdt<8Oy>#e4yf*FyoVC0Ap5kg`)fa`V2^k-NL6cdEFhd= z^30lSkMcZ_4pjr9*MWpyc_>>>%nl=n5&S^I*>G?ULNcUHmKu)WPqo4413{xTF%H#G zkNR_XBy}#jveJyw(tEWrp4;MV7(SX|MyNaFv%VH*|94yV0F<8594``&EM9q!WVIOs z&m}>Mq}W*d!Fsw&Guiq4V%dvv65z%+q5W4otEYak-?81j;^ZSAB@(^Kp1)%tvW<+e zl;orZHlk%_dd%nNrAcbr&t)1cqhnB-*j!=N-;T|p3fkI6{Nmc|VZtWXD+&^D|!KnOFS!ukbyPu&yo8zSY+ym79V1-A5dm&&wS5h`#ImGJ%M%s(N4bb zaQ}{Cp`N^Dp%I@c?n_!%ZI%lM&kpvHWpu@C6v(TV&NDk6DIGiikpd%AnS`sfwrp=+ z`5S228xF+p{t#D;yI z%ZB&gH5(WHhrc2D=Slq9yxr2XUnX^YyD(^W5et}}v=;mj&5`U|aKs3j(9t5crL z@D+zn(-dyDK8(ZX#EeO^@@TG-_)lB8H?#axZrY{CnW%7kPB=tlk%KaI?!+%6snc0= z<k~4oA0BmCR($B09<2Kk3+G{w;unirvX#4n;@)2h(E1Qbbl! zmMtv>2YW{1FRL^IH^`c(Lf+;Ogxm)417ml|X{C~z5;uHQt~&R6??2^J-uwC)rPZiZ zTu#z%-K$6Ou^fF$M^&aNo9+i=am>za>7Nsp@kt%>r}4}{2uIgtt)%puXpu4FWT9$g zkvDLwCp0$kYoZ=0l(fiu4ni5Kl4PDxhdjY?Un)9D*dINZqw6|OQW|e4@o=Q+>G`Dv zdfsQ6IzB}~;bf|(RTTB-UfAiDx#5p0S|Cu_k~o7l1bK;7uaffnB65Z`#Z+}HEzm_4elxOgc&R@-kL+z~N2yQlcv zf>!lxzepmLb<4KVp^ZYdlt`WwrcD0oHfC*nugEB%nI5g}_a|2jJh+{kx*R&zCxkY> zvE_6RxnusPH)PvPFQHw(xx=koef^yl$uqc+O{4li<4t^i;hxm(84^NiT868VK2}3% zGLhC}IgmKJ%r7{uEA+=?-YZ+Flc1YaO2+1RIF|Z&>Wqn<9o0xGWZcYp1P`L=2r<46 zQGyj1-rA3<+otiOHmpu$FM%TQ=sEJ3QPd_Cs28W+LV1}mRp4e?Jp8MkaUN9yGLz)j z_tzZ?85SX?t99DOTDW&ob4=GDB?3X7uM%?OCvj^f6dZljH=mrea!47m9A#vVAETF@ zjYR7U5WRp$b|tNc4g~Lh926%*UqWb6kK-+1hj5o!6Pb1qIw*#vN&620L-gI=B5XXv z@41QGct3`mWRJ@Q*U&5=7(oi)E5h2h+y91olkHMBPSuEza1blB`821wSc?=W03nohF4@b(D9&t=4T{NZYuhRrT zk-tCf^^pzr@F3SvX={r$2`|I%wnFWXuo3!LtR-ub!eFP=+hlRVWkqXboy*@}sHc?~ zVOO5eT9d^{?(l@wWFx(kt*otQnIKQsG{#4ZH4*kb2Bdi*Fs5kT@;i1 zia%=5_VaxWnDpulvp%TP_HW(?!nAx~_;<9y+IP^AkY4GK^|NvG`Y1ouB{m-nDe#fY zs=bn+UO!%m_1fr91W3&7{;G?6`*Mu4(~vYp(xVjazI+=G=*&J%z>0|bfG*SqUg3mv z7a>MJu;SA9F~j1#@E3>#meMTD3FnzCg%)0y{ZA~+k-A<-KnR}4K?&G%qr6?aVOaNj z$wB%0oq4(RAT+;pXlE9`Dg=QiW}KJ3agv$P?hdlNNt~I2RIxm@5zq%ccEyd_2WGEC zf_DLQH1^_LYqyg5NGx0tjg2fo8R~S?gQO_Ht|@iMj%)*K5*Cwb!DIAd9U7Y?Z;!87641S3;$B^qcd)sJr&_QlNy9w#S-Ut z`rk_$5VuK33iZf?OKg0oy>Qb z()3F@2<6GyN=A+5D4_u$HPGWBPsw(EEi2~ty%-*bBVtg-{CJC!C+|>{f=IcUuy(+j z6hWqDIlDCnR0edh;cXPstqeMH#&it>bBydbwKdc!>J%;#FP|v+1`wEO+GH8xZsHIg zWB;mAmq%l(Vk}Nt?EfS_WwkcqF?!dU|J^rc{U9Q?=_2cacDD)?>{3?WWb*BV70vdd zBe%l;m+-J@PpYId0^uS>` zBs7+W%n-)Y&)04;_g-bY*veF98}in3$jE^!mvAv;CsUzxUwQTX{zPc7Y`xHIa?9Mv zzcy~|FrNthCD{T*Bcni<44*C4SnRXSyH8?pvl&?qomaLC&O+LHG>U4GYB?Mm%c#L) zUhFsd;bd9y*Wdkq8P0lzh?Fep_#%;#m?WjKSCO^OTWJyukGM5c9kQjeijq=cO~m&c zudK^2$BKtF5?E{B8?UpiHPxw!{I)cOMNHd%NRT>TFJc9>eI4F@vl+z9{_tgjD%#y6 zwq?J#DC{eDT=CXJYyg`2&)Qa6XmKpzqe4NMA{0`7cw0voKY+7g3Ip&K%Hv%+0>> z{Z2Ql6=E1DsK^UG>uSdwjwp*p^J;W3{P-3*E2&Kt9h*MHpy|2GUuRT7IAKs_+3oM4 zb#$WHuVHswYf|=0%&`*O&yo6Ib@!4_K_+1u>vAhz4>@$@!OHg|uDb5n$#U0WX5kPg zip%x;rKN1)a(RjI7(0$S6>nqvaZ~$%1ggeb1x4k; z@nHz#iL_VyBh+$Tz36v2ny%7(;$S)>lpDez3V6g8002|Tb2X~ zrLS--K8MYbtijt{I#>3dY?lxV+pB$g4byR%uvT2SU;_oYMVw~5#uCnDa{_(M>8?OS zY55c3K==0nv8Tg)^MUvZ=sd=2dT)z^`L}G~@kAhU_#p{4w~oUvjiS#qB47H(Slyp| zyb)Tc`YZSV-Ku$Hfy!UBIUk>Ol^5raC6{!d_+90v_$QfN`6i8&&!OjCR@sS;{Ye??;)^(AqyDtJ%kHREys z1LW`%q6uV7-|j6Xf*V3SJL!A43!00rgokOm&fZ@+ANd(2p0IdO#Wve%Na{jQRtgOs zkGkeC|F1Y#975+%<_So5>-0IPqks=uJ|e>EqX31b1Y@T@b~>9u(s5$%#0neGaD=4~ zG_>?Sb6RLzgKpWjyMDtr!3i+KWiluLGInbw{!Ouzf+7hVNe;P=6AE8K*AEkha6ZMz zT_i1b$~4VwpWSdiX7d}5+&dE4by(@MuhnvvCzZ&<-er*M4wvPz6Vct)G~IsEQFC!srn%Yq6{IX??zF3@Jn#)O&AuL)^x8~F-kV`m26oQ znWUyVGfu(}eBO0dm?m2k$Cv{n+dOt~Wzf;0M1S@J87=EN#c<>6id%{_(7qcfQ;l!% zF@h`zJ}vmYzfgH~?Xp#sohssi9G*HC_vXSw9N9#xAb5?gIhMu}aQ(6MoiHVp5qT^q z7i*aQBue88(w5@nA|KwB3Gzd9_2-@xeZxmp>6NVM-c%3vs_u}4?5YjoNS3Z6j7M#4 z8~XUXf=5Cq=Mk77Yz{2+2FIQRlG#S8H>*y~WaU5FxMcxfxiC{I^7Qlo)6E*}U{(=a zLc+fcHW!%`4Y_;2hQ(V-MDQV)JoqOgZ=6BpEnt&;$sqD0&)oYxu5&suejL zcG5C`(u%{f5W1);*^rKf&ZOY)1V53OP8Lz4j?29q&%cCg16)mXIxdj0OX-5yNrbon zK0CQPx8(vyH&Gu+6v`jKSKzYaYBCe2_ThvpgyYHQ$#?tX^6AX?X@rGgKEW~;W=rfU z%+0Ks@#_2gH;8F&dV)(-d}+qeZOP_ z>Bd`BA#I_^rNm>Ay`Jd;wc}j{o!H}M>xU`o2!5TJXcxENls+#3lp&12`ZyY%aadmi zq`hbF|i@)cf4Fe3=)!Eih_-##I!=*st9rG5z85Xc#hFQN`-mI+5F zCXk7xu+KXDY&O9bA2iSj1bcrmO-g-o{jW~2E#1)`NN54k-QU5W_-?uzH4}cdbi|&9c=VuJq*RwYZ z@8SLDs}>YM9L8Yo>D)JFdNMl1pQ7D+{fWkz@=+J$HTI+6SP1$fkQW`+=nsJ^|Hj|> z+@>PC7vGexqARGIAcwX=ubHBl6uiy671Qt=kcx8B`{u)3pWMSj#=EzKIo6t+N7H<0 zjyk-w@$^Fkynn5Tr4s`@9kjitqNc36iw4xAt9lN_9abDCSk!=IIYkg# za0xE;JHta=+@oKjcx;Z_oZf`XNsH^=%Ei}a9x^2$#y{As52 z=v4FBCQt=p-A^V$2BU6|%!aqmzj29EhDZ^>?fvv|`Et%LJ6+;W!lS~oy=D^73o~0; zp2bAQ5<`RoGUmbOoE5So$NmsCW`5%Co|N5i{nI=}c1sVmt+&E~4HKiD!52l^4ZEgd zW~DB{pEVHbrl5)qUCD(0?}mSOkSFQ}iMy=aP>ebY&B&dBQ1L|m z52)W*T-NeG2*l_I39fv|b2TELmNqnwl#p%MI?SS?fG$gbhS-Yn;Go+vIE7jf#{ z8osPfAK$T1oOdq(L_wscTWl9c6=U+j;ST}9NAUf#?$r2H1M@%0aB=g>7V709_X2vg z05!>Zjh^l1!<|jkXsixteg6>9Wuk|H8-GQTkG?7YW4+IaC5??e@x`4pdJ^UOJd(pjP6{9Q~uTxcg=N;84dVwgcu2mwUN3WQwh_VL2C2&;6o!8f9A>cy*W> zZ$CF^l0erl2!URU9>%kGt+ymZJ}=wPtFr`Q0XIAVy9Wbvt{OK=?yChLB&Qh$ws!~v z<*tpG|8j7~cx~x^LkevgEbS9DEzgGnZw3KJB%*6^(P-gG_Ij)nBIEN*5)NL z8P`144rXScOjjDEbBX~#ao5DVX~O;CaJo%p*zFo^$;wc#iH1-%vW+QXilR=J=ku+V ziSS$p{YL{EUn9s-X)0}Y`Z9)Ja88f+HON;eRiz4{U=_*8&lNNYp!jOui@TBA%*AJ0 zwPd3jIk~Pt$+(z?5pk|NF1a#eu)?L=9bHWVG@n zzidhKD-)hIZs-8(0foF4cnvW&(?AmL+hB%%X0W+b7|9gRzp2|}i;IIq4&%@!g*FT- zm>4jLlypIQQT0)tuvDEOJ;K*Wwvl5ib8h;1YJ?MMvC4*QCXcM4bql(X z@c>4YVd=Nrv|0lM9+4qpd9$uLkXEX(T>_(Fym;5XAE;P$%NQh>=L#c#6HJ7!mh!f$ zie^9q{7L8@r`@@!k>&hst>>FGUI6C~Kdy z#ky;hzU6W%8I@dPMhc^?9d{25J{8tYe93a0 zg&%@-$86V!SOa$VuAiyZ46FP;t#V4HQ+9cNfhiH{v&^%y4o+Nw`oo%6%sz%SIcs^) zjFD@zFvCHQ9DAz6*ZA#C2yIT|jg|;9wtZCnxtOP2NnxMM#rR7$@N*NEa_lU!(4r7JME z*zlRU(10znsCe5c!WZd;Y<0TV+#^gbz#)V-F*LI2MTDD0V@t5p$$0_F5)HB@(mrBq z-3bx}(I(ll6-=e$Bs6ZQm?I5kZ?*4hcDqx_cvo{s4UtmoCAUnJ^6LhI_3WG~JP7^}IpGc*_aKzgCj^Bxy&(55dW+w%vu#(YVXz1&N z7crA7S@fmUaqs$XWszAPHlZ-5gHu9^KLf9RG+2mD#&7(_R8uB%+8gJP=C4C0~X zo1T1dFZJ$AVyHOkiqsq|6f)4Vp~`d7J2|45=-)r0nul)oWHF^QqD>*OF^0`tMqU)AmziLpEk&kZiy; zDzmD}NC@+dkd2KkekJ!&`cLU%dEPg!K~6JKmI2iKIF?RFT{dvi5hY+RU4@GhWTt&N zf~tam$>e)e3701ZIj)D~D0U4$DK}omu0H9tFG6`jmZZ!JqIkzI=I~KVqXvsbdhix- z?sErOBo+6Rfd~i~fe_HvVaKQ{!_jQDoiI6LG|mDHADF0GPE-?I&^B7C4*jwpD^ zsZzKtIeRoheI(N=?1%ue#E*Vjb!&oY5ClJKNF3&xST>~o%ppTG-Vw4^X}2}1jG|lx zA5C|0DV$H1eRRl<2Itl7c|w%>xMOXd_U8kSj(bC>d1=UY=Xo_lD7fkTp5O&0B;`ri z`i*Z>e#d8se{}R(PjZt)zOWcAPt%>VEKtDszM4N==M{f$A8rH9>+uFCss;r_u&*{| zqeUVxS?fs~(Yln*)(H9Xw3y9MW9$y+1o4m&hql3;nXvWVC}~Q^5tSQFTmE zeXP5Mw>N9U==^{I94|#egjT2~NazRtiTTr%xw7<(*Mn?bFob}g*vR#E3j(!%ds8p{yPuq#8_D4zA_e2ZRT1Vs=FoSII+I50Klsrq zx#k=5MS6OB=0kQ(hSLv`a}wrRkp)ye)wt#YdC9NUl454hL}wEyhE-wKh>9l0{UYtS z#Yv?UcNOo8s5J3Q+&&h4-fPGjIp8P3{SI9OtGzpMe{Y*Nwp=aA8yig=!Nv-u&Riai z38hF4jSfKV{2~$jlafO?Ilc2d>|FiJgR~y}<2ZcOcawo1TptqcYm=ca0b1MAtGC(L z?A|p}^qhPUUdLc+@*|jAoye#4(Md}->r}+D>bC%p=eQzeHCpnJja=OF*i({o-zrYN zzF&APxX_aSQ)bv=t?#X^FUfhIX7Wo@`{>BfU<0^nMl*Iyy}sj_Wh56c5ZF#IN}E~N zSJ%%jIoDbTzYP5x&UeMP>fs!bo<|5*R6hId{ei^FF|3;=Ja;ioloujde$CqEk#!=s z`eQZu+!a|j*q<$oi^A~%f$ zFBEt~61D$brt=U7dOm%zc*;Q7Mh@tkLQRiOjV;rUjqQT6g<@35d;jhK<^LIeGI z4WO_1us=ho?E*ZDa|JS^dvCh2GT*tXSdn|DnbdCR8Th|hc1GEenw43J#Y?;4wXa!h z1&E6NFrHWN(&m}udXWa*Lc;+UUip)0$}?G~cu*Mm!sBs9*NYtw(~hw*4(F8e_+~zR zfkt4Zf_M7jv>)t`rvn0B-7 z)GzfHQ7`x2C8}?T%=2>{{5S9Te=3Udt%x$F%^x5do8=m%!iHlO}V zcN8ZF>>vWcn5GCOk@>9wl?2noT@t|EQg)~d^t3nldDBkqTn}GjU>8KKTNd;iQ{&$! z0PTEH640S{<@J9Y^r+n@&p$;g?E!tHPSYs)I(9~K<=uQ-@Tev9hZXbOv`_~0AdVcp zbT}PWISEWb6b=f!LF7D%03S#ZcT%iY-I0E;U6&yX1N|Sz?0Hq5GT?FhdPnMv)$8L7 zGnLaiXjIDumQB!=q)<_fE4#Zcs9C5*+jj|1l#b{Z`zo+MKfL1q;FgB-KHqi3JAy_< zds1nM*sB>2=*Zja!g9<7?@1t`Kdqr-YM^@()GoWvLiS5yC4O_-1&Z5@W2fnqPguf4 zavoHKURI;yjfy_HL4wTZe7<+||9c48Ld70TLzFubA)U{4?4e49%9Yh#Y}zo1locryd59**uzAkz0Ts!T8+9L;CrpdHGMU_xad$NIKC@s5|{jJ z@dsi?7D(G);Wh_G-F+*<`pgC26(VmX+ZyXnZM0PzeGxe;Uz2>Eh*l$J37(24uDt`-QHC34V*4G5kKw zq$nn__Ak>urNWMKkatvyLl7)D|7A7Jugvk|K4i_~@abDS5 zM-}daHy&l?1N7pr&v?RxRObggq}T>X%+?eUXgXUIGRoPz@5Gk}CD+mlop+#E^H6q4 z2_vQUa09lN{B%}4Mv$ev;MYHEkeVXoYM1M~)xtOXyIS3Mx;+H5y2Dv4AUIA!{;cs- z%pe6h5OBClPACvyy_tV#J=WLX%;puX(J?s(MKF!v0ENyfJx5;za7r8;a1Q+Mxs2Ds zF}9QZvQ08A@^FjF0j8xPdT@}O?-4nibY!^0s(I#o61rdp(j`UW5!`={vpv_ zfma&m(!u}>*mnO;nP*cMnV??HS z3o<-vh!}4E3ac$uNscfIpb@Dh5LBeuukD5mQ0CVJ=ddT8EN^KtS7Y+AAvU=0qb)X# zjj;&f#w8yZ%-!;)Cl_K!uCf&wypKAf-;U%FoO4Bn+QW4 zx|p(|*#$}Nibyy5-2o$?d&Pwf1mHcE;HSIOjydu;bM*vxM1_^g{(sX3B4 zVC7AYDLyC}J*uSFn~PQ%*+g1wZT0th$SnEU2}_cJ#2uf@gW+d1&Hc@qocYPRl0qe# zYb(z_7DwILfH}R6rcm~TO1`A3IVJ`peB31g1HF-C57T!$v=x(h=5jEf1A63mY?XYp z4#x4P2=NYkYQbwf+L<%@9iu8t-Khn5p!0jU8mc?8;YPb7Z!t1?dxi`;q<~py;_vLb zYnlmM1!TGfFcIA}e%^EFtxk|wBXpB%P4~e}R@eUAF;P-L<;v;n*2kGalyq}oE_#|_ z?rzTZL?-cTWj*(ep|C>JcZf*m8m`6)6az9czj`qCz=o3BWn^s9N=;WIim6u`D1P{M zwwIc$-q1GNen9T0CKvWs68=3MG{%j~ZzS`*VX?Oz{sz_3aFv$rdOrRh*|tOzDSl7+ zK#ulZxN`O{eYFgQGDhprWAMrFq4YTIGfzIEorwhm_)*0hv8p=KtB_t77+JWBs!@bd zR+!a7Iwqj(6Q)?m8bk;w!i7UxA{2>@qXXpG?$L(4kQ0 zPz4t1#UN;L0C_g=ML!OL6s1omXwVppDv@x?TSQO_3<<``6x`Zv)AqsvaI>+=w2U2J zs)mYLBO{qv@)T}j?=WE-F?HG7vHiJFhbMeh^W?KF3pJGUx!B+&f7?xXwdvO5b=7gz z{dCz8>)cNW8lLJ6>bQ~_)Ik@RgD0wJY4-RCwaq>si= zlm$hkld8D$F{~Nhx7avss2?6kpHbDAepT0M&WGS$SJMsYKv_=L_PBV!+_98Q zdXx@$tvjPBggMVor<5?iV-Suz#MW;C9R{(f`7N_O8le?JZ!0s25MEty5R}Y*m!Wv1 zpVY`gA@40oN_6}mM$_V!sG+3d4K#IOjvYi#&Yct=ds8z0a#bh%wqm846>)K*YDru6 zPl{2qZhDSbL!QKi&>zpL8%)ULZVLk#vdO68pHB(AXOhWEX2d-q1 zN=? z(+{3X;!apv^3A_9h3N62Njv1LKdr$<)D*^fP%a9`?d?OeYsJ?P%W%G@b#;jVwHv`D{+;k20F+oWhrdfqf$TlU48Xjs!SQg02AK zBKP35c@wrRAXvQDNk84&p2GKfe%yxNMRViLfB$qhzhY{hxb`p`^OtX}VI_!51TMA+ z!Ul|)@7-Bq&<$cJ?a_pb{$W!a(yhwn;g!$0NkezN%4-?o;8RNFARiXlUyW3`h1PK) zmPnFVS|??QRBSGBP#P}o->Up3D4t^2+X>30Qqt3(fG>Yz;sa4sJ-a(nw{+|VjSp2e zzEAq^QvxXVfXDTDJW!fpwFUw`=>;72)>H~XQ+9r{Zbi#Y+nMV0lAxU;RFDyJ*zR~-)uOxV zpes6m(LpvuUCqsP>3yH4ek-A}G)qJ?>;HQ@*dX1c^?Y)P*~O3 zV-3Yu4GS&Jkep#zqU#4S>;)3rIk5iyMTFKl%CzY!^wGa; z)sVl0zcW9IA+&-hkk|%Vlk?vU`=m8sWHH({AquIz$<}f)k@c~$kNaV8TJ42n^XQ-! zqDReZ{h=Rhh^|S7#eDRplq5LyVU>md0nCr?P(=^+L1YXcIHKnJ&BQNd2QA45f1t@` z86JTs;pwJQSFV@*p7!^BTmP1tIHH-lcWpDmd|q&aV;9DkQF=ppIPV=I!z;vq!bdld znI)7O^PO#`Zxhp?eyw@G@ZzLSiHLkt`PPA6V`s1=qSm5^o=I1eO)EcF7D%t^LTD`MQeV^&(m_*RT)M4r&;+)S!R(_Nfv%@s#Nr#n$u8}r^k1rbzAu))=PHF zG=1xGu)gcSGnx;pGttGI=5ryvG_a(3Bw8lgSb0Z-oR?|r=CHtcaWTqwvqoiZt5)VG z^?Z^c<8eWF?6HDq4M+DT6Yil>3G|{U@eXVf$;PpnV}xXyBz@bW-M7WR4%|Yh5n;pc zrkJy&zdv^{xp}VENoAr7bNI)|pznJAqkX?xeG^G# zlfFHVc4Rp2?Q7sT|EA?L4KNG-Y8feCZz#=ti=v(03Nw8gnAgE!93{$x2hw6U2kVDI zz7ONf+Ggk;{hTJc*>6>>OEl>D?CoQW5wuyyY{N$dUIvCsR8kGl;HRSyQOW%LJZ#HctLMXn|e8JxN5Ey{c|W7)ycrU zeKEA8xj0yPdIpXD%n1cG7oh3-B6Kt{*$H!g_u@yCs(^bAE>|^=uF091_gVW zW2VCO%fNx!8sQ_nvjJki>b)*Ni9P%ttZBB4^}W0q!brz3YyL6a6jc443DzZA#mW*J%a~v{UFZKTGZqocX=rm#kgYt{! zg|}5BD`s9l>qyc<8PUv0uK>r~4_w(KDiMli#;_ z{+rH~DokE`FZIUbXaM;-?O`go$GbfXHS!UuYZDq%b z?bW9WVEQoVox z<#au76+}{*kG78XS5CxheelwV&hnsu1wxRtUqhYSfDt;^zR6IQY^Sd7-s+ZD0L-`^`v3MTI-9RLl_Jrlevq@gyKZat(Q{|)Ys=Xh*xN?LhMs6_fE z-}A4O@WO*H5Vyy8*%xijrvPDA3|86ES9y)G!1sELN9HaoyLpD zYH|PO`l`U3Vv4wHd<)0OI&^ETJ7qGS@e=AE6yOxv72>1eLdpuaRiGL@KCRsX7w(FE zJ+2kD{r;zw;l@wtWn!7JlB?1mGZ79UFngiM0S_UVV?U6inS+dt$qOs=mdZyC1giV1 zY1i2u9RwokiE}&ph$R%9jfocarqmzwX|^i(4;YBKfyDX=h=l+^^^aEt#_4 z{$^&8(|grY4ljHO<}41dt+~J3V0Mk^ZK-}PIF*&`D*We3# zs#17RFh(Sa5e)dm+kwTdGy1Cvr{#O<3M}G=*uMPCpHSawjGvs@c;G<&k-|WrO-8ik z9vB`dPw$d(**-x;AwTqaAy#|5miE+smn0QIQpT4x&I=_XAl2-NQ8LC%c(-qoxLgqa zR+xpBn)w^eKMh}J0rmx1(fh*UAivXn)d5)_L_v@ZVh0e_{0NC;z4;})rn!#oyG~AP zc;L6iwASB`_H=Ud!W%1>=_TpFPi%dSCRDsud-1oH!-rw|G1>Brti~?-dWN8xval?X z>le60lAX_pk+0~^+2SDgf%3E32szwT%%k)-Rc3Bfgq&WA*><$a_vmuH+w*Hd7ZHJH zJ>HTer4>NJsUZ8Wts^8rmMg9B|0ev-BK2X zMFx8r*}MeVIxzaw-MM=bw2HxJxM+xYa%RIkBtF9!O}^ME;c=mGG99iyV{eXc{8d$Q zC4~MQhsX<^zs)mfqurHKLy(a=YWB7((eD>wC?9Z+j1=BqEcDe%1C{dp%K$9i<6=;6 zZ^7oN?5)4#ApLpiJPbF9M=8O*2?Hvh9vIv2+;wSa$G2GrwTgT_R|<6%WkJ`BUG8UB zwq$Pv@TD~NhCNXNLZ2qgh}fQ5RfjKa>C!#tk~F<6#&528S;46ld2GUGk!5HX-4InG zEe%YULWeM=wwt5Ihd7FYcv1yIKvPYe4sYWg#P*s?XQ1URS&QrpwB=&2t6*n63-u;0 z{Y|Y9%u(eiYzH0#RzEoX&61*g+u0;P)J%OXYDO==@Ja{u7+XQoU; zuFKA)~84qKX+qy(xacpb&zWs`i74`S2!Eh(s2lp!d|YzXA6+X zvHa~=J1b41Y7_-4TVm=Q__|lvUu0HlI9RK&wY+PGI7xhMb%5$U?VV(VQVFNE#dIV& zEjaKv(-z$K>%a}}E%Xl;pO^leeX|Nf5g3m@*IZY_{TA$+`{oW^OALGcCj6P2S< z)k%%B9ZQy#@BXr4R;##De1zWE-Box|-3F&!(hLpvefbSwK2^7pQi|9F*p5ePmZ3?y zJ+YVAtM>G2z|`uxrqT(0%&0D*aUgrTz)Lzq3i%DVA@XUlxK`*O*E3yd~*PwzRu_Kn^jD<{MG~5IEe(n&XgL z$mRWU$G7u7SS6h)M+`si-nX9cNMcX1dTn<0dnDH8&F}h48O$mC^a$bp%ubz2d%7e>a~SzPRjLQB1wFM z;ciXyBCd z5B{vcva1~!*MN%qADp?T-1G1hmK_GPIQ3>+1I~=IBoZOTC%U9v+^T^TBd~dU`d6Dd zozI8zg|HW<$BeQf05OsT868V30`Y@xP-kgg<=@opu37CZVVN(_nEaO@Jab>MZ!jpU zp?^Fj;aG0BDQvvh+f2Px=?Cr4=;LlxpMPY6c=w)^j_&`^E02&Qo$_~(1-fCW607q2 zErt)qDdzffzoI3hUaUp==6tYek_dPU4fHe(4rw>Tn9&^l3-o|1B4kA*w2K`qoK0%; z!W>GJbG}~oz`5&2e}akRbextox#X;$6#)1 zH5N5I=!PW2LrR*Nv`~L#U%FTLlIg)?|3VWNkNN^F&BZFOt?DK=Ag)<3nR8C4{QOTO zJ9M7TQF8ek1#l{exfB+)yIU~Ck6I$V*|t^C?NP%*ZPdaKj+U%QYdDI)sAezSP5V?G zM~m0#5)h)DRg!M{gVN0Rdx=NjUlOsU*zO%IsEAfV*)3`kn5}_P9Cl|q5X*KxTB~OL zTW5$Sfm(X?cKn`NeN<4LICcRx>&eZ@i~l1}zl(V}JfJusH|B!`w_M%>Qy@G%Ph@sE z96jT+RHpgLX4U^Yv~I_YID&61vGn3ck9)^wjSEgXV^rJFc9(lkoN8a7$uHV=S&3>~ zCCh$BOTigNCg%f&5Iz>-en$eo%X6&bRpuYCFvu?6>>|+x#Ylo(8dRS*BOFoEy^Z`t zx4U%>3w&4Gb9{1oY{F^~BYx-!plSO&78KM*z29iBzBOlD$k4>?JIIN!tI*e0$xuNR z4j`a(fB9zQHH{Es6^MqGNt5BtOfsLHFK5Gwc{mk!JH=;;!D0#n65dO`_Zglo8@wC| zVlO?tzxmN&=}gSxqMv?^8Ac|N~VXy(T zOSyP+4MZt1CDpovO#BN%p7~pJO8HyPp~rCsk$1|Yeo=AjBK~Xh>J7ybF|Eg-l81fB za|O@zX-GA{1y~yE#M?eqFP>ROAqCp?{rMBx*%_wQ$NqPI|ItCFZ(k0X6wbG16=wXa zFlna@mQ`*|;U>fyNq8Sw`xINiEpD+iQJD46SpHE$_8*mf@{fYTa;na+)8*7zREO4* z8}i-;)BBX;5aqD!R$R0{^{4g^pSph>pBtpVs82MCJii*h85mz00S}|Q6pYLO;xk}c zvwil@elaQYqRLSGVlv|j>E2e6^$ljB*?5|@P3`!uE6v-O;?B=z;_afn#W?ph5X{Au zA)fJFe-GSh<6uvgYrl+j?O25ddfg~)GjaO~sQZ~2VhUE?Sb1mPW{5QF=$EbLrEuA= z8LYQFoDF>SHa)d_8UH@h-Ab=>jt2C;NNg^7XVb*FGfh{sq8R3sFyCd+Bu^6d1&Y!s zm)ri%F~)VMU^~trPy~i%NsP3*zP%PV4x~3`%&&D$>&%tGz2p@;)eMjZd22(9qu4Y# zaNFPTlo6(s<}a`0XWN&f&5592aD0cREe_Wr3$X6lb^+)#I+t=vLedGIy#d(u%@`xf zmbaWa0sT8i2v7R1V&m&be76>fCIYO0))UyN#@U8!a`w*zBz*ihNHM^C^39}0_@H|3 zI8dq=9soPMk$aG>(#p35MDz0a zHhA)?(wSe=D{nLe{4oS;0fw;|t!R2j3rxEsJG<{Nid_2G1l)b!o3uW>yoOq0;Xiq` zu)TmIrTpsGchFiqxI`Dq74HM|-rPH?&<=ZeJ4=<&w0IogyR;n#twI{95~aQ@Vqty! zXm|-*c-MA3Mht#cj3N8{h*zU=e^#kCgo4p3PH}U@gM(&hd|GXT1kA%^iQk|lOd3cE zk(tjykIQv);r>iDS~aLPqnx=!jjSMN`rPjG^R*2ab39*6Aw&@H0 zbyT@yRTsSQfYe1kWCAP`Tg@b*?-aUXtB_o_M}wi+S)-fdO87hPtDfm)$4&ay-)$hY zJI=v4@s1Q&>M->{1lCDgv(&YRd)JhsxHFB7+3g*-va3=TQmr*ta&~3Bb@m%tzRAh~ zv&|H)ZyKnxwxAi8(dKJ1^hOflys9=~bks*&HYs^qTd|~I^i}3La7g|VWz2YgJU-VUYTv+sZ}s>y z|8e*Ga8rf=FrE=!qN05}xPQnB@W>XjUw%5iITBMqELKe@N)b~Whqy|ei@nB>kS^5g9nkXrtF7V0&Bzt;6Q(ih^OSA!jE*7%25 zAA9XN=nu~@fSS$ipl5C=tVa0DYi8msRrm2w8Kl@d#g2TR)o3UWBJH|MBzGFr7a$;o zcg%R%>ecRLhOBqDE~gWV#ALU0wp&!Dptd7~`d_!C`~qCT8A6Ua0!@Nk?8gzM+~?H* zaCwxGTG3!Ha#rU1Fe|0sv`-v{G+z|-^rG&V<@Yv;`0~1O`NvJEdtGPJXd>m&ZCbx( z{Sp%Nh%`S}7W9%HIN}lB3J@dVDKqF4GrM^9nu>3+s-?pZ)$dorbI@%9>6ov%vFzjhv##f#yra<~elm z)}6+86n4jQ>atMFSGF(2>ADqtGt8WjkCPueKR;ue;HM(2!(JFa;=_3;QP+w2^m@Sh zv%vbp>cD~x1Y+orz`lfEV89*Niyy!%z~?C(>%Hbcgj^6Iz(TW(2!0+%$@iNaTTctI z^0wYX2A z2CsNCCt#*~jkD*ISnuWS^1`PtttoM$fIAv~9suu}ATilN)#Z;SDKVoCAOY z3g0L3n=)2mp1^R6aoj=c=Yq~*&O$8L&`#df&R2t(4r(*$qlX7s!77V$u)?B>b3l~+ zIzNJaX)iFX_k{kFO`^wkvZP0wj`;~ZY;-DD`fAN)RK>I6c{$H^dCxv1$6yk9UM zsTLbCgyF%0>z_z}S_*%`4~ib<>LG4-0;VpG5FOdRF}WKIa6|=P)_e4b3gV z@#X{7v~{&{z>o<$IflJjgT@Il-GJhRT$B7~CUjmHut76{dw}H`%vzwOKRoZdg*R?$ zo-{IzH-tpFuIZh2Kk<^Z!3&b6A+CO0Lm3NMgMX!-9NO(YBxF+tCdW#<#eF8n&Y}IS z_fo_v{(~NrsKLpTN)7d!I7c+^zSdN&YOhDqZOJy#M_L zKZN(SuhJ%@*Pm-Fu-@Bi7l!u;3$U-Bolw#rJbGlU_eR3lcqYdT<9bjh$E5G&hoex~ z-~4IcrL$Xudlv=mB$PN8r08Sv4h#i&;9YTR7raLymP)Um-se1D-n|c4zSb_#aYFv} ze7vT=XzLCk&gBVOhiP)+Z*dbjfm(%L`*0HM@GLwCR`jnr&Qt@dgfL6#0(Lml2`~xg$7*n1W>Qq$^O$= zdbc#m`+iTN3)h#;k_{PoWgYotOF9l0;>w&_3Y@c_&kv_{pE&t5lo)6<$1^niyNc>+ zw^SYyg3M?MQWco0Pnc~5<+BFrB9-l2+oedE6RRo8si8C~jI#sh6KB z4qtKtg`bV@x)+~;IjuD#eg7`g&neaPgi=Os{fS3ch{6_V517%|m?Lw7mFLMKb>A5F+@2mPCFDw5ZX zsDz9?pl*aJ=9$GrfN^h^6wcO;$A_{3L|cY1F5C0gXut<>FlszaowhkJ#+qs|GDz$; z${aNy5gNUpyID*&jI*6EU6Z%5fA|BrwtH>tlb~*_(`%DD8#>|ok*j_{*{LIHa zR4X2f?4oe4%LPw02&&Thra(lv$xAsHS$D}6>*EYWM{Vm85snUgudBt6)pYg^G5bdJ zwxxqR2<8nPss%BcN()RP+d(-XNCp1v8SQEB8SJ^nf#rf_*+3R0T0~hvIQhPrmJt{W zeGa|P-0Mm_`LO}kVFTU-T?W<|ngr?=S~_qYCQ1KO!v`nW&i6e1?i(ZwUmEZa#7*E;&>El^1HaUuF2V?Y6hsn4 z6htF}HbPjlSI;IJ`JEZ9A(p}!Sau-DpF^X@Whja}O;wgRtRb)dJGOY5vn{-MrvC>b zI2XhjWjRB{K2>zh*A~4uEtsyHsxHKw%XlCM=*fI)2(QYQ`krs8r@-70tY<^tI5qd< zlcD^mHJ_pM=`4A7r2{n~qIro@OWIGZXs-tYf7WbFu#6s|oa}SH`z)bcA;pz`TBZfK z>tL*!9gRx7)KgqRw$CM7QBE#GhK^u~Y{?M%;j0FR>DHj!QB* zTedWe`!}{qCqqg;qH(3b$(#<0S)qwmd^59ze3h6qs3>1n87Nh4n~~^L+e(7Sqwr>Q z%K3d=r}-pbD@>0QyHkEqsNQ#|@p&}rXTqySugp%vA5*$>kkuUwe>>cdP~-z90CzI| z%+AoDr~|}w&Y+aG#fnnl%*LJ^8>;s8YDZlk4-xI^-&+Xio2SZ=ymXPUsU%W~YuJ;M ze~FBjSJ$Ffw*2WR4MhL+`>*-K_u5BMdL_8>Eu7Q#YL4EbFFQ0DT9eROqmkaJ*o`cV z-wm~9+bVuL>(;i6Mp7GSF>PUe1K3K?-IM}_j85zLbB`@V7r+5kIbH~t@`%Ek8Ul2r zF<2FD!0^Ai*ypUL&Y(c|v`^RhG?mK^xvjspJnl$K58bpvaLasSMi@0-gGTxo996wE zc3~MvwH}N${PlNd7_^tMvMp!stn%6%Ra>QZ{ZrH#0NGsu&9$m4)D%)p;K7H1ROKOl zBurDd>`FG}P4Ruro7gUc*rr~JRk=a6OZ~{G#u>)-HbL|GTeY7Ro*l+|tuAIu5@J|> z{-dH|yIAWsgG@0g!M)J{{-NT9OJ@_x06Dla%A zJZx^lGu(lGVwESx=I#}6k)F1!jZ~tawbIQ=yq|c?q8nUWX8U^B=wc-}TXGA>tVw8i zXwC2^>|uK~L3o%SPj1p4`d zMk|a6KYOithjI`;g~1n+ty65T;g?Eu_B!!@CPIp#i`bF=PPJAJoUMxYPO7+&(QS4m z91LP5V?^i>DZ7M{0fv8aUVGcb9@Oq8EPBlurcz0Ye_iEXU6O#=LcO;munfNke~K43 z=eXToqf|gO6WI&4PN@Zm?LORCPy*IiDSs{(^#mmd!e%MYxKU*#Hcg`)2pPLfW+(@O z3(ZArB?~t5Oa)(n+QekO7le6L#9QGph5@+O2<%r{?}?Ts0B@m8Lqzp!f18sUOGM1V zga`~HT#mjIi^H!R{_yTlwrANd$p(Z{v&j=+?@;^jGZ{W_b2A=_)`%RP73%hLO6 zy>qCtt?oP5@NhtIk&|Dr&Hg%YYHG@_AWRA^Zu)aRPN4^IaTE%cY>*3nMr;Mg05~1_M!HnS;m(<@8IP4UMcA?`B$Nn8f{7+ zLjp@p=~94L*-?bTwB+#MT0*&Cgw(i(M(&2DGy?d#H=lIK!5x3aeQLMiLDXM(g5;b$ zF*&BSc!iKZJUl3j6ErQzIc_}52GA=Xlkpk)p3T*@xX1}ofg6d}h&Xd|vf}4VL>GoD zJ{R$&;2pAT5~N6cMvW0%P9-`z_B@%J(6W`T=_G)lz@UsZ`z%JzdM!;;%1i`d>33Nq z>COZrW4X#>?_Bcx2@17|FgxIp;+c~Bd7(*((36Y%nrwp930Z7vnR*dMNi1WJ>**P_ zp5p+M|0j1ZV~c&zzqWLg^n$;MMI+ZmlGQVt`|K1carV7uoE{_C;r{hAvID+|saBe3 zn%2NATOY##F&iLnnWJzW8yOf>Gz0@*aHXV=^g;SzV{eCsft=yBSm@U}UFeu+>hD_-e z>5gG9Ry(>4=_7L}U*B|A&k|msy@wTUmQm+wf_(7p#fDy7JapoF=2V<%8azAaep=)W zGVGy(Ofm=Q*9cTN;k3~i&)VFSk$e%#Il!DO95r)Y)Sl`0Hsf2-$}lOCzbZv-HUM2g!WJ>cM*jy6I~ILaSm3d&F-oI6M%A z$rFqvd(M&?JuK;r3)-rG49YDwV-4Z{q#rCd)hcOwb-Fg>noItD!u0f_%ZK|alpi8o z!WT%CzjS!;1DV^a=DXoZIG-ctAv@5yB z%A>y<-_CHOfJt2loWzVd*FpV>dk&eWO+phKP*dsb{7>x+?|J+b_pr>@ofhz&EvX33 zZ#&@oQX%yshv#H_x1@cmzS}p+xxr1)B903 zMj%XMVR>TojJUslF#iCDs@2aF4>whdW~WCDDxx{zi7^dwBB;9x@dDTDCs}AeH0H7f z*T<+#$pRH#(J_M9O$*d;5X5OFyh-ZE*(|#zglQV z)z(FZ+yAQjmHkzrxgn#{Gu^E=zwXyfuDnl;;=&V!82q?aW zFNF)~GU|>szc%LL7U%l@>(OOM_*BZZLk|9S#M7-ELc(oSX$Ut(VOa3kp3u@qlsRI3 z_RW>)dyiY;bK76wyuW;5o;w{@2^Mc^h^h~8JIN}Q@cpLZw(&%Fn-#Zc%6XPgi0h23xZhCf2{vt{Nq>YIyqG@=d;pODqH-u;`kwjw^TT25z+_)KK`r>ri7vi0I< zXhsn8is+%W%DHHp1z%hA*1}C;&frXT>B|zsLR~$sMZ1an!H84KO4NvyMXJRt?ij19 z0f?`fX;c-8-ih}Jc_?-4JFl%j2r_cwW#M%Lr=7w?7x-J-b|IiODlM**)d{EXgl)n( zqMhs?SL+X;&MK(5)m5y3WSmsUs2yb-PhB!-I8+5C-4Oos2>r|vGDE#I%bYRsiB3s^ zSEqh?fO1&hWr?%daM*)6nlH$X2^GIw_(EubFZH>C>s4@hcpk~1FWqb;`S!S+yUNyi?fzxM9OzC;g)9i@k zt|i*d(~aL19K<}eH0RB^XN$(!{PeD9oD+c`U;=CaSOuDh28v~{jec|TDg+2o6Ye8_orv{1Z-Z6P|pOzWX+LqZg3nuou-cTSu zC(R$0L96vioQVD3Iit0TI*TeI+BVk=wdRJ_vc&d6T2$$Bre^;0lel~awqI@12XR^-M4;{>qku!P+i3K4~urG|HK?mdmk z@BR!%Pq8n_8-2)TPRi*Ugf+9cg7-bq8Vb9(bPb7y)$Xi{XD745QbXL407AxKw}@zy zs6}68$;$(teX10EMg7kchT(CS8f9qo1LAed$nK!%8Ip%7MT=unhwlOmG^vt=ahF6S zXjq|_RG5;q16B+vl9~eq1yyOzVVBeylHTC!fJ6nE5MH;0Elo09mFcqOWF=?_(ms3o__H6!jOQ5!|#-#CwkbtEL=Q{6ALp4y2vxl93%7vP$Em zVKFkslHnb?_$7co$ruVGXh=gFXqT4fi9IweS7Z(YQm0NrRB4{4H^+(39JQ!JAF>Il z_)uqEtl;ngLsf=0o)*i6G`;}I3u9;y>EUxcsNUQKW=Jl?_x=5+1i8cS;|wfzxS>@f z5JF+09?d$`6=leW00aM!#1c^>jUfq9B&*RKKC;gt9Upd}LptEibHs(oj*y0f<_~y~ zKrlOIAxto8ywWtIffX7u$njbsb_iGYA%dtox#IpGcN9Z9l=uT%+413BYQ>TAwheRR zDvSTAtTwk~hJ{->h%n zgoN?cC;gr1V9TevT+g-rCwzTIe{N0F0De@&lwnTHJy`x7xP zZSkY1-qEVe3yRu$>?|7PO>e`jK>QEhXf1jc zjqC=#P}uNy24#Z>m#{cw6+=bd62U7ZT57QKx}r&Ea9~_NSJOjBo$asMC0wi^SmQ#V z)*x0q2F%XHJx4JoRju!+ZwYN(@=0(ULITO9|<*MYGRwo-Zimt zynEug4+64&@qO(9Pm=)iINTo7yEZ)j_CfUw`}9J>=yBlZ7yM>}KWY^;~o0Q$~97 zK`|bA?X8r+oR&lS;gJd1o`eUNQUO@=eP3>?zrtfbCRh4}E2d74>n`#T{sjmu-q|sW z83ibMsjDXmfWV2Gwj&E%vr2P2T=^~Bid@5XW2$nBG!SxnYLN4v(sILJOhn&jX4A$7 zDgc2q6fKXA#eoU|fy7y24nz5}2C8GT*9f~DQBen|`Sma>(Wjx#$--y~4C`pRl=g$?@rtPQLu1z_@= z$S^9u*mZp&9U%Te=)CqzJkv~Y{JPVQBO17?i|BZp1aA=mAq?}MCkvo~A1X=OVp%G= z$_(a2@hRFPwzIpUEQVA`UqwT)>oA5^%FSIU<3pl$n;bCX)g$MLMd#nELU)>MH`YGz z)RfA7`w2`3$|QiC%BE6S4O zN3%p!Uu9@tG%}UGJoQV!k;)J!S;!4L z2+bTMJ`eNYEL4WOGV#PQnYIJ-Y>-lDSL6MjDhbZNC37yS6jWh^o}p$g4P1>T+2$C( z{ed9!`*t$>dZi4p-Q$yI++4FLXBrnr4A{2}(vcr|-f~Qnj1HTVL~$gt2{lFeL^n`a z>rPxOK4J;pHc?)VK=E;B+^xlM{2@2HW-@n8wMi_H}vZ0T|Hhks&!e18DCn;c-5iM9k^lWbX-1X z*XZQ^F02vA{>nsUo=PqU&Qe9w(px(CnW!7C$4fQXo`sB+K>hbQ5JEqDw}y2j;9Qpl zyw@ZKn95Dv@+Rf#$aZy2&q=>ScJHm!kY4%Xg8%~ciwW}*{(8)(j>+v$YJ2Jz%Gh@k z{8%{&x5|8XXe6raZ$wJHBAxX2CDTVazmG^=5X6*`UJo~4bu06*<38UiYrZr36$FH; zT}$dbj2FN=l zNH%bF#i}%)$p*DYcl1TajRs}(d95n|NXHjD_aLye?QZ=oly18c4J*_`?R$hilU?Gl zk7%~`J3vS}#b`n%JMVu`pNgVZqz?O%>HD$kLhsb!fB;TdzH{wq)SU!W&Pl~0WqHPEKlAZ1x_*!DTGsYw6!NFQCP z8oa#lWlGNUG-@Dh@jhyZ#Zj(JikG#m{$ycpwIH#gJfpGa*z$0>vY&95z;=&*XMrWb z*x6Q$1f}SSL}sl_89w8VB;M7EKmMzLDhLR80K6#D9ikg@JgkFC3j!m5!@W|0+1VX64?D?5>awy^Rx^1Vj5mdTSl++sfjt1 zxH<_oL{>?%Ux%?Hv=HIW-f1EwL@VCN@n`{prj(4WWI7X-mYPa1p2GA*Gjr;G@ymtt z8~q`$i940)HB(o=NNes{Gwa?aq4bFlg}Jg@rCL_Oh`Yq-f2qGlzMDA1dREU00)RjC z_xt|1kO>-Kc8fI0nrprO4y}<~&&{|6xP9L&9qV}}XH3NI7kD~EJ#c&Myo|yFuiPU! z%T@2Zg|Z&$Cbr!IG%v90UQ(1DI6Fahb1LHpt#+;`Zzyq8691@GD2!QpE-(Kg*tT%_ zK`oB_rc|brmH8$v;nBH}MEnTArM&60DMj1%F-Y)cRGW}KdU>Zd|D!n6JScAh8)hfA z{-a>kNXJDza7&8(;Y-iI9=XZ9G|Rl0>m8LOJYxR0qe#qu=NEsZ(sS{nIhhx(LVs@N znpcC4Z5PR}hejss?$2|o^cLV5`&hPcIQbZMr?tHRmh`06+gZcLmDc?M!R{J94g z{R&PNTnJZgZCkU&k0Q)n<9`aWw($?w-+D)PB+8i&No~zpB~{0ZeB{0pW_)rYjaR%{Z_=d)@Jd{8QLptMVCd9vBFD>-nm?9~T^HVrAXwyta?}g{d); zuwbv>0j%SNcFhH2T=h>LK?Jpyx_2KBJ3+4^`1VHSe@lh^mfWu1!k+QRK!?!rJm<~; zI7-pI^2TpX>y$pS!FY=|`)CJ`ma8``wC6_Utyhxc6MecJpFLRCGPq@6WxjyWIvB3_ zTuu^0?|G7s@ zx%u+MH``4r{_;e?S@nbx!@@tUCK5Ue=qGr?s{t^jVef_vnq45fF)iP>T92E3$ACz{ zYXVqq6*siVBSAL)Ncile;gmw8!hn7yO8aVd-)c|JL`)>z6a?1HR8M$1R%+I4gl zuaXaHX67xGQ1xeAH)5z%+gOGmLPL;{AxIc!`F@m2*SV7XJ1!^0ju7GjZ=C;}<;AG* z-Fx17n&RrwE6V!`sEIh*FO}tp9-UL(bTzz3zumb0hvj!zz6<*9Md~tsjB4+G@a`>P zmjqn@brH+>kul$(8x=^sLzhJA=%-C-_27$un(@!seaf4pcdGBWL8cS66qn*==AG(& zr-*^muV0=ztTD%oENRaz3Og5Ivdo{5w(n=JAP|zmHhNcihgkG{HL6)Z>2mm zO;tr%`eh>D9231sOLjPmh~n zg)HWuYNZJ0^*d-zoujC7KuWqeh6MSm+i$-UL_hEOLf_g{IBJeSJ53iW)h@hdl{$)? zs$;|(!aydK@uRWkfeUvsw@7d^WcT^oxdX9A$D?(Z=QmutF`mwB4ZGL?Fw|X{5(%Py zt5mt_^Yf@L8%*AgJ(+a!eJ0m7<<$!iCpyk&PN*E%SUkp1vv-9=7M5J^z(7WLI7+2M z=1!Nt^Zxx2qv>HAnhe-l*H$|auV3}*N1&%mX5vq{Z#hVEvCw?|+Y;;bqgB>lDvf`} zXwxGWAn!W;=;XqhcH3s9D5BnzFbUGYiZqH#q!vw2Y2d+$6w;%gLgwnCg{L+ILbR&a zH0f?(oxh(j_ogRCo(FyUhZ~e=6-cBqi}soD>oKnAI3ssA0~RA+^0PMiDxc~i3a*~K z_^W4aA1yUx&~|TgE@*(^lS8d`AefDW-7lklQ6MUGn~>F;v)&(iDevz-cYaYr=N;(i z&)(tXH%Gb|LeY7v`YYH|srYMDz(|or(^2#^ip1*T39zy5p zv)zc?gIJYefi+&#)FO0sj}O)fiwJ3n9swtNHdc&^pzolN-csWzS8@D5GaD9%CGW`PVZ$F-Os) z9N%a;l+baNM5W`AW-(Ls51&9_Y?-95Fr16{rIcyyN&!A~URuXeMk%4+3XUFz4j~+I z=8}}nb4BR4+V#2wwQb@J;6)DQrT^O?w;V3j%n^rSpNXy zTcJjW0n^@3C4Lgf)P1Cr5?)jn$*>41mcIVYM3hZ>FnAHey)&_>9B;_$tDhd?Dzn_| zND=incLiC@c-RqLax#2DghQXDr57lpU%39u!clns<-w2A(L5v{fW(62;F17Nx*gI0 zqWPV40jNT~TCe)xwQ|-WNBPApa;8&K=tGsqpju3>uBeaHyO>LJ_AWR+-OswznMgH! zdDhHnGC3e@^HWLZ%HYILm^RsRFSrzON?6MFDpxC#m*$+*tT4JI4Q7M1ky$jEuTf-p-78DrtV3`U3xf%amSRx6p z%jq3&VtFn3^-E?$>y{DgWQR5(R`t(-qam7fTW)1|zwc|TXnE_lKqpdV2qpAtH6d|5 z+iT^U_X`1}>+UL2CYPBgO5?!0gcYYFC3r9DFL&r6)yViq;XEZWMzc)xxW_FOz(5}m z{5KEI8qf#cC)zW1m$bt1F!u1!M6dm^G8E@ zlB2ffsM2Dc1#+;*4ZGiA*>Z~Zaa46z@$2#Aa05I=;H?QKPWa^W{6GHTK3)IrDi=&W za8ZyrH%2!NdOHhx1Uxy+&i;{TMeL5hgtm`Bp#riyAkO_`ASfQ2@vXVe%-(?z?g-7W zSTSSFPtk6FoWmxOQR$qLQhu>`st+OY^m<|a>uKHclp? z`zniefHS({ew3DYVBKUf`lDRVW^O6mUW;2@E@6wXq4dV76#`4fneyE;0nEkoCHG&H z_pGL!3m;)ja$g9 zV)n$+9hTDhGUf4=STdTi5keaEmvjp?v4pvZX>1OtZyK{EsJGmjs6rD(7}soX9qAHT zuwDpZ9gN-0CIyH=V?I);qu1XB>5JJ0wu1RhL_#Vc49xy2UYjKp=?h8@ZG|i;U$K_} zPDA%lmWc|$sA45>W)%C4=bkLn+3)0DXV{vD@OgzN)S3ny;*e@*Sh zcq_jVS9qO5)l@aJDU;{EEd2JJjI0(Dwu)H5qj+)sNg&DY*BwAXUdC;9LQtoC{^Lt z{=_Fq(2GdpXhTqqoKc=Xc(bR@C z*uGh|(3x>H#>P2X^5KW9c9;CXo-uCR1P3Ke2jWfhd-VATD-HRo(xv!de8O3VCvBed z^B}#(#^ApRiOLS9)^av+hIqt6255iLn;6!+)vGy5$gui7{*Xw`Ib-}DPYqONhdkD# z&=Bo5S{=PHjuwFE`Sxn=f-gY=5XXxNHXKzkiIsc9@Y#y#B2p`GvR6RrK0X>9l{7g^ z)!A8gs_{oIl;=gkQof z<1S7BPI~x*WPi1YaYHto^G9lB7);$8&UpUU*p)^@xyRvm47bMELe?2ewvc^ST1Xj$ zdqrevFqUDAeHp5$Mi_eyC3Ng#-?|AYk+>?2T!oNB$Q)Z5j6K(wZl^jr_rC9k_xFBz zmf!RB|3A<9FR@TCm7mZi8Fi8a%ZuT}mppi3hWoItEo*d;=Wuw*H8&WKJTHpUQjqxw zq4rU`x4^2PF#kNdCG;jmUdh0QZhNi>7Jr;OWaR!<`($4jpbbfw)?F)LncP|$$?$e) zB8ks0Kv@%EC*(3T(rbqzq+_x|C0L}og`AXLmpIxU+uJ<1%26)*3KJVg#}~!yYrCo?sIMo4Oq{C-f$Q~t$vPmr>jagl z$Cp@inrf1#eNI;`F8V)tWyASJDbe6gSP!lyCWRHm`#~kOJ8)r2pCD&AtwwVrZ!W|n zaDPsSQStC>)$bH&e3_xH>{Ua;_fFDhU19rz&AW7=`F)sI-BLvwSjCIb{-spi`uroXXzrYaF!Bijdq6A5)XI@wrN5l5~gBm50|y`xlN$-w4Mq9$j~W>@044yaQ^ z8&#o^-U3dxm}37oP?d-_$yA4E&TE~RlF4Na`av4+ZAd)Hc%W5?BCm$`hi{TF=*qrFG)sarFi66Z|I_(O=+0nR9(>@J0Itf_G8aS2@TCN0-hS< zv1!nvo`!U^3*Gt&0?%XNyx9ZoxC{%p!!wDisLQHc6D>`5@^fgJ>E?{+P8K^Eh@l=iXR$5`s{t4qotpya%rp5TWm8XfO`aVU)p^!+- z0<9YbP|wMl_ckIG-wM7B%^_m$TcS|)mh~X$F-NP>u7*Gq{;qe<1=W1pJ#@ET6NI=k zMP}AcX5AZoe(s*n{N+J%bQEzdW4P}?JXK3(vp>e5R8O$}R#;horJ<$g;8?(>d)Y(% zxQ*F3IS1F&Vy9W;(ZEQEqWEm`9TX+r$c|5fTOjG>+&j4*_JoowS`;<7DMfVUu-^;Q zA$x~VewSG~UTkkmC^qy$g&nu?@ABs9<#rXNP_r?bN13Ev$*Kv=!`L>?I#CW)CN`|!k z-FQteBJsV{@F$}rkE)i&{C=~ga5eIos~Rf@R}8zuW%sl5vL0&Qj5g)>4eGe|S5VJHr`WUC4Rs+A z+>!x!`xeYnD}rX_6BQld6;rLQ&|O`6u`C}4@097t9u8h^_c5TW((R};HKK6pB|gez z5}$@#*5(SmDE@knd|FE)j{PR-q)$#n*@JPf=cj0@Hrto53?nlr1D9pqShiJ+&-kP( zwrg(fu`&a(h=JJw#&hIYgYC`$crZT@K!`a2JizP;#^{R1x&)%#87=Q@0C;=_iwX&c z0wC5U5CH5nyMK?T{8MYZ;16&{0B|E$NNfkFesxzMe((*Xh%r+FLqY2H80a447ZT{U zErChJtdnO@Ns(=yy@LV3{96D}`bGr+1y>(2sFa0%MMaXAQUGtj0n#XZ|90v9ZVO>* z5cr15Q1i!u@AeVSY^=wiu_59Au^gsi#aK4(rhcP@~EloK3TS-E$NE}V`pBE+; zBqUi<)&#|RCjGW4RSX@6Pf|15B&Y(}{EXn+it5LV(&k+~Bdgdi)mz_KirG`I$?`i{ z$q8+=W_C;KjV`A$Gdlv$PH`k>ZzZ0%F@dwGyi8uZsk^DnHs0;YRdIyS#V*%7zTc6F zCaqHuPEBcvID=A&9MMj-(fBb%v+YgE*4m1>(@Ca^xC*^sk;GRji;GS+4$~0A+SKED zR%1^gc-Y2sMCg6<+L(5B+~VlbaclRAb#Uq8wgy?o=9wuQ_t>p74_BB3(7S*06Tm5$ z9=wifQa1Zm^&(h$n#xrpe&D41y5iutGrL59EWbuZ{Z}oXws_j_)J7^V680uu7g`RB zJqPmqNzTDpspCa|n^lp5?f|9N#e+CdPQ}Iv`RlKf=C|yXHr+c`e3Kkg%<}cRGG8B! zpBb>26wO^sc7H#TdTd&fhs7-wi~wZrf#S&NlA0!s-}|~y#%ba2Flx*(iR|3XT2L){ z(m#9=$!^Dbk9)Xg5E_I06>t6Rr{q6yRt8j^xwnx0kL_Pu8ol844>0E(@SimmVqHni zZj1Ymqr6PPD3e+5?sF|GGBd@a@FhISh(_HlpzeCO3wgv>58uNk{C+RqqSgSzTf$2C zp*1@JTOH3F!anls|8SEIN5gu>pqTjje{0xj=rx}|H17?_8~eHBvs0@6qH}uK%AaCj za29{DP5=cRzyQBuxVzHT{e@rbb-`0NUD>B_0p@28KEHEzp~+<~o`NADGy*7d-Bd#I z0eJOZO{?sOqqvZC5y0f=bjrgK*w$<)=_Br9BAEtWPrGC;tN&y3*-gTkr-h-nco0o3 z_L{)BwPKN&V?A*E{bVSN9WV?=PE2lu6;pvu1m6NO&^}{*3){Rp#qOrLEdY#paJVZstWj zu%lv2f=_0XvVzlzJlO@{_eF-MkG%H0x8w<*uCbB&BTuvD;3qPGBs#FY;dT~#yOnTa zdmCpC0+a^|n*7;GyPoLQkf9U~Pq<5FtwU(vs(170NS10H99ZTH4E;Gd^9Fwj*~OE) zz7b?%h{bFyVKgGHC$GbM&9?Omy{rLF)pUN+;O_rIRVkE(ghy!WoIjr)wQTEHsrOEa zx9k#671K2x3Y3DQ~cea&-m(9%-4VPu3{M3#t#WK?a@f=*XAe=qPji!*$Zr5=C$Hi@j| zD+Q*frXYql4j=hes`(8}2J>SCfWhVc>hjD@b!d)}Pzm*CTxw1OIR2jZ{-=H`W^#xo zfHL2|Affnx06H0<4m@@aIG%cSG%20( z0^do$p~W?3>$Zcbyv0@JTAx2n%xbF(uu;2S@U7b@oVMxWXZdYxRlH_29pG->fVqyc zIb`>zPyblro^io3IChf5rBVM~VA}a8)`tl+DnHM*m6Q&?pXT%s3Im=+g$R=L23oQ9 zHbQc74NHBe#$pymd$cY|i&40Xk$l&u&msEu(nlkzM+S4&)qD0k$mpy3u9nEDz#}@& z8%p_-f-|iJbYET~{<$)rgA;H{!Xb`uWoUjEPH99#^M$yLi=LK>UnwIznX$9z#Yz;Z zQ#Lq9FINnQb_LZU0o9|-IlfHtJ?l@L{xP*9ekvOOuk_rk+m0a~ zX2`8Hsr`4|tFugb_x>pcHxl8v6#cEy441-2QdBSNITd<1gjj zBokESKN*VdK8%7uZ2FmjA#se*@=UMkV8ipp?!t_~?xDDcHQh{)XTGB>10R)bf{pseXg|@`*?>NRQV-U7K%H# ztM%0;19PNSG-u{jgG7ZnsJ3}lW6dI(MNzV?I-CiQt#oWU+x{XJUoB)#J*8CC{^A`o zgUx2Mc9t`jv}NoLz6dZ$aO8d)C1f3)FA*xYiFq?y%r1{EILOjcnC+2~^L(?5bjzAb z&Q}H{c4_H_?u>06I8~-~`C|vfC@5@&4g;O83t6SE=MkQVq3j^DN$xDc zCVSK`obGs!>CH#+{ugmvsD;v+pH|a&=LUm5e}(Qqtl~7!f%Q2pshtpav0~%(>g-f# zjPLXL?xzacq3tg$Kd-QKcKj$GV#ulGAfbOMcl;o_0|UKZ$ql1M5YW_(%?wpAW{qy& zc9irswN~xV?z8=~Bk>a?$TaDFp4l`hY*2%H0UgOhd`YxZSp7`k7K$T1~ z^Z-V;=H~O!Q^3FTAoCQ<;KgBp^N63L-=d!|H7sA#7<59dflb3Zer~uP@AgSAY6t84 z9hUxaG(l;EHP>0iY>ddo!|CeQc<_bz?9l`gO48OO^%Ht8WS@s&ezFWdptKLS2W-A@ zA>&xR5|T!P<{Z(cd9B)9tuQNJQONVAI`7$2%!l)TKoPbsxEp`Ji!UP|?$r9+1nk+F zR=KH1%yG76bF!7;%?(K?<~shCAy@8A*;w|f@y+dT#t%Ldq(?_CRy!F)!O8u9XcNeg zz&NumNf&P{Thc!)vMjQ^9UfqOz6;=}B7C{AoR~u|#A)bro-1iKk@X%GkN9k$grmc4 zam`4wlRMtHn#Op}dZ>u5sjSsP4sTByZroP_NL>Nd%>@~cSpM30Mvqt)kJvDf_$$|K z&e9N5|2E1N0tM~Xc}6RCjK8nwXtnOZo%UN6`>!b8v^oc2k(*bQ^g^>Y?!b$HV*l2d zZ!=y8>$6&1`K$MgR-NL)2T*|<9>5fx_v1zI?N1z z?BzV9cwm%gl4MUlxJ&B}>Dr>D=B%*vQFxc$-Wm6Ki}54Uj^lT`i4xtuSeg=Csb4?F zo~g9Z?w(VE9o`Y2?u+!eQUjfcbS?y^)-6J79HE?vs5Z)7T8%tD=!~pBkojj= zmXL%e4lARz?oaxX0bB#-moxXGw|+NfitN{>Z(xf-n&NroN07FxV?~ou^($Ou3g?dk zCciBoMB>*w6ts-b$QWTQTM=Ft>Bp}j>(~;Cm%fLK4sch>v4tLbqT_Yg{Pu6+A3l{F zA((zh8ifrpipZ3ngSE>pcaUH>b5Uv?zT>RSnfvT zz;{I;^!7FnPkewCqM@hm?E=p(!Sizdt_>g6o)8h=iWi>a76c5!*M)iH9|wDC`?E8^zyYJ9r{`GA5doV{Dbl=Ae;(zL#qiveGRkEvSZJG9;Es@tWUf;&f8}?6 zQ1F7o56} z%}Jt(>PtNO;4;@8cZnV#(7S&hhDVZTwRAC+f=fdD=WlZ!8m{)>C+~r~kG%;F-rT^t z|Me!IHTJ23PU5A`#MH>$fbQnT=GD2YS)iZa1)1TID*Gb`UO+@QS$=|LY_;o);qy`A z>=dA(YmB#W2eF)#%A}E~P1W{(6T8Q}R@5Y{5CnRy5FX4GZ>p;(ZT4NpSl!)N{g>@# zW8M8;wtaf;>wB76%$p_K;P+BPvEF=K4`o%NU-|_m)s1gAylz$JJeE17uC7sJnewU! zZZtHD)F}gsX=oBM!MWwaLU9{KT=v?Y;z>Y|#J$|T(5V1np8^N8t(2=ER3kwyybCBO zp)wrLYmCbHnR>pTw+nSllyr;Nh^@~856p<*3l`@}j_*j@74x|!t1#K|uB|6Kv%c08 z#gGkbmz-@JUO~P2#Y^+k*vp?{IPQ`SeBU)zy5{%TD|LO>SSiLq6!4l0wnY%~Wglpp z(tCnT$J(rkBA4#XHr3b3o(T9+^^LHW8bS@r&lPcb*4L6m9Q&DVD|{|D44!}~7l(R4 zB+%WxVyTJGDkxlSz1YO@*{sg;6?YkFPx;F`)hs>M{T7Ft@+F(1^*N?hx&%EuOR!93 zZ$*rxDZ`|v=-f%7B%YtoBUq}s2lzrJ(6Kv$$N||rX$*6K?^xy#T^slkCdRk=%~vKT zFJ!B{S$jyNGT+Cb)H0$^m7-kq2$H5Xf@WLNs+)Ay=`#^(XQCMkdPsTQZIFT?S!28phe+vHxY%qtj45~z%h=ko!BUd zpOBh=00M7jQ3%)b=9O*i;0USP0!zHg(f(t+>6b?%>XAIjXG^efpA53<)dF!=jtwHlnBw(Pb zQ;^!J-8(lEI=$Mf9q+%b!pyw7)bmr!XFx&FWx4yOSkW(8+Z5qqh_S)nj0*dOiCvDN zj&+VPmHWJZuxmQat!RYYuvmZNf{9(H<2OWwm}k*j{7`avjk>}+?qY|qG}v+C`b-Ay7@D*h&-$+=tY`LOzy+yqjG z(UxnkD}zdo{Ck(9r>A`?RRO*xUz9=-8#nQ5^h+-2Q8Vz~djF0|o3$c*Ma&_KGxrH|PgPrm2~KfR$S z?1@`5Dym)5!K5IA1CwtCyyV)we85prJ9G+wt^!jS@$8|LnoROSjL`xJ0SQ zqkiJ>dLD@@1eVLkHdRIvUe=C`eqzUigu|~d*cLDJF>X|vNEFNpVuQ9hKK_h$#Pd;+ znHfSEK7e8Xy|B>6JYi=sE14mAQBpvFiIFi@k5W=+m(G>(3kH`_Rwo}?JVADx4uXm) z<#<$f?y7_V^t1r8aX!*6zFl7H(!YP$y$ZNj*NKh{QB+?ddIuL6# z`d92a;A(jJi^P?RFsy&2` z4e0jqbVUv5w#%x01mAcah0k}BLyUIaF51MyjP%Feug+|Ezf!24-la>BpW+4&_Ay|U zL4_%@?TrYm9U>-VbZ$W+o3HPTW+{*xJx%h+5tFA<;$wY+Dv439co~~m8_Qznj7&H? zoKd>uy7-t7~4ldqiC>zZ`dC_X1bU`%V9ZIpjAnoi`Lh@ z%6&iBoTEb?2_2(D64c~qzBg}Xr#3)sNOpd+1!2p7rw7^9`d}*B30Pzo5S7QzxMyYd zOzAt^tCgh{utx#7mf+&Eheonib&^BOOm(J+3T)fOm4vhPIwZ51m{UED25HflracIw z#=hZ-1WB-ihId32{F3rZZ;(d(^5@_q=3~$Oq-K)?n+9=T+B?vP*zmCL1*#?aa7{br z>7xqGVuhB-Dhk|5HwCT&gJ7r8d&=6DKD`rK&~6p77Xo;TxdLRhBPdVG?6jJ?mlX0K zeFpuBi(Z}7YicXfWiR8k<3NS`7tQMsXiAD^o>25|z0kZ$PmF}rd#qxb9Ra^e)SdJ; z&6zNC-tQ?1D^9k_>(c5EMNLb#lst@!i7suLw@k#R)9j3xUZxTU>YkKnfi0So8k=?_ z+f73<5P+_fLY_@HS#;V!O`5TKKngCy>PIQpNxF^mBnS3NUAt3ysI%C9p6;f_ei$x- z^>u0re@TL^%lz~Q`{vnUeQTCQL5G;S;Irm~-m>kcRoDSD6;9!RC$HdPvaJOARw2Ei z;aLq%V*b%VrJbUn;~l;C`J#{zQmVnn&~aL-0^s6v&DR{Xut7J6e0bi?7AH&OSs@dD zqr_rcP>A!n)~AHE2hCPk$X@yCDyegUhq?e>>0F#QxRKiYOa}Kwi|DZ_e;?ZPs@94>D`ty0_OTV)2 zWFV$+DI(RZ)CJD@>~Jr!^l~p5^MbvGs88f+i|s=DN$f&d0s{cLb93JGmPg4xKXkvv zf|%sGDMGur^M_%)cZazTVyeHW9_n+^a`#>l=4a4_c3e6j(V+b}P!S7-?aR1P#^g+K zED->k$nf_Pgc2r5Q6S>4$&=`8p)JIrz+R8mWbG`+vJ(BamA^H-`863CAO{7pK=McB z%+x*yy`U?U`JB) zOnkA8X^5lB!c~hJv*ycID`=o<#fLjN@{r@$M%4G)qlBLkF*WP=!mtnd|Cq`tqUW4# zoW0E&yqj?xHWqe!#`PpHCFpUtEWAE8ah5vn|2V=Bj7^4M+n>xiOS*NS> z+QDOU1gk#4JCcKQ5IL7bosY4Ne!*sD{r>$Y`SehtICF^qfLfe6?R>3u5W#*r=La}U zn8s-Q_Cd(a1accAM6-P(#yF41^Thf0*f&(0LE)GCHkbD~oO^%w1IXO=JCk5`^!sD1 z!|MZg`1>?puh^~NwL<1vL$`K9>mPZy5rcO(ZoJ(wmrSA~`IlO*8j}0z(^j2k6L)uU zoLfO#^23~o;}flqf5StYvM#yT%qjlf#2vHH`tb)iP4UIDaCdSy#&8d9YOOUKxxDi; zbcEsI)^Bur)6X3M;&N&?PSV}iOeSxC=Ll9?z}0dDTS?D0g1)6aOxziYZ=WR}iIT1N z`+H(;i!uZXAt?6)g%MvErcWe$?{4IWY4(FKIhor`@|KJCgWRaLN8BZjY~i|76i%do z`2Mm#z`oJ>`M7oy?zy&JDYQPeyQs7)F}$9x0y7|Yr2_68$a@&$0q*$ql;NJF;WL%( zb&YLMF_d}k7WfVo9{3vcfgCh|R*IX$;jXyJ7bb&MDw(t8zBEwy>9SLX$=n;)J27rB zX=O;*okXxVIxY>TiKQrtI5n8y?fLh}s@AZvm83W0voOu_{-38Tsih66N<>V)I&3Pz z%Y)+<#{gfVsV1N1+g2>SfLP%%9D>O(D#tx}CDzOV{b;2$PW%*jmXxv&N6kg@3)4T0 z!n;`--BDyx40;9KIw{I?Fm&ziStm#@Is;oTp;*-r1GOc_f<2Eq6LyYvgYMMKbxD(i z>a<1;aY=X-s#{btU68^@`LM8@^l`lw#bnJrbwHoBemg*5l{PDL6DQEXF1cF!n_)?0 zz4B+PRFu)VrS?d-{5PDUs#?zZv)HNGoM59+d Date: Thu, 25 May 2023 13:09:39 +0200 Subject: [PATCH 07/54] added refernce fmus for fmi3 --- .../maestro/Fmi3ModuleReferenceFmusTest.java | 92 +++++++++++++++++++ .../org/intocps/maestro/Fmi3ModuleTest.java | 2 +- .../fmi3/reference/bounchingball/fmi3_bb.mabl | 40 ++++++++ 3 files changed, 133 insertions(+), 1 deletion(-) create mode 100644 maestro/src/test/java/org/intocps/maestro/Fmi3ModuleReferenceFmusTest.java create mode 100644 maestro/src/test/resources/fmi3/reference/bounchingball/fmi3_bb.mabl diff --git a/maestro/src/test/java/org/intocps/maestro/Fmi3ModuleReferenceFmusTest.java b/maestro/src/test/java/org/intocps/maestro/Fmi3ModuleReferenceFmusTest.java new file mode 100644 index 000000000..b388ef390 --- /dev/null +++ b/maestro/src/test/java/org/intocps/maestro/Fmi3ModuleReferenceFmusTest.java @@ -0,0 +1,92 @@ +package org.intocps.maestro; + +import org.apache.commons.io.FileUtils; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.provider.Arguments; + +import java.io.*; +import java.net.URL; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +public class Fmi3ModuleReferenceFmusTest extends FullSpecTest { + + private static Stream data() { + return Arrays.stream(Objects.requireNonNull(Paths.get("src", "test", "resources", "fmi3","reference").toFile().listFiles())) + .filter(n -> !n.getName().startsWith(".")).map(f -> Arguments.arguments(f.getName(), f)); + } + + protected List getSpecificationFiles(File specFolder) { + + List specFiles = Arrays.stream(Objects.requireNonNull(specFolder.listFiles((file, s) -> s.toLowerCase().endsWith(".mabl")))) + .collect(Collectors.toList()); + + //lets make sure we have replaced any relative URIs for fmu loading + for (File f : specFiles) { + Path path = f.toPath(); + Charset charset = StandardCharsets.UTF_8; + + String content = null; + try { + content = Files.readString(path, charset); + content = content.replace("file:", destination.toAbsolutePath().toUri().toString()); + Files.write(path, content.getBytes(charset)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + + return specFiles; + } +final static Path destination = Paths.get("target", Fmi3ModuleReferenceFmusTest.class.getSimpleName(), "cache"); + @BeforeAll + public static void downloadReferenceFmus() throws IOException { + + final String referenceFmuBundle = "https://github.com/modelica/Reference-FMUs/releases/download/v0.0.23/Reference-FMUs-0.0.23.zip"; + Path referenceFmuZipPath = destination.resolve( "Reference-FMUs.zip"); + if (referenceFmuZipPath.toFile().exists()) { + return; + } + + referenceFmuZipPath.toFile().getParentFile().mkdirs(); + + FileUtils.copyURLToFile(new URL(referenceFmuBundle), referenceFmuZipPath.toFile()); + +// Path destination = referenceFmuZipPath.getParent(); + + ZipInputStream zipIn = new ZipInputStream(new FileInputStream(referenceFmuZipPath.toFile())); + ZipEntry entry = zipIn.getNextEntry(); + while (entry != null) { + if (entry.getName().startsWith("3.0") && entry.getName().endsWith(".fmu")) { + extractFile(zipIn, destination.resolve(Paths.get(entry.getName()).getFileName().toString())); + } + zipIn.closeEntry(); + entry = zipIn.getNextEntry(); + } + zipIn.close(); + } + + private static final int BUFFER_SIZE = 4096; + + static private void extractFile(ZipInputStream zipIn, Path filePath) throws IOException { + BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath.toFile())); + byte[] bytesIn = new byte[BUFFER_SIZE]; + int read = 0; + while ((read = zipIn.read(bytesIn)) != -1) { + bos.write(bytesIn, 0, read); + } + bos.close(); + } + +} diff --git a/maestro/src/test/java/org/intocps/maestro/Fmi3ModuleTest.java b/maestro/src/test/java/org/intocps/maestro/Fmi3ModuleTest.java index 060125014..6f04b61ad 100644 --- a/maestro/src/test/java/org/intocps/maestro/Fmi3ModuleTest.java +++ b/maestro/src/test/java/org/intocps/maestro/Fmi3ModuleTest.java @@ -18,7 +18,7 @@ public class Fmi3ModuleTest extends FullSpecTest { private static Stream data() { - return Arrays.stream(Objects.requireNonNull(Paths.get("src", "test", "resources", "fmi3").toFile().listFiles())) + return Arrays.stream(Objects.requireNonNull(Paths.get("src", "test", "resources", "fmi3","basic").toFile().listFiles())) .filter(n -> !n.getName().startsWith(".")).map(f -> Arguments.arguments(f.getName(), f)); } diff --git a/maestro/src/test/resources/fmi3/reference/bounchingball/fmi3_bb.mabl b/maestro/src/test/resources/fmi3/reference/bounchingball/fmi3_bb.mabl new file mode 100644 index 000000000..774b95044 --- /dev/null +++ b/maestro/src/test/resources/fmi3/reference/bounchingball/fmi3_bb.mabl @@ -0,0 +1,40 @@ +simulation +import FMI3; +{ + FMI3 x1 =null; + try + { + x1 = load("FMI3", "{1AE5E10D-9521-4DE3-80B9-D0EAAA7D5AF1}", "file:BouncingBall.fmu"); + if (x1 == null) + { + error; + } + + string instanceName="fmi3functiontest"; + + bool visible=true; + bool loggingOn=true; + bool eventModeUsed=true; + bool earlyReturnAllowed=true; + uint requiredIntermediateVariables[2]={1,2}; + + FMI3Instance instance = x1.instantiateCoSimulation( instanceName, visible, loggingOn, eventModeUsed, earlyReturnAllowed, requiredIntermediateVariables); + if (instance == null) + { + error "instance not created"; + } + uint sv[3]={0,1,2}; + int i1 = 1; + float f1 = 1; + byte b1 = 2; + byte valu8[3]={100,0,0}; + instance.setUInt8(sv,valu8); + + x1.freeInstance(instance); + + } + finally + { + unload(x1); + } +} \ No newline at end of file From 020439146f8b277337e452b33ea12404684647c2 Mon Sep 17 00:00:00 2001 From: Kenneth Lausdahl Date: Thu, 25 May 2023 13:19:51 +0200 Subject: [PATCH 08/54] fixed path issues on windows --- .../{ => fmi3}/Fmi3ModuleReferenceFmusTest.java | 7 +++++-- .../intocps/maestro/{ => fmi3}/Fmi3ModuleTest.java | 13 ++++++++++--- .../fmi3/basic/{ => basic1}/fmi3_basic.mabl | 2 +- 3 files changed, 16 insertions(+), 6 deletions(-) rename maestro/src/test/java/org/intocps/maestro/{ => fmi3}/Fmi3ModuleReferenceFmusTest.java (92%) rename maestro/src/test/java/org/intocps/maestro/{ => fmi3}/Fmi3ModuleTest.java (68%) rename maestro/src/test/resources/fmi3/basic/{ => basic1}/fmi3_basic.mabl (88%) diff --git a/maestro/src/test/java/org/intocps/maestro/Fmi3ModuleReferenceFmusTest.java b/maestro/src/test/java/org/intocps/maestro/fmi3/Fmi3ModuleReferenceFmusTest.java similarity index 92% rename from maestro/src/test/java/org/intocps/maestro/Fmi3ModuleReferenceFmusTest.java rename to maestro/src/test/java/org/intocps/maestro/fmi3/Fmi3ModuleReferenceFmusTest.java index b388ef390..1c74d313a 100644 --- a/maestro/src/test/java/org/intocps/maestro/Fmi3ModuleReferenceFmusTest.java +++ b/maestro/src/test/java/org/intocps/maestro/fmi3/Fmi3ModuleReferenceFmusTest.java @@ -1,6 +1,7 @@ -package org.intocps.maestro; +package org.intocps.maestro.fmi3; import org.apache.commons.io.FileUtils; +import org.intocps.maestro.FullSpecTest; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.params.provider.Arguments; @@ -19,11 +20,13 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; +import static org.intocps.maestro.fmi3.Fmi3ModuleTest.hasMablSpec; + public class Fmi3ModuleReferenceFmusTest extends FullSpecTest { private static Stream data() { return Arrays.stream(Objects.requireNonNull(Paths.get("src", "test", "resources", "fmi3","reference").toFile().listFiles())) - .filter(n -> !n.getName().startsWith(".")).map(f -> Arguments.arguments(f.getName(), f)); + .filter(n -> !n.getName().startsWith(".")).filter(hasMablSpec).map(f -> Arguments.arguments(f.getName(), f)); } protected List getSpecificationFiles(File specFolder) { diff --git a/maestro/src/test/java/org/intocps/maestro/Fmi3ModuleTest.java b/maestro/src/test/java/org/intocps/maestro/fmi3/Fmi3ModuleTest.java similarity index 68% rename from maestro/src/test/java/org/intocps/maestro/Fmi3ModuleTest.java rename to maestro/src/test/java/org/intocps/maestro/fmi3/Fmi3ModuleTest.java index 6f04b61ad..8591e80e6 100644 --- a/maestro/src/test/java/org/intocps/maestro/Fmi3ModuleTest.java +++ b/maestro/src/test/java/org/intocps/maestro/fmi3/Fmi3ModuleTest.java @@ -1,5 +1,7 @@ -package org.intocps.maestro; +package org.intocps.maestro.fmi3; +import org.intocps.maestro.FullSpecTest; +import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; import org.junit.jupiter.params.provider.Arguments; import java.io.File; @@ -12,14 +14,18 @@ import java.util.Arrays; import java.util.List; import java.util.Objects; +import java.util.function.Predicate; import java.util.stream.Collectors; import java.util.stream.Stream; public class Fmi3ModuleTest extends FullSpecTest { + public static final Predicate hasMablSpec= + path-> path.isDirectory()&& Arrays.stream(Objects.requireNonNull(path.listFiles())).anyMatch(f->f.getName().endsWith(".mabl")); + private static Stream data() { return Arrays.stream(Objects.requireNonNull(Paths.get("src", "test", "resources", "fmi3","basic").toFile().listFiles())) - .filter(n -> !n.getName().startsWith(".")).map(f -> Arguments.arguments(f.getName(), f)); + .filter(n -> !n.getName().startsWith(".")).filter(hasMablSpec).map(f -> Arguments.arguments(f.getName(), f)); } protected List getSpecificationFiles(File specFolder) { @@ -35,7 +41,8 @@ protected List getSpecificationFiles(File specFolder) { String content = null; try { content = Files.readString(path, charset); - content = content.replace("src/test/resources/fmi3/basic", new File("src/test/resources/fmi3/basic").getAbsolutePath()); + content = content.replace("file:", + Paths.get("src","test","resources","fmi3","basic").toAbsolutePath().toUri().toString()); Files.write(path, content.getBytes(charset)); } catch (IOException e) { throw new RuntimeException(e); diff --git a/maestro/src/test/resources/fmi3/basic/fmi3_basic.mabl b/maestro/src/test/resources/fmi3/basic/basic1/fmi3_basic.mabl similarity index 88% rename from maestro/src/test/resources/fmi3/basic/fmi3_basic.mabl rename to maestro/src/test/resources/fmi3/basic/basic1/fmi3_basic.mabl index b2fc690f3..5c4f408d4 100644 --- a/maestro/src/test/resources/fmi3/basic/fmi3_basic.mabl +++ b/maestro/src/test/resources/fmi3/basic/basic1/fmi3_basic.mabl @@ -4,7 +4,7 @@ import FMI3; FMI3 x1 =null; try { - x1 = load("FMI3", "{FMI3_TEST_TOKEN}", "file:src/test/resources/fmi3/basic/fmi3functiontest.fmu"); + x1 = load("FMI3", "{FMI3_TEST_TOKEN}", "file:fmi3functiontest.fmu"); if (x1 == null) { error; From 23ae8db2094c780d867fc4a2a433e352b3d1e6c8 Mon Sep 17 00:00:00 2001 From: Kenneth Lausdahl Date: Mon, 12 Jun 2023 12:34:19 +0200 Subject: [PATCH 09/54] updated external reflect helper to allow for output through return and added support for most of fmi3 --- .../maestro/interpreter/Fmi3Interpreter.java | 1565 ----------------- .../interpreter/Fmi3InterpreterAuto.java | 1079 ------------ .../extensions/Fmi3LifecycleHandler.java | 5 +- .../fmi3/Fmi3InstanceArgMapping.java | 63 + .../extensions/fmi3/Fmi3Interpreter.java | 698 ++++++++ .../extensions/fmi3/Fmi3StateArgMapping.java | 84 + .../extensions/fmi3/Fmi3StatusArgMapping.java | 83 + .../extensions/fmi3/ResultProxyArgMapper.java | 80 + .../external/ExternalReflectCallHelper.java | 212 ++- .../external/ExternalReflectModuleHelper.java | 13 +- .../interpreter/external/IArgMapping.java | 5 +- .../fmi3/reference/bounchingball/fmi3_bb.mabl | 77 +- .../org/intocps/maestro/typechecker/FMI3.mabl | 28 +- 13 files changed, 1265 insertions(+), 2727 deletions(-) delete mode 100644 interpreter/src/main/java/org/intocps/maestro/interpreter/Fmi3Interpreter.java delete mode 100644 interpreter/src/main/java/org/intocps/maestro/interpreter/Fmi3InterpreterAuto.java create mode 100644 interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/fmi3/Fmi3InstanceArgMapping.java create mode 100644 interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/fmi3/Fmi3Interpreter.java create mode 100644 interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/fmi3/Fmi3StateArgMapping.java create mode 100644 interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/fmi3/Fmi3StatusArgMapping.java create mode 100644 interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/fmi3/ResultProxyArgMapper.java diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/Fmi3Interpreter.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/Fmi3Interpreter.java deleted file mode 100644 index 276b4822c..000000000 --- a/interpreter/src/main/java/org/intocps/maestro/interpreter/Fmi3Interpreter.java +++ /dev/null @@ -1,1565 +0,0 @@ -package org.intocps.maestro.interpreter; - -import org.apache.commons.lang3.ArrayUtils; -import org.apache.logging.log4j.Level; -import org.apache.logging.log4j.core.Layout; -import org.apache.logging.log4j.core.impl.Log4jLogEvent; -import org.apache.logging.log4j.core.layout.PatternLayout; -import org.apache.logging.log4j.message.ParameterizedMessage; -import org.intocps.fmi.FmuInvocationException; -import org.intocps.fmi.FmuMissingLibraryException; -import org.intocps.fmi.jnifmuapi.fmi3.*; -import org.intocps.maestro.ast.AFunctionDeclaration; -import org.intocps.maestro.ast.AModuleDeclaration; -import org.intocps.maestro.ast.node.ANameType; -import org.intocps.maestro.ast.node.AReferenceType; -import org.intocps.maestro.ast.node.PType; -import org.intocps.maestro.interpreter.external.ExternalReflectCallHelper; -import org.intocps.maestro.interpreter.external.IArgMapping; -import org.intocps.maestro.interpreter.external.TP; -import org.intocps.maestro.interpreter.values.*; -import org.intocps.maestro.interpreter.values.fmi.Fmu3InstanceValue; -import org.intocps.maestro.interpreter.values.fmi.Fmu3StateValue; -import org.intocps.maestro.interpreter.values.fmi.Fmu3Value; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.*; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.net.URI; -import java.nio.charset.StandardCharsets; -import java.util.*; -import java.util.function.Function; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -import static org.intocps.maestro.interpreter.Fmi2Interpreter.*; - -public class Fmi3Interpreter { - static final ExternalReflectCallHelper.ArgMapping boolArrayOutArgMapper = new ExternalReflectCallHelper.ArgMapping(TP.Bool, 2, - ExternalReflectCallHelper.ArgMapping.InOut.Output, null); - static final ExternalReflectCallHelper.ArgMapping doubleArrayOutArgMapper = new ExternalReflectCallHelper.ArgMapping(TP.Real, 2, - ExternalReflectCallHelper.ArgMapping.InOut.Output, null); - - static final ExternalReflectCallHelper.ArgMapping intInArgMapper = new ExternalReflectCallHelper.ArgMapping(TP.Int, 1, - ExternalReflectCallHelper.ArgMapping.InOut.Input, null); - static final ExternalReflectCallHelper.ArgMapping doubleInArgMapper = new ExternalReflectCallHelper.ArgMapping(TP.Real, 1, - ExternalReflectCallHelper.ArgMapping.InOut.Input, null); - - static final ExternalReflectCallHelper.ArgMapping boolInArgMapper = new ExternalReflectCallHelper.ArgMapping(TP.Bool, 1, - ExternalReflectCallHelper.ArgMapping.InOut.Input, null); - - static final ExternalReflectCallHelper.ArgMapping doubleArrayInArgMapper = new ExternalReflectCallHelper.ArgMapping(TP.Real, 2, - ExternalReflectCallHelper.ArgMapping.InOut.Input, null); - - static final ExternalReflectCallHelper.ArgMapping longArrayInArgMapper = new ExternalReflectCallHelper.ArgMapping(TP.Long, 2, - ExternalReflectCallHelper.ArgMapping.InOut.Input, null); - - static final ExternalReflectCallHelper.ArgMapping uintArrayOutArgMapper = new ExternalReflectCallHelper.ArgMapping(TP.Int, 2, - ExternalReflectCallHelper.ArgMapping.InOut.Output, null); - static final ExternalReflectCallHelper.ArgMapping longArrayOutArgMapper = new ExternalReflectCallHelper.ArgMapping(TP.Long, 2, - ExternalReflectCallHelper.ArgMapping.InOut.Output, null); - - static final ExternalReflectCallHelper.ArgMapping intArrayOutArgMapper = new ExternalReflectCallHelper.ArgMapping(TP.Int, 2, - ExternalReflectCallHelper.ArgMapping.InOut.Output, null); - - - final static Logger logger = LoggerFactory.getLogger(Interpreter.class); - private final File workingDirectory; - private final Function resolver; - - public Fmi3Interpreter(File workingDirectory, Function resolver) { - - this.workingDirectory = workingDirectory; - this.resolver = resolver; - } - - public static Double getDouble(Value value) { - - if (value == null || value instanceof NullValue) { - return null; - } - - value = value.deref(); - - if (value == null || value instanceof NullValue) { - return null; - } - - if (value instanceof RealValue) { - return ((RealValue) value).getValue(); - } - throw new InterpreterException("Value is not double"); - } - - public static UpdatableValue getUpdatable(Value v) { - if (!(v instanceof UpdatableValue)) { - throw new InterpreterException("value not a reference value"); - } - return (UpdatableValue) v; - } - - public Map createFmuMembers(File workingDirectory, String guid, IFmi3Fmu fmu) { - - - var fmi3Module = resolver.apply("FMI3"); - Map functions = new HashMap<>(); - - /* - * - * FMI3Instance instantiateCoSimulation(string instanceName, string instantiationToken, string resourceLocation, bool visible, bool loggingOn, - bool eventModeUsed, bool earlyReturnAllowed, uint[] requiredIntermediateVariables); //, ILogMessageCallback logMessage,IIntermediateUpdateCallback intermediateUpdate - -FMI2Component instantiateCoSimulationWrapAsFmi2(string instanceName, string instantiationToken, string resourceLocation, bool visible, bool loggingOn, - bool eventModeUsed, bool earlyReturnAllowed, uint[] requiredIntermediateVariables);//, ILogMessageCallback logMessage,IIntermediateUpdateCallback intermediateUpdate - - * - * */ - - - functions.put("instantiateCoSimulation", new FunctionValue.ExternalFunctionValue(fargs -> { - - Fmi2Interpreter.checkArgLength(fargs, 6); - - String name = Fmi2Interpreter.getString(fargs.get(0)); - boolean visible = Fmi2Interpreter.getBool(fargs.get(1)); - boolean logginOn = Fmi2Interpreter.getBool(fargs.get(2)); - - boolean eventModeUsed = Fmi2Interpreter.getBool(fargs.get(3)); - boolean earlyReturnAllowed = Fmi2Interpreter.getBool(fargs.get(4)); - long[] requiredIntermediateVariables = getArrayValue(fargs.get(5), Optional.empty(), NumericValue.class).stream() - .mapToLong(NumericValue::longValue).toArray(); - - try { - - long startInstantiateTime = System.nanoTime(); - - logger.debug(String.format("Loading native FMU. GUID: %s, NAME: %s", "" + guid, "" + name)); - - BufferedOutputStream fmuLogOutputStream = workingDirectory == null ? null : new BufferedOutputStream( - new FileOutputStream(new File(workingDirectory, name + ".log"))); - - final String formatter = "{} {} {} {}"; - String pattern = "%d{ISO8601} %-5p - %m%n"; - - Layout layout = PatternLayout.newBuilder().withPattern(pattern).withCharset(StandardCharsets.UTF_8).build();// - - ILogMessageCallback logCallback = (instanceName, status, category, message) -> { - logger.info("NATIVE: instance: '{}', status: '{}', category: '{}', message: {}", instanceName, status, category, message); - { - - if (fmuLogOutputStream == null) { - return; - } - - Log4jLogEvent.Builder builder = Log4jLogEvent.newBuilder() - .setMessage(new ParameterizedMessage(formatter, category, status, instanceName, message)); - - - switch (status) { - case OK: - case Discard: - builder.setLevel(Level.INFO); - break; - case Error: - case Fatal: - builder.setLevel(Level.ERROR); - case Warning: - builder.setLevel(Level.WARN); - break; - default: - builder.setLevel(Level.TRACE); - break; - } - - try { - Log4jLogEvent event = builder.build(); - fmuLogOutputStream.write(layout.toByteArray(event)); - } catch (IOException e) { - e.printStackTrace(); - } - } - }; - IIntermediateUpdateCallback intermediateUpdateCallback = (instanceEnvironment, intermediateUpdateTime, clocksTicked, intermediateVariableSetRequested, intermediateVariableGetAllowed, intermediateStepFinished, canReturnEarly) -> new IIntermediateUpdateCallback.IntermediateUpdateResponse( - false, intermediateUpdateTime); - IFmi3Instance instance = fmu.instantiateCoSimulation(name, guid, visible, logginOn, eventModeUsed, earlyReturnAllowed, - requiredIntermediateVariables, logCallback, null); - - - if (instance == null) { - logger.debug("Instance instantiate failed"); - return new NullValue(); - } - long stopInstantiateTime = System.nanoTime(); - System.out.println("Interpretation instantiate took: " + (stopInstantiateTime - startInstantiateTime)); - - return getFmuInstanceValue(fmuLogOutputStream, instance, resolver); - - - } catch (IOException | NoSuchMethodException e) { - e.printStackTrace(); - } - - return null; - })); - - - functions.put("freeInstance", new FunctionValue.ExternalFunctionValue(fargs -> { - - fargs = fargs.stream().map(Value::deref).collect(Collectors.toList()); - - logger.debug("freeInstance"); - - if (fargs.size() != 1) { - throw new InterpreterException("Too few arguments"); - } - - if (!(fargs.get(0) instanceof Fmu3InstanceValue)) { - throw new InterpreterException("Argument must be an external module reference"); - } - - Fmu3InstanceValue component = (Fmu3InstanceValue) fargs.get(0); - - try { - OutputStream loggerOutputStream = component.getFmuLoggerOutputStream(); - if (loggerOutputStream != null) { - loggerOutputStream.close(); - } - component.getModule().freeInstance(); - } catch (IOException | FmuInvocationException e) { - e.printStackTrace(); - } - - - return new VoidValue(); - })); - - functions.put("unload", new FunctionValue.ExternalFunctionValue(fargs -> { - fargs = fargs.stream().map(Value::deref).collect(Collectors.toList()); - - logger.debug("unload"); - - if (fargs.size() != 0) { - throw new InterpreterException("Too many arguments"); - } - - try { - fmu.unLoad(); - } catch (FmuInvocationException e) { - e.printStackTrace(); - } - - return new VoidValue(); - })); - - checkRequiredFunctions(fmi3Module, functions); - - return functions; - } - - static void checkRequiredFunctions(AModuleDeclaration module, Map functions) { - var expectedFunctions = module.getFunctions().stream().map(f -> f.getName().getText()).collect(Collectors.toSet()); - - if (expectedFunctions.size() != functions.size() || !functions.keySet().equals(expectedFunctions)) { - logger.warn("Runtime type '{}' does not match declaration. Missing: '{}'", module.getName().getText(), - expectedFunctions.stream().filter(n -> !functions.containsKey(n)).sorted().collect(Collectors.joining(",\n\t", "\n\t", ""))); - } - } - - private static Value getFmuInstanceValue(BufferedOutputStream fmuLogOutputStream, IFmi3Instance instance, - Function resolver) throws NoSuchMethodException { - - //populate component functions - var module = resolver.apply("FMI3Instance"); - - - Map functions = new HashMap<>(createGetSetMembers(instance)); - - Predicate functionFilter = fun -> !fun.getName().getText().equals("enterInitializationMode") && !fun.getName().getText() - .startsWith("get") && !fun.getName().getText().equals("setBinary"); - - Function costumeArgMapper = t -> { - - boolean output = t instanceof AReferenceType; - if (output) { - t = ((AReferenceType) t).getType(); - } - - - if (t instanceof ANameType) { - String typeName = ((ANameType) t).getName().getText(); - if (typeName.equals("FMI3Instance")) { - return new IArgMapping() { - @Override - public int getDimension() { - return 1; - } - - @Override - public long[] getLimits() { - return null; - } - - @Override - public ExternalReflectCallHelper.ArgMapping.InOut getDirection() { - return ExternalReflectCallHelper.ArgMapping.InOut.Input; - } - - @Override - public Object map(Value v) { - if (v instanceof ExternalModuleValue) { - return ((ExternalModuleValue) v).getModule(); - } - return null; - } - - @Override - public void mapOut(Value original, Object value) { - throw new RuntimeException("This is only for input so should not be called"); - } - - @Override - public Value mapOut(Object value) { - return new ExternalModuleValue<>(null, value) {}; - } - - @Override - public Class getType() { - return Object.class; - } - - @Override - public String getDescriptiveName() { - return "FMI3Instance"; - } - - @Override - public String getDefaultTestValue() { - return "null"; - } - }; - } else if (typeName.equals("FMU3State")) { - return new IArgMapping() { - @Override - public int getDimension() { - return 1; - } - - @Override - public long[] getLimits() { - return null; - } - - @Override - public ExternalReflectCallHelper.ArgMapping.InOut getDirection() { - return output ? ExternalReflectCallHelper.ArgMapping.InOut.Output : ExternalReflectCallHelper.ArgMapping.InOut.Input; - } - - @Override - public Object map(Value v) { - if (v instanceof Fmu3StateValue) { - return ((Fmu3StateValue) v).getModule(); - } - return null; - } - - @Override - public void mapOut(Value original, Object value) { - if (original instanceof UpdatableValue) { - UpdatableValue up = (UpdatableValue) original; - up.setValue(new Fmu3StateValue((Fmi3State) value)); - } - - } - - @Override - public Value mapOut(Object value) { - return null; - } - - @Override - public Class getType() { - return Fmi3State.class; - } - - @Override - public String getDescriptiveName() { - return "Fmi3State"; - } - - @Override - public String getDefaultTestValue() { - return null; - } - }; - } - } - return null; - }; - - for (AFunctionDeclaration function : module.getFunctions()) { - if (functionFilter == null || functionFilter.test(function)) { - - functions.computeIfAbsent(function.getName().getText(), key -> { - try { - return new ExternalReflectCallHelper(function, instance, costumeArgMapper).build(); - } catch (NoSuchMethodException e) { - System.err.println(e.getMessage()); - return null; - } catch (RuntimeException e) { - System.err.println(e.getMessage()); - return null; - } - }); - - } - } - - - for (AFunctionDeclaration function : module.getFunctions()) { - if (functionFilter == null || functionFilter.test(function)) { - - functions.computeIfAbsent(function.getName().getText(), key -> { - try { - return new ExternalReflectCallHelper(function, instance, costumeArgMapper) { - @Override - public FunctionValue.ExternalFunctionValue build() throws NoSuchMethodException { - final List args = Collections.unmodifiableList(this); - final IArgMapping rArg = returnArg; - final Method method = object.getClass().getMethod(functionName, - args.stream().filter(arg -> arg.getDirection() == ArgMapping.InOut.Input).map(IArgMapping::getType) - .toArray(Class[]::new)); - - if (method.getReturnType().isAssignableFrom(FmuResult.class)) { - //ok so we are using the result return type - long outputs = args.stream().filter(arg -> arg.getDirection() == ArgMapping.InOut.Output).count(); - System.out.println(outputs); - } - - - return new FunctionValue.ExternalFunctionValue(fcargs -> { - - checkArgLength(fcargs, args.size()); - - //map inputs - var vitr = fcargs.iterator(); - var mitr = args.iterator(); - List argValues = new ArrayList(args.size()); - while (vitr.hasNext() && mitr.hasNext()) { - var v = vitr.next(); - IArgMapping mapper = mitr.next(); - switch (mapper.getDirection()) { - case Input: - case Output: - argValues.add(mapper.map(v)); - break; - } - } - - try { - var ret = method.invoke(object, argValues.toArray()); - - //map outputs - vitr = fcargs.iterator(); - var voitr = argValues.iterator(); - mitr = args.iterator(); - while (vitr.hasNext() && voitr.hasNext() && mitr.hasNext()) { - var original = vitr.next(); - IArgMapping mapper = mitr.next(); - - Object output = null; - - switch (mapper.getDirection()) { - case Input: - case Output: - output = voitr.next(); - break; - } - - if (mapper.getDirection() == ArgMapping.InOut.Output) { - mapper.mapOut(original, output); - } - } - - - if (rArg == null) { - return new VoidValue(); - } - return rArg.mapOut(ret); - - - } catch (IllegalAccessException | InvocationTargetException e) { - throw new RuntimeException(e); - } - }); - } - }.build(); - } catch (NoSuchMethodException e) { - System.err.println(e.getMessage()); - return null; - } catch (RuntimeException e) { - System.err.println(e.getMessage()); - return null; - } - }); - - } - } - - - //void methods - // functions.put("freeInstance", new FunctionValue.ExternalFunctionValue(fcargs -> { - // - // checkArgLength(fcargs, 0); - // try { - // instance.freeInstance(); - // return new VoidValue(); - // } catch (FmuInvocationException e) { - // throw new InterpreterException(e); - // } - // - // })); - // - // String[] voidStatusMethods = new String[]{"exitInitializationMode", "enterEventMode", "terminate", "reset", "enterConfigurationMode", - // "exitConfigurationMode", "evaluateDiscreteStates", "enterContinuousTimeMode", "enterStepMode"}; - // - // for (String methodName : voidStatusMethods) { - // Method method = instance.getClass().getMethod(methodName); - // - // functions.put(methodName, new FunctionValue.ExternalFunctionValue(fcargs -> { - // - // checkArgLength(fcargs, 0); - // - // - // try { - // Fmi3Status res = (Fmi3Status) method.invoke(instance); - // return status2IntValue(res); - // } catch (IllegalAccessException | InvocationTargetException e) { - // throw new InterpreterException(e); - // } - // })); - // - // } - - - - /* - -int setDebugLogging(bool loggingOn, string categories[]); -int enterInitializationMode(bool toleranceDefined, real tolerance, real startTime, bool stopTimeDefined, - -int getBinary(uint valueReferences[], int nValueReferences, byte values[][], int nValues); -int setBinary(uint valueReferences[], int nValueReferences, long sizes[], byte array_name[][], int nValues); -int getNumberOfVariableDependencies(uint valueReference, out int nDependencies); -int getVariableDependencies(uint dependent, int elementIndicesOfDependent[], uint independents[], -int getFMUState(out FMUS3tate FMUState); -int setFMUState(FMUS3tate FMUState); -int freeFMUState(out FMUS3tate FMUState); -int getDirectionalDerivative(uint unknowns[], int nUnknowns, uint knowns[], int nKnowns, real seed[], int nSeed, -int getAdjointDerivative(uint unknowns[], int nUnknowns, uint knowns[], int nKnowns, real seed[], int nSeed, -int getClock(uint valueReferences[], int nValueReferences, bool values[]); -int setClock(uint valueReferences[], int nValueReferences, bool values[]); -int getIntervalDecimal(uint valueReferences[], int nValueReferences, real intervals[], -int getIntervalFraction(uint valueReferences[], int nValueReferences, uint intervalCounters[], uint resolutions[], -int getShiftDecimal(uint valueReferences[], int nValueReferences, real shifts[]); -int getShiftFraction(uint valueReferences[], int nValueReferences, uint shiftCounters[], uint resolutions[]); -int setIntervalDecimal(uint valueReferences[], int nValueReferences, real interval[]); -int setIntervalFraction(uint valueReferences[], int nValueReferences, uint intervalCounter[], uint resolution[]); -int setShiftDecimal(uint valueReferences[], int nValueReferences, real shifts[]); -int setShiftFraction(uint valueReferences[], int nValueReferences, uint counters[], uint resolutions[]); -int updateDiscreteStates(bool[] discreteStatesNeedUpdate, bool[] terminateSimulation, -int completedIntegratorStep(bool nosetFMUStatePriorToCurrentPoint, bool[] enterEventMode, -int setTime(real time); -int setContinuousStates(real continuousStates[], int nContinuousStates); -int getContinuousStateDerivatives(real derivatives[], int nContinuousStates); -int getEventIndicators(real eventIndicators[], int nEventIndicators); -int getContinuousStates(real continuousStates[], int nContinuousStates); -int getNominalsOfContinuousStates(real nominals[], int nContinuousStates); -int getNumberOfEventIndicators(int[] nEventIndicators); -int getNumberOfContinuousStates(int[] nContinuousStates); -int getOutputDerivatives(uint valueReferences[], int nValueReferences, int orders[], real values[], int nValues); -int doStep(real currentCommunicationPoint, real communicationStepSize, bool nosetFMUStatePriorToCurrentPoint, -int activateModelPartition(uint clockReference, real activationTime); - - */ - - - // functions.put("setDebugLogging", new FunctionValue.ExternalFunctionValue(fcargs -> { - // - // checkArgLength(fcargs, 3); - // - // boolean debugLogginOn = getBool(fcargs.get(0)); - // // int arraySize = getInteger(fcargs.get(1)); - // List categories = getArrayValue(fcargs.get(2), StringValue.class); - // - // try { - // Fmi3Status res = instance.setDebugLogging(debugLogginOn, categories.stream().map(StringValue::getValue).toArray(String[]::new)); - // return new IntegerValue(res.value); - // } catch (FmuInvocationException e) { - // throw new InterpreterException(e); - // } - // })); - - // functions.put("setupExperiment", new FunctionValue.ExternalFunctionValue(fcargs -> { - // - // checkArgLength(fcargs, 5); - // - // boolean toleranceDefined = getBool(fcargs.get(0)); - // double tolerance = getDouble(fcargs.get(1)); - // double startTime = getDouble(fcargs.get(2)); - // boolean stopTimeDefined = getBool(fcargs.get(3)); - // double stopTime = getDouble(fcargs.get(4)); - // try { - // Fmi2Status res = instance.setupExperiment(toleranceDefined, tolerance, startTime, stopTimeDefined, stopTime); - // return new IntegerValue(res.value); - // } catch (FmuInvocationException e) { - // throw new InterpreterException(e); - // } - // })); - functions.put("enterInitializationMode", new FunctionValue.ExternalFunctionValue(fcargs -> { - - checkArgLength(fcargs, 3); - - Double tolerance = getDouble(fcargs.get(0)); - double startTime = getDouble(fcargs.get(1)); - Double stopTime = getDouble(fcargs.get(2)); - - - try { - Fmi3Status res = instance.enterInitializationMode(tolerance, startTime, stopTime); - return new IntegerValue(res.value); - } catch (FmuInvocationException e) { - throw new InterpreterException(e); - } - - })); - - functions.put("completedIntegratorStep", new FunctionValue.ExternalFunctionValue(fcargs -> { - // int completedIntegratorStep(bool nosetFMUStatePriorToCurrentPoint, bool[] enterEventMode,bool[] terminateSimulation); - - checkArgLength(fcargs, 3); - try { - FmuResult res = instance.completedIntegratorStep( - (Boolean) boolInArgMapper.map(fcargs.get(0))); - boolArrayOutArgMapper.mapOut(fcargs.get(1), new boolean[]{res.result.isEnterEventMode()}); - boolArrayOutArgMapper.mapOut(fcargs.get(2), new boolean[]{res.result.isTerminateSimulation()}); - return status2IntValue(res.status); - } catch (FmuInvocationException e) { - throw new InterpreterException(e); - } - - })); - - functions.put("getAdjointDerivative", new FunctionValue.ExternalFunctionValue(fcargs -> { - // int getAdjointDerivative(uint unknowns[], int nUnknowns, uint knowns[], int nKnowns, real seed[], int nSeed, - // real sensitivity[], int nSensitivity); - - checkArgLength(fcargs, 8); - try { - FmuResult res = instance.getGetAdjointDerivative((long[]) longArrayInArgMapper.map(fcargs.get(0)), - (long[]) longArrayInArgMapper.map(fcargs.get(2)), (double[]) doubleArrayInArgMapper.map(fcargs.get(4)), - (Integer) intInArgMapper.map(fcargs.get(5))); - doubleArrayOutArgMapper.mapOut(fcargs.get(6), res.result); - return status2IntValue(res.status); - } catch (FmuInvocationException e) { - throw new InterpreterException(e); - } - - })); - - functions.put("getClock", new FunctionValue.ExternalFunctionValue(fcargs -> { - // int getClock(uint valueReferences[], int nValueReferences, bool values[]); - - checkArgLength(fcargs, 3); - try { - FmuResult res = instance.getClock((long[]) longArrayInArgMapper.map(fcargs.get(0))); - boolArrayOutArgMapper.mapOut(fcargs.get(2), res.result); - return status2IntValue(res.status); - } catch (FmuInvocationException e) { - throw new InterpreterException(e); - } - - })); - - - functions.put("getContinuousStateDerivatives", new FunctionValue.ExternalFunctionValue(fcargs -> { - //int getContinuousStateDerivatives(real derivatives[], int nContinuousStates); - - checkArgLength(fcargs, 2); - try { - FmuResult res = instance.getContinuousStateDerivatives((Integer) intInArgMapper.map(fcargs.get(1))); - doubleArrayOutArgMapper.mapOut(fcargs.get(0), res.result); - return status2IntValue(res.status); - } catch (FmuInvocationException e) { - throw new InterpreterException(e); - } - - })); - - functions.put("getContinuousStates", new FunctionValue.ExternalFunctionValue(fcargs -> { - //int getContinuousStates(real continuousStates[], int nContinuousStates); - - checkArgLength(fcargs, 2); - try { - FmuResult res = instance.getGetContinuousStates((Integer) intInArgMapper.map(fcargs.get(1))); - doubleArrayOutArgMapper.mapOut(fcargs.get(0), res.result); - return status2IntValue(res.status); - } catch (FmuInvocationException e) { - throw new InterpreterException(e); - } - - })); - - functions.put("getDirectionalDerivative", new FunctionValue.ExternalFunctionValue(fcargs -> { - // int getDirectionalDerivative(uint unknowns[], int nUnknowns, uint knowns[], int nKnowns, real seed[], int nSeed, - // real sensitivity[], int nSensitivity); - - checkArgLength(fcargs, 8); - try { - FmuResult res = instance.getDirectionalDerivative((long[]) longArrayInArgMapper.map(fcargs.get(0)), - (long[]) longArrayInArgMapper.map(fcargs.get(2)), (double[]) doubleArrayInArgMapper.map(fcargs.get(4))); - - doubleArrayOutArgMapper.mapOut(fcargs.get(6), res.result); - return status2IntValue(res.status); - } catch (FmuInvocationException e) { - throw new InterpreterException(e); - } - - })); - - - functions.put("getEventIndicators", new FunctionValue.ExternalFunctionValue(fcargs -> { - // int getEventIndicators(real eventIndicators[], int nEventIndicators); - - checkArgLength(fcargs, 2); - try { - FmuResult res = instance.getGetEventIndicators((Integer) intInArgMapper.map(fcargs.get(1))); - doubleArrayOutArgMapper.mapOut(fcargs.get(0), res.result); - return status2IntValue(res.status); - } catch (FmuInvocationException e) { - throw new InterpreterException(e); - } - - })); - - - functions.put("getIntervalDecimal", new FunctionValue.ExternalFunctionValue(fcargs -> { - // int getIntervalDecimal(uint valueReferences[], int nValueReferences, real intervals[], - // int qualifiers[]); - - checkArgLength(fcargs, 4); - try { - FmuResult res = instance.getIntervalDecimal( - (long[]) longArrayInArgMapper.map(fcargs.get(0))); - doubleArrayOutArgMapper.mapOut(fcargs.get(2), res.result.getIntervals()); - doubleArrayOutArgMapper.mapOut(fcargs.get(3), res.result.getQualifiers()); - return status2IntValue(res.status); - } catch (FmuInvocationException e) { - throw new InterpreterException(e); - } - - })); - - functions.put("getIntervalFraction", new FunctionValue.ExternalFunctionValue(fcargs -> { - // int getIntervalFraction(uint valueReferences[], int nValueReferences, uint intervalCounters[], uint resolutions[], - // int qualifiers[]); - - checkArgLength(fcargs, 5); - try { - FmuResult res = instance.getIntervalFraction( - (long[]) longArrayInArgMapper.map(fcargs.get(0))); - uintArrayOutArgMapper.mapOut(fcargs.get(2), res.result.getIntervalCounters()); - uintArrayOutArgMapper.mapOut(fcargs.get(3), res.result.getResolutions()); - intInArgMapper.mapOut(fcargs.get(3), Arrays.stream(res.result.getQualifiers()).map(q -> q.getValue()).toArray()); - return status2IntValue(res.status); - } catch (FmuInvocationException e) { - throw new InterpreterException(e); - } - - })); - - functions.put("getNominalsOfContinuousStates", new FunctionValue.ExternalFunctionValue(fcargs -> { - // int getNominalsOfContinuousStates(real nominals[], int nContinuousStates); - - checkArgLength(fcargs, 2); - try { - FmuResult res = instance.getGetNominalsOfContinuousStates((Integer) intInArgMapper.map(fcargs.get(1))); - doubleArrayOutArgMapper.mapOut(fcargs.get(0), res.result); - return status2IntValue(res.status); - } catch (FmuInvocationException e) { - throw new InterpreterException(e); - } - - })); - - functions.put("getNumberOfContinuousStates", new FunctionValue.ExternalFunctionValue(fcargs -> { - // int getNumberOfContinuousStates(int[] nContinuousStates); - - checkArgLength(fcargs, 1); - try { - FmuResult res = instance.getNumberOfContinuousStates(); - longArrayOutArgMapper.mapOut(fcargs.get(0), res.result); - return status2IntValue(res.status); - } catch (FmuInvocationException e) { - throw new InterpreterException(e); - } - - })); - - functions.put("getNumberOfEventIndicators", new FunctionValue.ExternalFunctionValue(fcargs -> { - // int getNumberOfEventIndicators(int[] nEventIndicators); - - checkArgLength(fcargs, 1); - try { - FmuResult res = instance.getNumberOfEventIndicators(); - intArrayOutArgMapper.mapOut(fcargs.get(0), res.result); - return status2IntValue(res.status); - } catch (FmuInvocationException e) { - throw new InterpreterException(e); - } - - })); - - - // functions.put("exitInitializationMode", new FunctionValue.ExternalFunctionValue(fcargs -> { - // checkArgLength(fcargs, 0); - // try { - // Fmi3Status res = instance.exitInitializationMode(); - // return new IntegerValue(res.value); - // } catch (FmuInvocationException e) { - // throw new InterpreterException(e); - // } - // })); - // functions.put("setReal", new FunctionValue.ExternalFunctionValue(fcargs -> { - // checkArgLength(fcargs, 3); - // long elementsToUse = getUint(fcargs.get(1)); - // long[] scalarValueIndices = - // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) - // .toArray(); - // double[] values = getArrayValue(fcargs.get(2), Optional.of(elementsToUse), NumericValue.class).stream().limit(elementsToUse) - // .mapToDouble(NumericValue::realValue).toArray(); - // - // try { - // Fmi3Status res = instance.setReals(scalarValueIndices, values); - // return new IntegerValue(res.value); - // } catch (InvalidParameterException | FmiInvalidNativeStateException e) { - // throw new InterpreterException(e); - // } - // - // })); - // functions.put("getReal", new FunctionValue.ExternalFunctionValue(fcargs -> { - // - // checkArgLength(fcargs, 3); - // - // if (!(fcargs.get(2) instanceof UpdatableValue)) { - // throw new InterpreterException("value not a reference value"); - // } - // long elementsToUse = getUint(fcargs.get(1)); - // - // long[] scalarValueIndices = - // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) - // .toArray(); - // - // - // try { - // org.intocps.fmi.FmuResult res = instance.getReal(scalarValueIndices); - // - // if (res.status == Fmi2Status.OK) { - // UpdatableValue ref = (UpdatableValue) fcargs.get(2); - // - // List values = Arrays.stream(ArrayUtils.toObject(res.result)).limit(elementsToUse).map(d -> new RealValue(d)) - // .collect(Collectors.toList()); - // - // ref.setValue(new ArrayValue<>(values)); - // } - // - // - // return new IntegerValue(res.status.value); - // - // } catch (FmuInvocationException e) { - // throw new InterpreterException(e); - // } - // - // - // })); - // functions.put("setInteger", new FunctionValue.ExternalFunctionValue(fcargs -> { - // checkArgLength(fcargs, 3); - // long elementsToUse = getUint(fcargs.get(1)); - // long[] scalarValueIndices = - // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) - // .toArray(); - // int[] values = - // getArrayValue(fcargs.get(2), Optional.of(elementsToUse), IntegerValue.class).stream().mapToInt(IntegerValue::getValue).toArray(); - // - // try { - // Fmi2Status res = instance.setIntegers(scalarValueIndices, values); - // return new IntegerValue(res.value); - // } catch (InvalidParameterException | FmiInvalidNativeStateException e) { - // throw new InterpreterException(e); - // } - // })); - // functions.put("getInteger", new FunctionValue.ExternalFunctionValue(fcargs -> { - // - // checkArgLength(fcargs, 3); - // long elementsToUse = getUint(fcargs.get(1)); - // - // if (!(fcargs.get(2) instanceof UpdatableValue)) { - // throw new InterpreterException("value not a reference value"); - // } - // - // long[] scalarValueIndices = - // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) - // .toArray(); - // - // - // try { - // org.intocps.fmi.FmuResult res = instance.getInteger(scalarValueIndices); - // - // if (res.status == Fmi2Status.OK) { - // UpdatableValue ref = (UpdatableValue) fcargs.get(2); - // - // List values = Arrays.stream(ArrayUtils.toObject(res.result)).limit(elementsToUse).map(i -> new IntegerValue(i)) - // .collect(Collectors.toList()); - // - // ref.setValue(new ArrayValue<>(values)); - // } - // - // - // return new IntegerValue(res.status.value); - // - // } catch (FmuInvocationException e) { - // throw new InterpreterException(e); - // } - // - // - // })); - // functions.put("setBoolean", new FunctionValue.ExternalFunctionValue(fcargs -> { - // - // checkArgLength(fcargs, 3); - // long elementsToUse = getUint(fcargs.get(1)); - // long[] scalarValueIndices = - // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) - // .toArray(); - // boolean[] values = ArrayUtils.toPrimitive( - // getArrayValue(fcargs.get(2), Optional.of(elementsToUse), BooleanValue.class).stream().map(BooleanValue::getValue) - // .collect(Collectors.toList()).toArray(new Boolean[]{})); - // - // try { - // Fmi2Status res = instance.setBooleans(scalarValueIndices, values); - // return new IntegerValue(res.value); - // } catch (InvalidParameterException | FmiInvalidNativeStateException e) { - // throw new InterpreterException(e); - // } - // })); - // functions.put("getBoolean", new FunctionValue.ExternalFunctionValue(fcargs -> { - // - // checkArgLength(fcargs, 3); - // - // if (!(fcargs.get(2) instanceof UpdatableValue)) { - // throw new InterpreterException("value not a reference value"); - // } - // - // long elementsToUse = getUint(fcargs.get(1)); - // - // - // long[] scalarValueIndices = - // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) - // .toArray(); - // - // - // try { - // org.intocps.fmi.FmuResult res = instance.getBooleans(scalarValueIndices); - // - // if (res.status == Fmi2Status.OK) { - // UpdatableValue ref = (UpdatableValue) fcargs.get(2); - // - // List values = - // Arrays.stream(ArrayUtils.toObject(res.result)).limit(elementsToUse).map(BooleanValue::new).collect(Collectors.toList()); - // - // ref.setValue(new ArrayValue<>(values)); - // } - // - // - // return new IntegerValue(res.status.value); - // - // } catch (FmuInvocationException e) { - // throw new InterpreterException(e); - // } - // - // })); - // functions.put("setString", new FunctionValue.ExternalFunctionValue(fcargs -> { - // - // checkArgLength(fcargs, 3); - // long elementsToUse = getUint(fcargs.get(1)); - // - // long[] scalarValueIndices = - // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) - // .toArray(); - // String[] values = getArrayValue(fcargs.get(2), Optional.of(elementsToUse), StringValue.class).stream().map(StringValue::getValue) - // .collect(Collectors.toList()).toArray(new String[]{}); - // - // try { - // Fmi2Status res = instance.setStrings(scalarValueIndices, values); - // return new IntegerValue(res.value); - // } catch (InvalidParameterException | FmiInvalidNativeStateException e) { - // throw new InterpreterException(e); - // } - // - // })); - // functions.put("getString", new FunctionValue.ExternalFunctionValue(fcargs -> { - // - // checkArgLength(fcargs, 3); - // - // if (!(fcargs.get(2) instanceof UpdatableValue)) { - // throw new InterpreterException("value not a reference value"); - // } - // - // - // long elementsToUse = getUint(fcargs.get(1)); - // - // - // long[] scalarValueIndices = - // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) - // .toArray(); - // - // - // try { - // org.intocps.fmi.FmuResult res = instance.getStrings(scalarValueIndices); - // - // if (res.status == Fmi2Status.OK) { - // UpdatableValue ref = (UpdatableValue) fcargs.get(2); - // - // List values = Arrays.stream(res.result).limit(elementsToUse).map(StringValue::new).collect(Collectors.toList()); - // - // ref.setValue(new ArrayValue<>(values)); - // } - // - // - // return new IntegerValue(res.status.value); - // - // } catch (FmuInvocationException e) { - // throw new InterpreterException(e); - // } - // - // - // })); - functions.put("doStep", new FunctionValue.ExternalFunctionValue(fcargs -> { - - checkArgLength(fcargs, 7); - - //in - double currentCommunicationPoint = getDouble(fcargs.get(0)); - double communicationStepSize = getDouble(fcargs.get(1)); - boolean noSetFMUStatePriorToCurrentPoint = getBool(fcargs.get(2)); - //out - - UpdatableValue eventHandlingNeeded = getUpdatable(fcargs.get(3)); - UpdatableValue terminateSimulation = getUpdatable(fcargs.get(4)); - UpdatableValue earlyReturn = getUpdatable(fcargs.get(5)); - UpdatableValue lastSuccessfulTime = getUpdatable(fcargs.get(6)); - /*int doStep(real currentCommunicationPoint, real communicationStepSize, bool nosetFMUStatePriorToCurrentPoint, - out bool eventHandlingNeeded,out bool terminateSimulation,out bool earlyReturn,out real lastSuccessfulTime);*/ - - try { - FmuResult res = instance.doStep(currentCommunicationPoint, communicationStepSize, - noSetFMUStatePriorToCurrentPoint); - - if (res.status == Fmi3Status.OK) { - eventHandlingNeeded.setValue(new BooleanValue(res.result.isEventHandlingNeeded())); - terminateSimulation.setValue(new BooleanValue(res.result.isTerminateSimulation())); - earlyReturn.setValue(new BooleanValue(res.result.isEarlyReturn())); - lastSuccessfulTime.setValue(new RealValue(res.result.getLastSuccessfulTime())); - } - return new IntegerValue(res.status.value); - } catch (FmuInvocationException e) { - throw new InterpreterException(e); - } - })); - - functions.put("terminate", new FunctionValue.ExternalFunctionValue(fcargs -> { - checkArgLength(fcargs, 0); - try { - Fmi3Status res = instance.terminate(); - return new IntegerValue(res.value); - } catch (FmuInvocationException e) { - throw new InterpreterException(e); - } - })); - - functions.put("setFMUState", new FunctionValue.ExternalFunctionValue(fcargs -> { - checkArgLength(fcargs, 1); - - Value v = fcargs.get(0).deref(); - - if (v instanceof Fmu3StateValue) { - try { - Fmu3StateValue stateValue = (Fmu3StateValue) v; - Fmi3Status res = instance.setState(stateValue.getModule()); - return new IntegerValue(res.value); - } catch (FmuInvocationException e) { - throw new InterpreterException(e); - } - } - - throw new InterpreterException("Invalid value"); - })); - functions.put("getFMUState", new FunctionValue.ExternalFunctionValue(fcargs -> { - - checkArgLength(fcargs, 1); - - if (!(fcargs.get(0) instanceof UpdatableValue)) { - throw new InterpreterException("value not a reference value"); - } - - - try { - - org.intocps.fmi.jnifmuapi.fmi3.FmuResult res = instance.getState(); - - if (res.status == Fmi3Status.OK) { - UpdatableValue ref = (UpdatableValue) fcargs.get(0); - ref.setValue(new Fmu3StateValue(res.result)); - } - - - return new IntegerValue(res.status.value); - - } catch (FmuInvocationException e) { - throw new InterpreterException(e); - } - - - })); - functions.put("freeFMUState", new FunctionValue.ExternalFunctionValue(fcargs -> { - - checkArgLength(fcargs, 1); - - Value v = fcargs.get(0).deref(); - - if (v instanceof Fmu3StateValue) { - try { - Fmu3StateValue stateValue = (Fmu3StateValue) v; - Fmi3Status res = instance.freeState(stateValue.getModule()); - return new IntegerValue(res.value); - } catch (FmuInvocationException e) { - throw new InterpreterException(e); - } - } - - throw new InterpreterException("Invalid value"); - - - })); - - // functions.put("getRealStatus", new FunctionValue.ExternalFunctionValue(fcargs -> { - // - // checkArgLength(fcargs, 2); - // - // if (!(fcargs.get(1) instanceof UpdatableValue)) { - // throw new InterpreterException("value not a reference value"); - // } - // - // Value kindValue = fcargs.get(0).deref(); - // - // if (!(kindValue instanceof IntegerValue)) { - // throw new InterpreterException("Invalid kind value: " + kindValue); - // } - // - // int kind = ((IntegerValue) kindValue).getValue(); - // - // Fmi2StatusKind kindEnum = Arrays.stream(Fmi2StatusKind.values()).filter(v -> v.value == kind).findFirst().orElse(null); - // - // try { - // org.intocps.fmi.FmuResult res = instance.getRealStatus(kindEnum); - // - // if (res.status == Fmi2Status.OK) { - // UpdatableValue ref = (UpdatableValue) fcargs.get(1); - // - // ref.setValue(new RealValue(res.result)); - // } - // - // - // return new IntegerValue(res.status.value); - // - // } catch (FmuInvocationException e) { - // throw new InterpreterException(e); - // } - // - // - // })); - // - // functions.put("getRealOutputDerivatives", new FunctionValue.ExternalFunctionValue(fcargs -> { - // // int getRealOutputDerivatives(long[] scalarValueIndices, UInt nvr, int[] order, ref double[] derivatives); - // checkArgLength(fcargs, 4); - // - // if (!(fcargs.get(3) instanceof UpdatableValue)) { - // throw new InterpreterException("value not a reference value"); - // } - // - // long elementsToUse = getUint(fcargs.get(1)); - // - // - // long[] scalarValueIndices = - // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) - // .toArray(); - // - // int[] orders = - // getArrayValue(fcargs.get(2), Optional.of(elementsToUse), NumericValue.class).stream().mapToInt(NumericValue::intValue).toArray(); - // - // try { - // FmuResult res = instance.getRealOutputDerivatives(scalarValueIndices, orders); - // - // if (res.status == Fmi2Status.OK) { - // UpdatableValue ref = (UpdatableValue) fcargs.get(3); - // - // List values = Arrays.stream(ArrayUtils.toObject(res.result)).limit(elementsToUse).map(d -> new RealValue(d)) - // .collect(Collectors.toList()); - // - // ref.setValue(new ArrayValue<>(values)); - // } - // - // - // return new IntegerValue(res.status.value); - // - // } catch (FmuInvocationException e) { - // throw new InterpreterException(e); - // } - // - // - // })); - // - // functions.put("setRealInputDerivatives", new FunctionValue.ExternalFunctionValue(fcargs -> { - // // int setRealInputDerivatives(UInt[] scalarValueIndices, UInt nvr, int[] order, ref real[] derivatives); - // checkArgLength(fcargs, 4); - // long elementsToUse = getUint(fcargs.get(1)); - // - // - // long[] scalarValueIndices = - // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) - // .toArray(); - // - // int[] orders = - // getArrayValue(fcargs.get(2), Optional.of(elementsToUse), NumericValue.class).stream().mapToInt(NumericValue::intValue).toArray(); - // - // double[] values = - // getArrayValue(fcargs.get(3), Optional.of(elementsToUse), RealValue.class).stream().mapToDouble(RealValue::getValue).toArray(); - // - // try { - // Fmi2Status res = instance.setRealInputDerivatives(scalarValueIndices, orders, values); - // return new IntegerValue(res.value); - // } catch (FmuInvocationException e) { - // throw new InterpreterException(e); - // } - // - // }) - // ) - checkRequiredFunctions(module, functions); - - return new Fmu3InstanceValue(functions, instance, fmuLogOutputStream); - } - - private static Value status2IntValue(Fmi3Status res) { - switch (res) { - - case OK: - return new IntegerValue(0); - case Warning: - return new IntegerValue(1); - case Discard: - return new IntegerValue(2); - case Error: - return new IntegerValue(3); - case Fatal: - return new IntegerValue(4); - } - return null; - } - - private static Map createGetSetMembers(IFmi3Instance instance) throws NoSuchMethodException { - Map componentMembers = new HashMap<>(); - - Map methodTypeMapping = new HashMap<>() {{ - put("getFloat32", TP.Float); - put("getFloat64", TP.Real); - put("getInt8", TP.Byte); - put("getUInt8", TP.Byte); - put("getInt16", TP.Short); - put("getUInt16", TP.Short); - put("getInt32", TP.Int); - put("getUInt32", TP.Int); - put("getInt64", TP.Long); - put("getUInt64", TP.Long); - put("getBoolean", TP.Bool); - put("getString", TP.String); - put("setFloat32", TP.Float); - put("setFloat64", TP.Real); - put("setInt8", TP.Byte); - put("setUInt8", TP.Byte); - put("setInt16", TP.Short); - put("setUInt16", TP.Short); - put("setInt32", TP.Int); - put("setUInt32", TP.Int); - put("setInt64", TP.Long); - put("setUInt64", TP.Long); - put("setBoolean", TP.Bool); - put("setString", TP.String); - - - }}; - - - for (Map.Entry method : methodTypeMapping.entrySet()) { - if (method.getKey().startsWith("get")) { - - Method m = instance.getClass().getMethod(method.getKey(), long[].class); - - componentMembers.put(method.getKey(), new FunctionValue.ExternalFunctionValue(fcargs -> { - - checkArgLength(fcargs, 2); - Value scalarValue = fcargs.get(0); - Value valuesValue = fcargs.get(1); - - if (!(valuesValue instanceof UpdatableValue)) { - throw new InterpreterException("value not a reference value"); - } - // long elementsToUse = getUint(fcargs.get(1)); - - // long[] scalarValueIndices = - // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) - // .toArray(); - - long[] scalarValueIndices = getArrayValue(scalarValue, Optional.empty(), NumericValue.class).stream() - .mapToLong(NumericValue::longValue).toArray(); - - long elementsToUse = scalarValueIndices.length; - - try { - @SuppressWarnings("rawtypes") - FmuResult res = (FmuResult) m.invoke(instance, scalarValueIndices);// instance.getFloat64(scalarValueIndices); - - if (res.status == Fmi3Status.OK) { - UpdatableValue ref = (UpdatableValue) valuesValue; - - List values = null; - switch (method.getValue()) { - - case Bool: - values = Arrays.stream(ArrayUtils.toObject((boolean[]) res.result)).limit(elementsToUse).map(BooleanValue::new) - .collect(Collectors.toList()); - break; - case Byte: - values = Arrays.stream(ArrayUtils.toObject((byte[]) res.result)).limit(elementsToUse).map(ByteValue::new) - .collect(Collectors.toList()); - break; - case Float: - values = Arrays.stream(ArrayUtils.toObject((float[]) res.result)).limit(elementsToUse).map(FloatValue::new) - .collect(Collectors.toList()); - break; - case Int: - values = Arrays.stream(ArrayUtils.toObject((int[]) res.result)).limit(elementsToUse).map(IntegerValue::new) - .collect(Collectors.toList()); - break; - case Long: - values = Arrays.stream(ArrayUtils.toObject((long[]) res.result)).limit(elementsToUse).map(LongValue::new) - .collect(Collectors.toList()); - break; - case Real: - values = Arrays.stream(ArrayUtils.toObject((double[]) res.result)).limit(elementsToUse).map(RealValue::new) - .collect(Collectors.toList()); - break; - case Short: - values = Arrays.stream(ArrayUtils.toObject((short[]) res.result)).limit(elementsToUse).map(ShortValue::new) - .collect(Collectors.toList()); - break; - case String: - values = Arrays.stream((String[]) res.result).limit(elementsToUse).map(StringValue::new) - .collect(Collectors.toList()); - break; - } - - - ref.setValue(new ArrayValue<>(values)); - } - - return status2IntValue(res.status); - - } catch (IllegalAccessException | InvocationTargetException e) { - throw new InterpreterException(e); - } - - - })); - - } else { - - Class argClass = null; - - switch (method.getValue()) { - - case Bool: - argClass = boolean[].class; - break; - case Byte: - argClass = byte[].class; - break; - case Float: - argClass = float[].class; - break; - case Int: - argClass = int[].class; - break; - case Long: - argClass = long[].class; - break; - case Real: - argClass = double[].class; - break; - case Short: - argClass = short[].class; - break; - case String: - argClass = String[].class; - break; - } - - Method m = instance.getClass().getMethod(method.getKey(), long[].class, argClass); - - componentMembers.put(method.getKey(), new FunctionValue.ExternalFunctionValue(fcargs -> { - checkArgLength(fcargs, 2); - // long elementsToUse = getUint(fcargs.get(1)); - // long[] scalarValueIndices = - // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) - // .toArray(); - Value scalarValue = fcargs.get(0); - Value valuesValue = fcargs.get(1); - - long[] scalarValueIndices = getArrayValue(scalarValue, Optional.empty(), NumericValue.class).stream() - .mapToLong(NumericValue::longValue).toArray(); - - long elementsToUse = scalarValueIndices.length; - - //extract values - Object values = null; - - switch (method.getValue()) { - - case Bool: - values = ArrayUtils.toPrimitive( - getArrayValue(valuesValue, Optional.of(elementsToUse), BooleanValue.class).stream().map(BooleanValue::getValue) - .collect(Collectors.toList()).toArray(new Boolean[]{})); - break; - case Byte: - //todo change native type to use int as byte us unsigned - values = ArrayUtils.toPrimitive( - getArrayValue(valuesValue, Optional.of(elementsToUse), ByteValue.class).stream().map(ByteValue::getValue) - .map(v -> v & 0x00ff).map(Integer::byteValue).collect(Collectors.toList()).toArray(new Byte[]{})); - break; - case Float: - values = ArrayUtils.toPrimitive( - getArrayValue(valuesValue, Optional.of(elementsToUse), FloatValue.class).stream().map(FloatValue::getValue) - .collect(Collectors.toList()).toArray(new Float[]{})); - break; - case Int: - values = ArrayUtils.toPrimitive( - getArrayValue(valuesValue, Optional.of(elementsToUse), IntegerValue.class).stream().map(IntegerValue::getValue) - .collect(Collectors.toList()).toArray(new Integer[]{})); - break; - case Long: - values = ArrayUtils.toPrimitive( - getArrayValue(valuesValue, Optional.of(elementsToUse), LongValue.class).stream().map(LongValue::getValue) - .collect(Collectors.toList()).toArray(new Long[]{})); - break; - case Real: - values = getArrayValue(valuesValue, Optional.of(elementsToUse), NumericValue.class).stream().limit(elementsToUse) - .mapToDouble(NumericValue::realValue).toArray(); - break; - case Short: - values = ArrayUtils.toPrimitive( - getArrayValue(valuesValue, Optional.of(elementsToUse), ShortValue.class).stream().map(ShortValue::getValue) - .collect(Collectors.toList()).toArray(new Short[]{})); - break; - case String: - values = getArrayValue(valuesValue, Optional.of(elementsToUse), StringValue.class).stream().map(StringValue::getValue) - .collect(Collectors.toList()).toArray(new String[]{}); - break; - } - - try { - Fmi3Status res = (Fmi3Status) m.invoke(instance, scalarValueIndices, values);// instance.setBoolean().setReals - // (scalarValueIndices, values); - return new IntegerValue(res.value); - } catch (IllegalAccessException | InvocationTargetException e) { - throw new InterpreterException(e); - } - - })); - } - } - - /* -int getFloat32(uint valueReferences[], int nValueReferences, float values[], int nValues); -int getFloat64(uint valueReferences[], int nValueReferences, real values[], int nValues); -int getInt8(uint valueReferences[], int nValueReferences, byte values[], int nValues); -int getUInt8(uint valueReferences[], int nValueReferences, byte values[], int nValues); -int getInt16(uint valueReferences[], int nValueReferences, short values[], int nValues); -int getUInt16(uint valueReferences[], int nValueReferences, short values[], int nValues); -int getInt32(uint valueReferences[], int nValueReferences, int values[], int nValues); -int getUInt32(uint valueReferences[], int nValueReferences, int values[], int nValues); -int getInt64(uint valueReferences[], int nValueReferences, long values[], int nValues); -int getUInt64(uint valueReferences[], int nValueReferences, long values[], int nValues); -int getBoolean(uint valueReferences[], int nValueReferences, bool values[], int nValues); -int getString(uint valueReferences[], int nValueReferences, string values[], int nValues); -int setFloat32(uint valueReferences[], int nValueReferences, float values[], int nValues); -int setFloat64(uint valueReferences[], int nValueReferences, real values[], int nValues); -int setInt8(uint valueReferences[], int nValueReferences, byte values[], int nValues); -int setUInt8(uint valueReferences[], int nValueReferences, byte values[], int nValues); -int setInt16(uint valueReferences[], int nValueReferences, short values[], int nValues); -int setUInt16(uint valueReferences[], int nValueReferences, short values[], int nValues); -int setInt32(uint valueReferences[], int nValueReferences, int values[], int nValues); -int setUInt32(uint valueReferences[], int nValueReferences, int values[], int nValues); -int setInt64(uint valueReferences[], int nValueReferences, long values[], int nValues); -int setUInt64(uint valueReferences[], int nValueReferences, long values[], int nValues); -int setBoolean(uint valueReferences[], int nValueReferences, bool values[], int nValues); -int setString(uint valueReferences[], int nValueReferences, string values[], int nValues); - */ - - - return componentMembers; - - } - - public Value createFmiValue(String path, String guid) { - try { - long startExecTime = System.nanoTime(); - - URI uri = URI.create(path); - if (!uri.isAbsolute()) { - uri = new File(".").toURI().resolve(uri); - } - File file = new File(uri); - - final IFmi3Fmu fmu = new Fmu3(file); - - fmu.load(); - - Map functions = createFmuMembers(workingDirectory, guid, fmu); - - long stopTime = System.nanoTime(); - - System.out.println("Interpretation load took: " + (stopTime - startExecTime)); - - return new Fmu3Value(functions, fmu); - - } catch (IOException | FmuInvocationException | FmuMissingLibraryException e) { - - e.printStackTrace(); - return new NullValue(); - } catch (Exception e) { - e.printStackTrace(); - return new NullValue(); - } - } - - -} diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/Fmi3InterpreterAuto.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/Fmi3InterpreterAuto.java deleted file mode 100644 index 3c0507a7c..000000000 --- a/interpreter/src/main/java/org/intocps/maestro/interpreter/Fmi3InterpreterAuto.java +++ /dev/null @@ -1,1079 +0,0 @@ -package org.intocps.maestro.interpreter; - -import org.apache.commons.lang3.ArrayUtils; -import org.apache.logging.log4j.Level; -import org.apache.logging.log4j.core.Layout; -import org.apache.logging.log4j.core.impl.Log4jLogEvent; -import org.apache.logging.log4j.core.layout.PatternLayout; -import org.apache.logging.log4j.message.ParameterizedMessage; -import org.intocps.fmi.FmuInvocationException; -import org.intocps.fmi.FmuMissingLibraryException; -import org.intocps.fmi.jnifmuapi.fmi3.*; -import org.intocps.maestro.interpreter.external.TP; -import org.intocps.maestro.interpreter.values.*; -import org.intocps.maestro.interpreter.values.fmi.Fmu3InstanceValue; -import org.intocps.maestro.interpreter.values.fmi.Fmu3StateValue; -import org.intocps.maestro.interpreter.values.fmi.Fmu3Value; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.*; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.net.URI; -import java.nio.charset.StandardCharsets; -import java.util.*; -import java.util.stream.Collectors; - -import static org.intocps.maestro.interpreter.Fmi2Interpreter.*; - -public class Fmi3InterpreterAuto { - final static Logger logger = LoggerFactory.getLogger(Interpreter.class); - private final File workingDirectory; - - public Fmi3InterpreterAuto(File workingDirectory) { - - this.workingDirectory = workingDirectory; - } - - public static Double getDouble(Value value) { - - if (value == null || value instanceof NullValue) { - return null; - } - - value = value.deref(); - - if (value == null || value instanceof NullValue) { - return null; - } - - if (value instanceof RealValue) { - return ((RealValue) value).getValue(); - } - throw new InterpreterException("Value is not double"); - } - - public static UpdatableValue getUpdatable(Value v) { - if (!(v instanceof UpdatableValue)) { - throw new InterpreterException("value not a reference value"); - } - return (UpdatableValue) v; - } - - public static Map createFmuMembers(File workingDirectory, String guid, IFmi3Fmu fmu) { - Map functions = new HashMap<>(); - - functions.put("instantiateCoSimulation", new FunctionValue.ExternalFunctionValue(fargs -> { - - Fmi2Interpreter.checkArgLength(fargs, 6); - - String name = Fmi2Interpreter.getString(fargs.get(0)); - boolean visible = Fmi2Interpreter.getBool(fargs.get(1)); - boolean logginOn = Fmi2Interpreter.getBool(fargs.get(2)); - - boolean eventModeUsed = Fmi2Interpreter.getBool(fargs.get(3)); - boolean earlyReturnAllowed = Fmi2Interpreter.getBool(fargs.get(4)); - long[] requiredIntermediateVariables = - getArrayValue(fargs.get(5), Optional.empty(), NumericValue.class).stream().mapToLong(NumericValue::longValue).toArray(); - - try { - - long startInstantiateTime = System.nanoTime(); - - logger.debug(String.format("Loading native FMU. GUID: %s, NAME: %s", "" + guid, "" + name)); - - BufferedOutputStream fmuLogOutputStream = - workingDirectory == null ? null : new BufferedOutputStream(new FileOutputStream(new File(workingDirectory, name + ".log"))); - - final String formatter = "{} {} {} {}"; - String pattern = "%d{ISO8601} %-5p - %m%n"; - - Layout layout = PatternLayout.newBuilder().withPattern(pattern).withCharset(StandardCharsets.UTF_8).build();// - - ILogMessageCallback logCallback = (instanceName, status, category, message) -> { - logger.info("NATIVE: instance: '{}', status: '{}', category: '{}', message: {}", instanceName, status, category, message); - { - - if (fmuLogOutputStream == null) { - return; - } - - Log4jLogEvent.Builder builder = - Log4jLogEvent.newBuilder().setMessage(new ParameterizedMessage(formatter, category, status, instanceName, message)); - - - switch (status) { - case OK: - case Discard: - builder.setLevel(Level.INFO); - break; - case Error: - case Fatal: - builder.setLevel(Level.ERROR); - case Warning: - builder.setLevel(Level.WARN); - break; - default: - builder.setLevel(Level.TRACE); - break; - } - - try { - Log4jLogEvent event = builder.build(); - fmuLogOutputStream.write(layout.toByteArray(event)); - } catch (IOException e) { - e.printStackTrace(); - } - } - }; - IIntermediateUpdateCallback intermediateUpdateCallback = - (instanceEnvironment, intermediateUpdateTime, clocksTicked, intermediateVariableSetRequested, intermediateVariableGetAllowed, intermediateStepFinished, canReturnEarly) -> new IIntermediateUpdateCallback.IntermediateUpdateResponse( - false, intermediateUpdateTime); - IFmi3Instance instance = - fmu.instantiateCoSimulation(name, guid, visible, logginOn, eventModeUsed, earlyReturnAllowed, requiredIntermediateVariables, - logCallback, null); - - - if (instance == null) { - logger.debug("Instance instantiate failed"); - return new NullValue(); - } - long stopInstantiateTime = System.nanoTime(); - System.out.println("Interpretation instantiate took: " + (stopInstantiateTime - startInstantiateTime)); - - return getFmuInstanceValue(fmuLogOutputStream, instance); - - - } catch (IOException | NoSuchMethodException e) { - e.printStackTrace(); - } - - return null; - })); - - - functions.put("freeInstance", new FunctionValue.ExternalFunctionValue(fargs -> { - - fargs = fargs.stream().map(Value::deref).collect(Collectors.toList()); - - logger.debug("freeInstance"); - - if (fargs.size() != 1) { - throw new InterpreterException("Too few arguments"); - } - - if (!(fargs.get(0) instanceof Fmu3InstanceValue)) { - throw new InterpreterException("Argument must be an external module reference"); - } - - Fmu3InstanceValue component = (Fmu3InstanceValue) fargs.get(0); - - try { - OutputStream loggerOutputStream = component.getFmuLoggerOutputStream(); - if (loggerOutputStream != null) { - loggerOutputStream.close(); - } - component.getModule().freeInstance(); - } catch (IOException | FmuInvocationException e) { - e.printStackTrace(); - } - - - return new VoidValue(); - })); - - functions.put("unload", new FunctionValue.ExternalFunctionValue(fargs -> { - fargs = fargs.stream().map(Value::deref).collect(Collectors.toList()); - - logger.debug("unload"); - - if (fargs.size() != 0) { - throw new InterpreterException("Too many arguments"); - } - - try { - fmu.unLoad(); - } catch (FmuInvocationException e) { - e.printStackTrace(); - } - - return new VoidValue(); - })); - return functions; - } - - private static Value getFmuInstanceValue(BufferedOutputStream fmuLogOutputStream, IFmi3Instance instance) throws NoSuchMethodException { - - //populate component functions - - - Map componentMembers = new HashMap<>(createGetSetMembers(instance)); - - //void methods - componentMembers.put("freeInstance", new FunctionValue.ExternalFunctionValue(fcargs -> { - - checkArgLength(fcargs, 0); - try { - instance.freeInstance(); - return new VoidValue(); - } catch (FmuInvocationException e) { - throw new InterpreterException(e); - } - - })); - - String[] voidStatusMethods = - new String[]{"exitInitializationMode", "enterEventMode", "terminate", "reset", "enterConfigurationMode", "exitConfigurationMode", - "evaluateDiscreteStates", "enterContinuousTimeMode", "enterStepMode"}; - - for (String methodName : voidStatusMethods) { - Method method = instance.getClass().getMethod(methodName); - - componentMembers.put(methodName, new FunctionValue.ExternalFunctionValue(fcargs -> { - - checkArgLength(fcargs, 0); - - - try { - Fmi3Status res = (Fmi3Status) method.invoke(instance); - return status2IntValue(res); - } catch (IllegalAccessException | InvocationTargetException e) { - throw new InterpreterException(e); - } - })); - - } - - - - /* - -int setDebugLogging(bool loggingOn, string categories[]); -int enterInitializationMode(bool toleranceDefined, real tolerance, real startTime, bool stopTimeDefined, - -int getBinary(uint valueReferences[], int nValueReferences, byte values[][], int nValues); -int setBinary(uint valueReferences[], int nValueReferences, long sizes[], byte array_name[][], int nValues); -int getNumberOfVariableDependencies(uint valueReference, out int nDependencies); -int getVariableDependencies(uint dependent, int elementIndicesOfDependent[], uint independents[], -int getFMUState(out FMUS3tate FMUState); -int setFMUState(FMUS3tate FMUState); -int freeFMUState(out FMUS3tate FMUState); -int getDirectionalDerivative(uint unknowns[], int nUnknowns, uint knowns[], int nKnowns, real seed[], int nSeed, -int getAdjointDerivative(uint unknowns[], int nUnknowns, uint knowns[], int nKnowns, real seed[], int nSeed, -int getClock(uint valueReferences[], int nValueReferences, bool values[]); -int setClock(uint valueReferences[], int nValueReferences, bool values[]); -int getIntervalDecimal(uint valueReferences[], int nValueReferences, real intervals[], -int getIntervalFraction(uint valueReferences[], int nValueReferences, uint intervalCounters[], uint resolutions[], -int getShiftDecimal(uint valueReferences[], int nValueReferences, real shifts[]); -int getShiftFraction(uint valueReferences[], int nValueReferences, uint shiftCounters[], uint resolutions[]); -int setIntervalDecimal(uint valueReferences[], int nValueReferences, real interval[]); -int setIntervalFraction(uint valueReferences[], int nValueReferences, uint intervalCounter[], uint resolution[]); -int setShiftDecimal(uint valueReferences[], int nValueReferences, real shifts[]); -int setShiftFraction(uint valueReferences[], int nValueReferences, uint counters[], uint resolutions[]); -int updateDiscreteStates(bool[] discreteStatesNeedUpdate, bool[] terminateSimulation, -int completedIntegratorStep(bool nosetFMUStatePriorToCurrentPoint, bool[] enterEventMode, -int setTime(real time); -int setContinuousStates(real continuousStates[], int nContinuousStates); -int getContinuousStateDerivatives(real derivatives[], int nContinuousStates); -int getEventIndicators(real eventIndicators[], int nEventIndicators); -int getContinuousStates(real continuousStates[], int nContinuousStates); -int getNominalsOfContinuousStates(real nominals[], int nContinuousStates); -int getNumberOfEventIndicators(int[] nEventIndicators); -int getNumberOfContinuousStates(int[] nContinuousStates); -int getOutputDerivatives(uint valueReferences[], int nValueReferences, int orders[], real values[], int nValues); -int doStep(real currentCommunicationPoint, real communicationStepSize, bool nosetFMUStatePriorToCurrentPoint, -int activateModelPartition(uint clockReference, real activationTime); - - */ - - - componentMembers.put("setDebugLogging", new FunctionValue.ExternalFunctionValue(fcargs -> { - - checkArgLength(fcargs, 3); - - boolean debugLogginOn = getBool(fcargs.get(0)); - // int arraySize = getInteger(fcargs.get(1)); - List categories = getArrayValue(fcargs.get(2), StringValue.class); - - try { - Fmi3Status res = instance.setDebugLogging(debugLogginOn, categories.stream().map(StringValue::getValue).toArray(String[]::new)); - return new IntegerValue(res.value); - } catch (FmuInvocationException e) { - throw new InterpreterException(e); - } - })); - - // componentMembers.put("setupExperiment", new FunctionValue.ExternalFunctionValue(fcargs -> { - // - // checkArgLength(fcargs, 5); - // - // boolean toleranceDefined = getBool(fcargs.get(0)); - // double tolerance = getDouble(fcargs.get(1)); - // double startTime = getDouble(fcargs.get(2)); - // boolean stopTimeDefined = getBool(fcargs.get(3)); - // double stopTime = getDouble(fcargs.get(4)); - // try { - // Fmi2Status res = instance.setupExperiment(toleranceDefined, tolerance, startTime, stopTimeDefined, stopTime); - // return new IntegerValue(res.value); - // } catch (FmuInvocationException e) { - // throw new InterpreterException(e); - // } - // })); - componentMembers.put("enterInitializationMode", new FunctionValue.ExternalFunctionValue(fcargs -> { - - checkArgLength(fcargs, 3); - - Double tolerance = getDouble(fcargs.get(0)); - double startTime = getDouble(fcargs.get(1)); - Double stopTime = getDouble(fcargs.get(2)); - - - try { - Fmi3Status res = instance.enterInitializationMode(tolerance, startTime, stopTime); - return new IntegerValue(res.value); - } catch (FmuInvocationException e) { - throw new InterpreterException(e); - } - - })); - // componentMembers.put("exitInitializationMode", new FunctionValue.ExternalFunctionValue(fcargs -> { - // checkArgLength(fcargs, 0); - // try { - // Fmi3Status res = instance.exitInitializationMode(); - // return new IntegerValue(res.value); - // } catch (FmuInvocationException e) { - // throw new InterpreterException(e); - // } - // })); - // componentMembers.put("setReal", new FunctionValue.ExternalFunctionValue(fcargs -> { - // checkArgLength(fcargs, 3); - // long elementsToUse = getUint(fcargs.get(1)); - // long[] scalarValueIndices = - // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) - // .toArray(); - // double[] values = getArrayValue(fcargs.get(2), Optional.of(elementsToUse), NumericValue.class).stream().limit(elementsToUse) - // .mapToDouble(NumericValue::realValue).toArray(); - // - // try { - // Fmi3Status res = instance.setReals(scalarValueIndices, values); - // return new IntegerValue(res.value); - // } catch (InvalidParameterException | FmiInvalidNativeStateException e) { - // throw new InterpreterException(e); - // } - // - // })); - // componentMembers.put("getReal", new FunctionValue.ExternalFunctionValue(fcargs -> { - // - // checkArgLength(fcargs, 3); - // - // if (!(fcargs.get(2) instanceof UpdatableValue)) { - // throw new InterpreterException("value not a reference value"); - // } - // long elementsToUse = getUint(fcargs.get(1)); - // - // long[] scalarValueIndices = - // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) - // .toArray(); - // - // - // try { - // org.intocps.fmi.FmuResult res = instance.getReal(scalarValueIndices); - // - // if (res.status == Fmi2Status.OK) { - // UpdatableValue ref = (UpdatableValue) fcargs.get(2); - // - // List values = Arrays.stream(ArrayUtils.toObject(res.result)).limit(elementsToUse).map(d -> new RealValue(d)) - // .collect(Collectors.toList()); - // - // ref.setValue(new ArrayValue<>(values)); - // } - // - // - // return new IntegerValue(res.status.value); - // - // } catch (FmuInvocationException e) { - // throw new InterpreterException(e); - // } - // - // - // })); - // componentMembers.put("setInteger", new FunctionValue.ExternalFunctionValue(fcargs -> { - // checkArgLength(fcargs, 3); - // long elementsToUse = getUint(fcargs.get(1)); - // long[] scalarValueIndices = - // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) - // .toArray(); - // int[] values = - // getArrayValue(fcargs.get(2), Optional.of(elementsToUse), IntegerValue.class).stream().mapToInt(IntegerValue::getValue).toArray(); - // - // try { - // Fmi2Status res = instance.setIntegers(scalarValueIndices, values); - // return new IntegerValue(res.value); - // } catch (InvalidParameterException | FmiInvalidNativeStateException e) { - // throw new InterpreterException(e); - // } - // })); - // componentMembers.put("getInteger", new FunctionValue.ExternalFunctionValue(fcargs -> { - // - // checkArgLength(fcargs, 3); - // long elementsToUse = getUint(fcargs.get(1)); - // - // if (!(fcargs.get(2) instanceof UpdatableValue)) { - // throw new InterpreterException("value not a reference value"); - // } - // - // long[] scalarValueIndices = - // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) - // .toArray(); - // - // - // try { - // org.intocps.fmi.FmuResult res = instance.getInteger(scalarValueIndices); - // - // if (res.status == Fmi2Status.OK) { - // UpdatableValue ref = (UpdatableValue) fcargs.get(2); - // - // List values = Arrays.stream(ArrayUtils.toObject(res.result)).limit(elementsToUse).map(i -> new IntegerValue(i)) - // .collect(Collectors.toList()); - // - // ref.setValue(new ArrayValue<>(values)); - // } - // - // - // return new IntegerValue(res.status.value); - // - // } catch (FmuInvocationException e) { - // throw new InterpreterException(e); - // } - // - // - // })); - // componentMembers.put("setBoolean", new FunctionValue.ExternalFunctionValue(fcargs -> { - // - // checkArgLength(fcargs, 3); - // long elementsToUse = getUint(fcargs.get(1)); - // long[] scalarValueIndices = - // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) - // .toArray(); - // boolean[] values = ArrayUtils.toPrimitive( - // getArrayValue(fcargs.get(2), Optional.of(elementsToUse), BooleanValue.class).stream().map(BooleanValue::getValue) - // .collect(Collectors.toList()).toArray(new Boolean[]{})); - // - // try { - // Fmi2Status res = instance.setBooleans(scalarValueIndices, values); - // return new IntegerValue(res.value); - // } catch (InvalidParameterException | FmiInvalidNativeStateException e) { - // throw new InterpreterException(e); - // } - // })); - // componentMembers.put("getBoolean", new FunctionValue.ExternalFunctionValue(fcargs -> { - // - // checkArgLength(fcargs, 3); - // - // if (!(fcargs.get(2) instanceof UpdatableValue)) { - // throw new InterpreterException("value not a reference value"); - // } - // - // long elementsToUse = getUint(fcargs.get(1)); - // - // - // long[] scalarValueIndices = - // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) - // .toArray(); - // - // - // try { - // org.intocps.fmi.FmuResult res = instance.getBooleans(scalarValueIndices); - // - // if (res.status == Fmi2Status.OK) { - // UpdatableValue ref = (UpdatableValue) fcargs.get(2); - // - // List values = - // Arrays.stream(ArrayUtils.toObject(res.result)).limit(elementsToUse).map(BooleanValue::new).collect(Collectors.toList()); - // - // ref.setValue(new ArrayValue<>(values)); - // } - // - // - // return new IntegerValue(res.status.value); - // - // } catch (FmuInvocationException e) { - // throw new InterpreterException(e); - // } - // - // })); - // componentMembers.put("setString", new FunctionValue.ExternalFunctionValue(fcargs -> { - // - // checkArgLength(fcargs, 3); - // long elementsToUse = getUint(fcargs.get(1)); - // - // long[] scalarValueIndices = - // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) - // .toArray(); - // String[] values = getArrayValue(fcargs.get(2), Optional.of(elementsToUse), StringValue.class).stream().map(StringValue::getValue) - // .collect(Collectors.toList()).toArray(new String[]{}); - // - // try { - // Fmi2Status res = instance.setStrings(scalarValueIndices, values); - // return new IntegerValue(res.value); - // } catch (InvalidParameterException | FmiInvalidNativeStateException e) { - // throw new InterpreterException(e); - // } - // - // })); - // componentMembers.put("getString", new FunctionValue.ExternalFunctionValue(fcargs -> { - // - // checkArgLength(fcargs, 3); - // - // if (!(fcargs.get(2) instanceof UpdatableValue)) { - // throw new InterpreterException("value not a reference value"); - // } - // - // - // long elementsToUse = getUint(fcargs.get(1)); - // - // - // long[] scalarValueIndices = - // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) - // .toArray(); - // - // - // try { - // org.intocps.fmi.FmuResult res = instance.getStrings(scalarValueIndices); - // - // if (res.status == Fmi2Status.OK) { - // UpdatableValue ref = (UpdatableValue) fcargs.get(2); - // - // List values = Arrays.stream(res.result).limit(elementsToUse).map(StringValue::new).collect(Collectors.toList()); - // - // ref.setValue(new ArrayValue<>(values)); - // } - // - // - // return new IntegerValue(res.status.value); - // - // } catch (FmuInvocationException e) { - // throw new InterpreterException(e); - // } - // - // - // })); - componentMembers.put("doStep", new FunctionValue.ExternalFunctionValue(fcargs -> { - - checkArgLength(fcargs, 7); - - //in - double currentCommunicationPoint = getDouble(fcargs.get(0)); - double communicationStepSize = getDouble(fcargs.get(1)); - boolean noSetFMUStatePriorToCurrentPoint = getBool(fcargs.get(2)); - //out - - UpdatableValue eventHandlingNeeded = getUpdatable(fcargs.get(3)); - UpdatableValue terminateSimulation = getUpdatable(fcargs.get(4)); - UpdatableValue earlyReturn = getUpdatable(fcargs.get(5)); - UpdatableValue lastSuccessfulTime = getUpdatable(fcargs.get(6)); - /*int doStep(real currentCommunicationPoint, real communicationStepSize, bool nosetFMUStatePriorToCurrentPoint, - out bool eventHandlingNeeded,out bool terminateSimulation,out bool earlyReturn,out real lastSuccessfulTime);*/ - - try { - FmuResult res = - instance.doStep(currentCommunicationPoint, communicationStepSize, noSetFMUStatePriorToCurrentPoint); - - if (res.status == Fmi3Status.OK) { - eventHandlingNeeded.setValue(new BooleanValue(res.result.isEventHandlingNeeded())); - terminateSimulation.setValue(new BooleanValue(res.result.isTerminateSimulation())); - earlyReturn.setValue(new BooleanValue(res.result.isEarlyReturn())); - lastSuccessfulTime.setValue(new RealValue(res.result.getLastSuccessfulTime())); - } - return new IntegerValue(res.status.value); - } catch (FmuInvocationException e) { - throw new InterpreterException(e); - } - })); - - componentMembers.put("terminate", new FunctionValue.ExternalFunctionValue(fcargs -> { - checkArgLength(fcargs, 0); - try { - Fmi3Status res = instance.terminate(); - return new IntegerValue(res.value); - } catch (FmuInvocationException e) { - throw new InterpreterException(e); - } - })); - - componentMembers.put("setState", new FunctionValue.ExternalFunctionValue(fcargs -> { - checkArgLength(fcargs, 1); - - Value v = fcargs.get(0).deref(); - - if (v instanceof Fmu3StateValue) { - try { - Fmu3StateValue stateValue = (Fmu3StateValue) v; - Fmi3Status res = instance.setState(stateValue.getModule()); - return new IntegerValue(res.value); - } catch (FmuInvocationException e) { - throw new InterpreterException(e); - } - } - - throw new InterpreterException("Invalid value"); - })); - componentMembers.put("getState", new FunctionValue.ExternalFunctionValue(fcargs -> { - - checkArgLength(fcargs, 1); - - if (!(fcargs.get(0) instanceof UpdatableValue)) { - throw new InterpreterException("value not a reference value"); - } - - - try { - - FmuResult res = instance.getState(); - - if (res.status == Fmi3Status.OK) { - UpdatableValue ref = (UpdatableValue) fcargs.get(0); - ref.setValue(new Fmu3StateValue(res.result)); - } - - - return new IntegerValue(res.status.value); - - } catch (FmuInvocationException e) { - throw new InterpreterException(e); - } - - - })); - componentMembers.put("freeState", new FunctionValue.ExternalFunctionValue(fcargs -> { - - checkArgLength(fcargs, 1); - - Value v = fcargs.get(0).deref(); - - if (v instanceof Fmu3StateValue) { - try { - Fmu3StateValue stateValue = (Fmu3StateValue) v; - Fmi3Status res = instance.freeState(stateValue.getModule()); - return new IntegerValue(res.value); - } catch (FmuInvocationException e) { - throw new InterpreterException(e); - } - } - - throw new InterpreterException("Invalid value"); - - - })); - - // componentMembers.put("getRealStatus", new FunctionValue.ExternalFunctionValue(fcargs -> { - // - // checkArgLength(fcargs, 2); - // - // if (!(fcargs.get(1) instanceof UpdatableValue)) { - // throw new InterpreterException("value not a reference value"); - // } - // - // Value kindValue = fcargs.get(0).deref(); - // - // if (!(kindValue instanceof IntegerValue)) { - // throw new InterpreterException("Invalid kind value: " + kindValue); - // } - // - // int kind = ((IntegerValue) kindValue).getValue(); - // - // Fmi2StatusKind kindEnum = Arrays.stream(Fmi2StatusKind.values()).filter(v -> v.value == kind).findFirst().orElse(null); - // - // try { - // org.intocps.fmi.FmuResult res = instance.getRealStatus(kindEnum); - // - // if (res.status == Fmi2Status.OK) { - // UpdatableValue ref = (UpdatableValue) fcargs.get(1); - // - // ref.setValue(new RealValue(res.result)); - // } - // - // - // return new IntegerValue(res.status.value); - // - // } catch (FmuInvocationException e) { - // throw new InterpreterException(e); - // } - // - // - // })); - // - // componentMembers.put("getRealOutputDerivatives", new FunctionValue.ExternalFunctionValue(fcargs -> { - // // int getRealOutputDerivatives(long[] scalarValueIndices, UInt nvr, int[] order, ref double[] derivatives); - // checkArgLength(fcargs, 4); - // - // if (!(fcargs.get(3) instanceof UpdatableValue)) { - // throw new InterpreterException("value not a reference value"); - // } - // - // long elementsToUse = getUint(fcargs.get(1)); - // - // - // long[] scalarValueIndices = - // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) - // .toArray(); - // - // int[] orders = - // getArrayValue(fcargs.get(2), Optional.of(elementsToUse), NumericValue.class).stream().mapToInt(NumericValue::intValue).toArray(); - // - // try { - // FmuResult res = instance.getRealOutputDerivatives(scalarValueIndices, orders); - // - // if (res.status == Fmi2Status.OK) { - // UpdatableValue ref = (UpdatableValue) fcargs.get(3); - // - // List values = Arrays.stream(ArrayUtils.toObject(res.result)).limit(elementsToUse).map(d -> new RealValue(d)) - // .collect(Collectors.toList()); - // - // ref.setValue(new ArrayValue<>(values)); - // } - // - // - // return new IntegerValue(res.status.value); - // - // } catch (FmuInvocationException e) { - // throw new InterpreterException(e); - // } - // - // - // })); - // - // componentMembers.put("setRealInputDerivatives", new FunctionValue.ExternalFunctionValue(fcargs -> { - // // int setRealInputDerivatives(UInt[] scalarValueIndices, UInt nvr, int[] order, ref real[] derivatives); - // checkArgLength(fcargs, 4); - // long elementsToUse = getUint(fcargs.get(1)); - // - // - // long[] scalarValueIndices = - // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) - // .toArray(); - // - // int[] orders = - // getArrayValue(fcargs.get(2), Optional.of(elementsToUse), NumericValue.class).stream().mapToInt(NumericValue::intValue).toArray(); - // - // double[] values = - // getArrayValue(fcargs.get(3), Optional.of(elementsToUse), RealValue.class).stream().mapToDouble(RealValue::getValue).toArray(); - // - // try { - // Fmi2Status res = instance.setRealInputDerivatives(scalarValueIndices, orders, values); - // return new IntegerValue(res.value); - // } catch (FmuInvocationException e) { - // throw new InterpreterException(e); - // } - // - // }) - // ) - - - return new Fmu3InstanceValue(componentMembers, instance, fmuLogOutputStream); - } - - private static Value status2IntValue(Fmi3Status res) { - switch (res) { - - case OK: - return new IntegerValue(0); - case Warning: - return new IntegerValue(1); - case Discard: - return new IntegerValue(2); - case Error: - return new IntegerValue(3); - case Fatal: - return new IntegerValue(4); - } - return null; - } - - private static Map createGetSetMembers(IFmi3Instance instance) throws NoSuchMethodException { - Map componentMembers = new HashMap<>(); - - Map methodTypeMapping = new HashMap<>() {{ - put("getFloat32", TP.Float); - put("getFloat64", TP.Real); - put("getInt8", TP.Byte); - put("getUInt8", TP.Byte); - put("getInt16", TP.Short); - put("getUInt16", TP.Short); - put("getInt32", TP.Int); - put("getUInt32", TP.Int); - put("getInt64", TP.Long); - put("getUInt64", TP.Long); - put("getBoolean", TP.Bool); - put("getString", TP.String); - put("setFloat32", TP.Float); - put("setFloat64", TP.Real); - put("setInt8", TP.Byte); - put("setUInt8", TP.Byte); - put("setInt16", TP.Short); - put("setUInt16", TP.Short); - put("setInt32", TP.Int); - put("setUInt32", TP.Int); - put("setInt64", TP.Long); - put("setUInt64", TP.Long); - put("setBoolean", TP.Bool); - put("setString", TP.String); - - - }}; - - - for (Map.Entry method : methodTypeMapping.entrySet()) { - if (method.getKey().startsWith("get")) { - - Method m = instance.getClass().getMethod(method.getKey(), long[].class); - - componentMembers.put(method.getKey(), new FunctionValue.ExternalFunctionValue(fcargs -> { - - checkArgLength(fcargs, 2); - Value scalarValue = fcargs.get(0); - Value valuesValue = fcargs.get(1); - - if (!(valuesValue instanceof UpdatableValue)) { - throw new InterpreterException("value not a reference value"); - } - // long elementsToUse = getUint(fcargs.get(1)); - - // long[] scalarValueIndices = - // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) - // .toArray(); - - long[] scalarValueIndices = - getArrayValue(scalarValue, Optional.empty(), NumericValue.class).stream().mapToLong(NumericValue::longValue).toArray(); - - long elementsToUse = scalarValueIndices.length; - - try { - @SuppressWarnings("rawtypes") - FmuResult res = (FmuResult) m.invoke(instance, scalarValueIndices);// instance.getFloat64(scalarValueIndices); - - if (res.status == Fmi3Status.OK) { - UpdatableValue ref = (UpdatableValue) valuesValue; - - List values = null; - switch (method.getValue()) { - - case Bool: - values = Arrays.stream(ArrayUtils.toObject((boolean[]) res.result)).limit(elementsToUse).map(BooleanValue::new) - .collect(Collectors.toList()); - break; - case Byte: - values = Arrays.stream(ArrayUtils.toObject((byte[]) res.result)).limit(elementsToUse).map(ByteValue::new) - .collect(Collectors.toList()); - break; - case Float: - values = Arrays.stream(ArrayUtils.toObject((float[]) res.result)).limit(elementsToUse).map(FloatValue::new) - .collect(Collectors.toList()); - break; - case Int: - values = Arrays.stream(ArrayUtils.toObject((int[]) res.result)).limit(elementsToUse).map(IntegerValue::new) - .collect(Collectors.toList()); - break; - case Long: - values = Arrays.stream(ArrayUtils.toObject((long[]) res.result)).limit(elementsToUse).map(LongValue::new) - .collect(Collectors.toList()); - break; - case Real: - values = Arrays.stream(ArrayUtils.toObject((double[]) res.result)).limit(elementsToUse).map(RealValue::new) - .collect(Collectors.toList()); - break; - case Short: - values = Arrays.stream(ArrayUtils.toObject((short[]) res.result)).limit(elementsToUse).map(ShortValue::new) - .collect(Collectors.toList()); - break; - case String: - values = Arrays.stream((String[]) res.result).limit(elementsToUse).map(StringValue::new) - .collect(Collectors.toList()); - break; - } - - - ref.setValue(new ArrayValue<>(values)); - } - - return status2IntValue(res.status); - - } catch (IllegalAccessException | InvocationTargetException e) { - throw new InterpreterException(e); - } - - - })); - - } else { - - Class argClass = null; - - switch (method.getValue()) { - - case Bool: - argClass = boolean[].class; - break; - case Byte: - argClass = byte[].class; - break; - case Float: - argClass = float[].class; - break; - case Int: - argClass = int[].class; - break; - case Long: - argClass = long[].class; - break; - case Real: - argClass = double[].class; - break; - case Short: - argClass = short[].class; - break; - case String: - argClass = String[].class; - break; - } - - Method m = instance.getClass().getMethod(method.getKey(), long[].class, argClass); - - componentMembers.put(method.getKey(), new FunctionValue.ExternalFunctionValue(fcargs -> { - checkArgLength(fcargs, 2); - // long elementsToUse = getUint(fcargs.get(1)); - // long[] scalarValueIndices = - // getArrayValue(fcargs.get(0), Optional.of(elementsToUse), NumericValue.class).stream().mapToLong(NumericValue::longValue) - // .toArray(); - Value scalarValue = fcargs.get(0); - Value valuesValue = fcargs.get(1); - - long[] scalarValueIndices = - getArrayValue(scalarValue, Optional.empty(), NumericValue.class).stream().mapToLong(NumericValue::longValue).toArray(); - - long elementsToUse = scalarValueIndices.length; - - //extract values - Object values = null; - - switch (method.getValue()) { - - case Bool: - values = ArrayUtils.toPrimitive( - getArrayValue(valuesValue, Optional.of(elementsToUse), BooleanValue.class).stream().map(BooleanValue::getValue) - .collect(Collectors.toList()).toArray(new Boolean[]{})); - break; - case Byte: - //todo change native type to use int as byte us unsigned - values = ArrayUtils.toPrimitive( - getArrayValue(valuesValue, Optional.of(elementsToUse), ByteValue.class).stream().map(ByteValue::getValue) - .map(v -> v & 0x00ff).map(Integer::byteValue).collect(Collectors.toList()).toArray(new Byte[]{})); - break; - case Float: - values = ArrayUtils.toPrimitive( - getArrayValue(valuesValue, Optional.of(elementsToUse), FloatValue.class).stream().map(FloatValue::getValue) - .collect(Collectors.toList()).toArray(new Float[]{})); - break; - case Int: - values = ArrayUtils.toPrimitive( - getArrayValue(valuesValue, Optional.of(elementsToUse), IntegerValue.class).stream().map(IntegerValue::getValue) - .collect(Collectors.toList()).toArray(new Integer[]{})); - break; - case Long: - values = ArrayUtils.toPrimitive( - getArrayValue(valuesValue, Optional.of(elementsToUse), LongValue.class).stream().map(LongValue::getValue) - .collect(Collectors.toList()).toArray(new Long[]{})); - break; - case Real: - values = getArrayValue(valuesValue, Optional.of(elementsToUse), NumericValue.class).stream().limit(elementsToUse) - .mapToDouble(NumericValue::realValue).toArray(); - break; - case Short: - values = ArrayUtils.toPrimitive( - getArrayValue(valuesValue, Optional.of(elementsToUse), ShortValue.class).stream().map(ShortValue::getValue) - .collect(Collectors.toList()).toArray(new Short[]{})); - break; - case String: - values = getArrayValue(valuesValue, Optional.of(elementsToUse), StringValue.class).stream().map(StringValue::getValue) - .collect(Collectors.toList()).toArray(new String[]{}); - break; - } - - try { - Fmi3Status res = (Fmi3Status) m.invoke(instance, scalarValueIndices, values);// instance.setBoolean().setReals - // (scalarValueIndices, values); - return new IntegerValue(res.value); - } catch (IllegalAccessException | InvocationTargetException e) { - throw new InterpreterException(e); - } - - })); - } - } - - /* -int getFloat32(uint valueReferences[], int nValueReferences, float values[], int nValues); -int getFloat64(uint valueReferences[], int nValueReferences, real values[], int nValues); -int getInt8(uint valueReferences[], int nValueReferences, byte values[], int nValues); -int getUInt8(uint valueReferences[], int nValueReferences, byte values[], int nValues); -int getInt16(uint valueReferences[], int nValueReferences, short values[], int nValues); -int getUInt16(uint valueReferences[], int nValueReferences, short values[], int nValues); -int getInt32(uint valueReferences[], int nValueReferences, int values[], int nValues); -int getUInt32(uint valueReferences[], int nValueReferences, int values[], int nValues); -int getInt64(uint valueReferences[], int nValueReferences, long values[], int nValues); -int getUInt64(uint valueReferences[], int nValueReferences, long values[], int nValues); -int getBoolean(uint valueReferences[], int nValueReferences, bool values[], int nValues); -int getString(uint valueReferences[], int nValueReferences, string values[], int nValues); -int setFloat32(uint valueReferences[], int nValueReferences, float values[], int nValues); -int setFloat64(uint valueReferences[], int nValueReferences, real values[], int nValues); -int setInt8(uint valueReferences[], int nValueReferences, byte values[], int nValues); -int setUInt8(uint valueReferences[], int nValueReferences, byte values[], int nValues); -int setInt16(uint valueReferences[], int nValueReferences, short values[], int nValues); -int setUInt16(uint valueReferences[], int nValueReferences, short values[], int nValues); -int setInt32(uint valueReferences[], int nValueReferences, int values[], int nValues); -int setUInt32(uint valueReferences[], int nValueReferences, int values[], int nValues); -int setInt64(uint valueReferences[], int nValueReferences, long values[], int nValues); -int setUInt64(uint valueReferences[], int nValueReferences, long values[], int nValues); -int setBoolean(uint valueReferences[], int nValueReferences, bool values[], int nValues); -int setString(uint valueReferences[], int nValueReferences, string values[], int nValues); - */ - - - return componentMembers; - - } - - public Value createFmiValue(String path, String guid) { - try { - long startExecTime = System.nanoTime(); - - URI uri = URI.create(path); - if (!uri.isAbsolute()) { - uri = new File(".").toURI().resolve(uri); - } - File file = new File(uri); - - final IFmi3Fmu fmu = new Fmu3(file); - - fmu.load(); - - Map functions = createFmuMembers(workingDirectory, guid, fmu); - - long stopTime = System.nanoTime(); - - System.out.println("Interpretation load took: " + (stopTime - startExecTime)); - return new Fmu3Value(functions, fmu); - - } catch (IOException | FmuInvocationException | FmuMissingLibraryException e) { - - e.printStackTrace(); - return new NullValue(); - } catch (Exception e) { - e.printStackTrace(); - return new NullValue(); - } - } - - -} diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/Fmi3LifecycleHandler.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/Fmi3LifecycleHandler.java index 5c07c967d..74933d041 100644 --- a/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/Fmi3LifecycleHandler.java +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/Fmi3LifecycleHandler.java @@ -3,9 +3,8 @@ import com.spencerwi.either.Either; import org.intocps.maestro.ast.AModuleDeclaration; import org.intocps.maestro.ast.analysis.AnalysisException; -import org.intocps.maestro.interpreter.DefaultExternalValueFactory; -import org.intocps.maestro.interpreter.Fmi3Interpreter; import org.intocps.maestro.interpreter.api.IValueLifecycleHandler; +import org.intocps.maestro.interpreter.extensions.fmi3.Fmi3Interpreter; import org.intocps.maestro.interpreter.values.FunctionValue; import org.intocps.maestro.interpreter.values.StringValue; import org.intocps.maestro.interpreter.values.Value; @@ -46,6 +45,6 @@ public Either instantiate(List args) { } catch (URISyntaxException e) { return Either.left(new AnalysisException("The path passed to load is not a URI", e)); } - return Either.right(new Fmi3Interpreter(workingDirectory,resolver).createFmiValue(path, guid)); + return Either.right(new Fmi3Interpreter(workingDirectory, resolver).createFmiValue(path, guid)); } } \ No newline at end of file diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/fmi3/Fmi3InstanceArgMapping.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/fmi3/Fmi3InstanceArgMapping.java new file mode 100644 index 000000000..a3b342df6 --- /dev/null +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/fmi3/Fmi3InstanceArgMapping.java @@ -0,0 +1,63 @@ +package org.intocps.maestro.interpreter.extensions.fmi3; + +import org.intocps.maestro.interpreter.external.ExternalReflectCallHelper; +import org.intocps.maestro.interpreter.external.IArgMapping; +import org.intocps.maestro.interpreter.values.ExternalModuleValue; +import org.intocps.maestro.interpreter.values.Value; + +import java.util.Map; + +class Fmi3InstanceArgMapping implements IArgMapping { + @Override + public int getDimension() { + return 1; + } + + @Override + public long[] getLimits() { + return null; + } + + @Override + public ExternalReflectCallHelper.ArgMapping.InOut getDirection() { + return ExternalReflectCallHelper.ArgMapping.InOut.Input; + } + + @Override + public void setDirection(ExternalReflectCallHelper.ArgMapping.InOut direction) { + + } + + @Override + public Object map(Value v) { + if (v instanceof ExternalModuleValue) { + return ((ExternalModuleValue) v).getModule(); + } + return null; + } + + @Override + public void mapOut(Value original, Object value) { + throw new RuntimeException("This is only for input so should not be called"); + } + + @Override + public Value mapOut(Object value, Map outputThroughReturn) { + return new ExternalModuleValue<>(null, value) {}; + } + + @Override + public Class getType() { + return Object.class; + } + + @Override + public String getDescriptiveName() { + return "FMI3Instance"; + } + + @Override + public String getDefaultTestValue() { + return "null"; + } +} diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/fmi3/Fmi3Interpreter.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/fmi3/Fmi3Interpreter.java new file mode 100644 index 000000000..7f80dfbdf --- /dev/null +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/fmi3/Fmi3Interpreter.java @@ -0,0 +1,698 @@ +package org.intocps.maestro.interpreter.extensions.fmi3; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.core.Layout; +import org.apache.logging.log4j.core.impl.Log4jLogEvent; +import org.apache.logging.log4j.core.layout.PatternLayout; +import org.apache.logging.log4j.message.ParameterizedMessage; +import org.intocps.fmi.FmuInvocationException; +import org.intocps.fmi.jnifmuapi.fmi3.*; +import org.intocps.maestro.ast.AFunctionDeclaration; +import org.intocps.maestro.ast.AModuleDeclaration; +import org.intocps.maestro.ast.node.AIntNumericPrimitiveType; +import org.intocps.maestro.ast.node.ANameType; +import org.intocps.maestro.ast.node.AReferenceType; +import org.intocps.maestro.ast.node.PType; +import org.intocps.maestro.interpreter.Fmi2Interpreter; +import org.intocps.maestro.interpreter.Interpreter; +import org.intocps.maestro.interpreter.InterpreterException; +import org.intocps.maestro.interpreter.external.ExternalReflectCallHelper; +import org.intocps.maestro.interpreter.external.IArgMapping; +import org.intocps.maestro.interpreter.external.TP; +import org.intocps.maestro.interpreter.values.*; +import org.intocps.maestro.interpreter.values.fmi.Fmu3InstanceValue; +import org.intocps.maestro.interpreter.values.fmi.Fmu3StateValue; +import org.intocps.maestro.interpreter.values.fmi.Fmu3Value; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.*; +import java.lang.reflect.Method; +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +import static org.intocps.maestro.interpreter.Fmi2Interpreter.*; +import static org.intocps.maestro.interpreter.extensions.fmi3.Fmi3StatusArgMapping.status2IntValue; + +public class Fmi3Interpreter { + static final ExternalReflectCallHelper.ArgMapping boolArrayOutArgMapper = new ExternalReflectCallHelper.ArgMapping(TP.Bool, 2, + ExternalReflectCallHelper.ArgMapping.InOut.Output, null); + static final ExternalReflectCallHelper.ArgMapping doubleArrayOutArgMapper = new ExternalReflectCallHelper.ArgMapping(TP.Real, 2, + ExternalReflectCallHelper.ArgMapping.InOut.Output, null); + + static final ExternalReflectCallHelper.ArgMapping intInArgMapper = new ExternalReflectCallHelper.ArgMapping(TP.Int, 1, + ExternalReflectCallHelper.ArgMapping.InOut.Input, null); + static final ExternalReflectCallHelper.ArgMapping doubleInArgMapper = new ExternalReflectCallHelper.ArgMapping(TP.Real, 1, + ExternalReflectCallHelper.ArgMapping.InOut.Input, null); + + static final ExternalReflectCallHelper.ArgMapping boolInArgMapper = new ExternalReflectCallHelper.ArgMapping(TP.Bool, 1, + ExternalReflectCallHelper.ArgMapping.InOut.Input, null); + + static final ExternalReflectCallHelper.ArgMapping doubleArrayInArgMapper = new ExternalReflectCallHelper.ArgMapping(TP.Real, 2, + ExternalReflectCallHelper.ArgMapping.InOut.Input, null); + + static final ExternalReflectCallHelper.ArgMapping longArrayInArgMapper = new ExternalReflectCallHelper.ArgMapping(TP.Long, 2, + ExternalReflectCallHelper.ArgMapping.InOut.Input, null); + + static final ExternalReflectCallHelper.ArgMapping uintArrayOutArgMapper = new ExternalReflectCallHelper.ArgMapping(TP.Int, 2, + ExternalReflectCallHelper.ArgMapping.InOut.Output, null); + static final ExternalReflectCallHelper.ArgMapping longArrayOutArgMapper = new ExternalReflectCallHelper.ArgMapping(TP.Long, 2, + ExternalReflectCallHelper.ArgMapping.InOut.Output, null); + + static final ExternalReflectCallHelper.ArgMapping intArrayOutArgMapper = new ExternalReflectCallHelper.ArgMapping(TP.Int, 2, + ExternalReflectCallHelper.ArgMapping.InOut.Output, null); + + + final static Logger logger = LoggerFactory.getLogger(Interpreter.class); + private final File workingDirectory; + private final Function resolver; + + public Fmi3Interpreter(File workingDirectory, Function resolver) { + + this.workingDirectory = workingDirectory; + this.resolver = resolver; + } + + public static Double getDouble(Value value) { + + if (value == null || value instanceof NullValue) { + return null; + } + + value = value.deref(); + + if (value == null || value instanceof NullValue) { + return null; + } + if (value.isNumeric()) { + return ((NumericValue) value).doubleValue(); + } + throw new InterpreterException("Value is not double"); + } + + public static UpdatableValue getUpdatable(Value v) { + if (!(v instanceof UpdatableValue)) { + throw new InterpreterException("value not a reference value"); + } + return (UpdatableValue) v; + } + + public Map createFmuMembers(File workingDirectory, String guid, IFmi3Fmu fmu) { + + + var fmi3Module = resolver.apply("FMI3"); + Map functions = new HashMap<>(); + + /* + * + * FMI3Instance instantiateCoSimulation(string instanceName, string instantiationToken, string resourceLocation, bool visible, bool loggingOn, + bool eventModeUsed, bool earlyReturnAllowed, uint[] requiredIntermediateVariables); //, ILogMessageCallback logMessage,IIntermediateUpdateCallback intermediateUpdate + +FMI2Component instantiateCoSimulationWrapAsFmi2(string instanceName, string instantiationToken, string resourceLocation, bool visible, bool loggingOn, + bool eventModeUsed, bool earlyReturnAllowed, uint[] requiredIntermediateVariables);//, ILogMessageCallback logMessage,IIntermediateUpdateCallback intermediateUpdate + + * + * */ + + + functions.put("instantiateCoSimulation", new FunctionValue.ExternalFunctionValue(fargs -> { + + Fmi2Interpreter.checkArgLength(fargs, 6); + + String name = Fmi2Interpreter.getString(fargs.get(0)); + boolean visible = Fmi2Interpreter.getBool(fargs.get(1)); + boolean logginOn = Fmi2Interpreter.getBool(fargs.get(2)); + + boolean eventModeUsed = Fmi2Interpreter.getBool(fargs.get(3)); + boolean earlyReturnAllowed = Fmi2Interpreter.getBool(fargs.get(4)); + long[] requiredIntermediateVariables = getArrayValue(fargs.get(5), Optional.empty(), NumericValue.class).stream() + .mapToLong(NumericValue::longValue).toArray(); + + try { + + long startInstantiateTime = System.nanoTime(); + + logger.debug(String.format("Loading native FMU. GUID: %s, NAME: %s", "" + guid, "" + name)); + + BufferedOutputStream fmuLogOutputStream = workingDirectory == null ? null : new BufferedOutputStream( + new FileOutputStream(new File(workingDirectory, name + ".log"))); + + final String formatter = "{} {} {} {}"; + String pattern = "%d{ISO8601} %-5p - %m%n"; + + Layout layout = PatternLayout.newBuilder().withPattern(pattern).withCharset(StandardCharsets.UTF_8).build();// + + ILogMessageCallback logCallback = (instanceName, status, category, message) -> { + logger.info("NATIVE: instance: '{}', status: '{}', category: '{}', message: {}", instanceName, status, category, message); + { + + if (fmuLogOutputStream == null) { + return; + } + + Log4jLogEvent.Builder builder = Log4jLogEvent.newBuilder() + .setMessage(new ParameterizedMessage(formatter, category, status, instanceName, message)); + + + switch (status) { + case OK: + case Discard: + builder.setLevel(Level.INFO); + break; + case Error: + case Fatal: + builder.setLevel(Level.ERROR); + case Warning: + builder.setLevel(Level.WARN); + break; + default: + builder.setLevel(Level.TRACE); + break; + } + + try { + Log4jLogEvent event = builder.build(); + fmuLogOutputStream.write(layout.toByteArray(event)); + } catch (IOException e) { + e.printStackTrace(); + } + } + }; + IIntermediateUpdateCallback intermediateUpdateCallback = (instanceEnvironment, intermediateUpdateTime, clocksTicked, intermediateVariableSetRequested, intermediateVariableGetAllowed, intermediateStepFinished, canReturnEarly) -> new IIntermediateUpdateCallback.IntermediateUpdateResponse( + false, intermediateUpdateTime); + IFmi3Instance instance = fmu.instantiateCoSimulation(name, guid, visible, logginOn, eventModeUsed, earlyReturnAllowed, + requiredIntermediateVariables, logCallback, null); + + + if (instance == null) { + logger.debug("Instance instantiate failed"); + return new NullValue(); + } + long stopInstantiateTime = System.nanoTime(); + System.out.println("Interpretation instantiate took: " + (stopInstantiateTime - startInstantiateTime)); + + return getFmuInstanceValue(fmuLogOutputStream, instance, resolver); + + + } catch (IOException | NoSuchMethodException e) { + e.printStackTrace(); + } + + return null; + })); + + + functions.put("freeInstance", new FunctionValue.ExternalFunctionValue(fargs -> { + + fargs = fargs.stream().map(Value::deref).collect(Collectors.toList()); + + logger.debug("freeInstance"); + + if (fargs.size() != 1) { + throw new InterpreterException("Too few arguments"); + } + + if (!(fargs.get(0) instanceof Fmu3InstanceValue)) { + throw new InterpreterException("Argument must be an external module reference"); + } + + Fmu3InstanceValue component = (Fmu3InstanceValue) fargs.get(0); + + try { + OutputStream loggerOutputStream = component.getFmuLoggerOutputStream(); + if (loggerOutputStream != null) { + loggerOutputStream.close(); + } + component.getModule().freeInstance(); + } catch (IOException | FmuInvocationException e) { + e.printStackTrace(); + } + + + return new VoidValue(); + })); + + functions.put("unload", new FunctionValue.ExternalFunctionValue(fargs -> { + fargs = fargs.stream().map(Value::deref).collect(Collectors.toList()); + + logger.debug("unload"); + + if (fargs.size() != 0) { + throw new InterpreterException("Too many arguments"); + } + + try { + fmu.unLoad(); + } catch (FmuInvocationException e) { + e.printStackTrace(); + } + + return new VoidValue(); + })); + + checkRequiredFunctions(fmi3Module, functions); + + return functions; + } + + static void checkRequiredFunctions(AModuleDeclaration module, Map functions) { + var expectedFunctions = module.getFunctions().stream().map(f -> f.getName().getText()).collect(Collectors.toSet()); + + if (expectedFunctions.size() != functions.size() || !functions.keySet().equals(expectedFunctions)) { + logger.warn("Runtime type '{}' does not match declaration. Missing: '{}'", module.getName().getText(), + expectedFunctions.stream().filter(n -> !functions.containsKey(n)).sorted().collect(Collectors.joining(",\n\t", "\n\t", ""))); + } + } + + public static Function getFmi3InstanceCustomArgMapper() { + + Set statusRetuningFunctions = Arrays.stream(Fmi3Instance.class.getDeclaredMethods()) + .filter(m -> m.getReturnType().getSimpleName().equals("Fmi3Status")).map(Method::getName).collect(Collectors.toSet()); + + + Function costumeArgMapper = tCtxt -> { + + PType t = tCtxt.getArgType(); + boolean output = t instanceof AReferenceType; + if (output) { + t = ((AReferenceType) t).getType(); + } + + if (tCtxt.getArgType() instanceof AIntNumericPrimitiveType && tCtxt.getArgName() == null && statusRetuningFunctions.contains( + tCtxt.getFunctionName())) { + //ok this is a return of status we need to make it an int + return new Fmi3StatusArgMapping(); + } else if (t instanceof ANameType) { + String typeName = ((ANameType) t).getName().getText(); + if (typeName.equals("FMI3Instance")) { + return new Fmi3InstanceArgMapping(); + } else if (typeName.equals("FMU3State")) { + return new Fmi3StateArgMapping(tCtxt); + } + } + return null; + }; + return costumeArgMapper; + } + + + private static Value getFmuInstanceValue(BufferedOutputStream fmuLogOutputStream, IFmi3Instance instance, + Function resolver) throws NoSuchMethodException { + + //populate component functions + var module = resolver.apply("FMI3Instance"); + + + Map functions = new HashMap<>();//createGetSetMembers(instance)); + + Predicate functionFilter = fun -> !fun.getName().getText().equals("enterInitializationMode") && !fun.getName().getText() + .equals("setBinary"); + + Set resultRetuningFunctions = Arrays.stream(Fmi3Instance.class.getDeclaredMethods()) + .filter(m -> m.getReturnType().getName().equals(org.intocps.fmi.jnifmuapi.fmi3.FmuResult.class.getName())).map(Method::getName) + .collect(Collectors.toSet()); + + final var costumeArgMapper = getFmi3InstanceCustomArgMapper(); + + + for (AFunctionDeclaration function : module.getFunctions()) { + if (functionFilter == null || functionFilter.test(function)) { + + functions.computeIfAbsent(function.getName().getText(), key -> { + try { + var builder = new ExternalReflectCallHelper(function, instance, costumeArgMapper); + if (resultRetuningFunctions.contains(function.getName().getText())) { + return handleResultReturns(builder).build(); + } else { + return builder.build(); + } + } catch (NoSuchMethodException | RuntimeException e) { + logger.warn("Auto binding faild for: " + e.getMessage()); + return null; + } + }); + + } + } + + + functions.put("enterInitializationMode", new FunctionValue.ExternalFunctionValue(fcargs -> { + + checkArgLength(fcargs, 5); + + boolean toleranceDefined = getBool(fcargs.get(0)); + double tolerance = getDouble(fcargs.get(1)); + double startTime = getDouble(fcargs.get(2)); + boolean stopTimeDefined = getBool(fcargs.get(3)); + Double stopTime = getDouble(fcargs.get(4)); + + + try { + Fmi3Status res = instance.enterInitializationMode(toleranceDefined ? tolerance : null, startTime, stopTimeDefined ? stopTime : null); + return new IntegerValue(res.value); + } catch (FmuInvocationException e) { + throw new InterpreterException(e); + } + + })); + + functions.put("completedIntegratorStep", new FunctionValue.ExternalFunctionValue(fcargs -> { + // int completedIntegratorStep(bool nosetFMUStatePriorToCurrentPoint, bool[] enterEventMode,bool[] terminateSimulation); + + checkArgLength(fcargs, 3); + try { + FmuResult res = instance.completedIntegratorStep( + (Boolean) boolInArgMapper.map(fcargs.get(0))); + boolArrayOutArgMapper.mapOut(fcargs.get(1), new boolean[]{res.result.isEnterEventMode()}); + boolArrayOutArgMapper.mapOut(fcargs.get(2), new boolean[]{res.result.isTerminateSimulation()}); + return status2IntValue(res.status); + } catch (FmuInvocationException e) { + throw new InterpreterException(e); + } + + })); + + functions.put("getAdjointDerivative", new FunctionValue.ExternalFunctionValue(fcargs -> { + // int getAdjointDerivative(uint unknowns[], int nUnknowns, uint knowns[], int nKnowns, real seed[], int nSeed, + // real sensitivity[], int nSensitivity); + + checkArgLength(fcargs, 8); + try { + FmuResult res = instance.getGetAdjointDerivative((long[]) longArrayInArgMapper.map(fcargs.get(0)), + (long[]) longArrayInArgMapper.map(fcargs.get(2)), (double[]) doubleArrayInArgMapper.map(fcargs.get(4)), + (Integer) intInArgMapper.map(fcargs.get(5))); + doubleArrayOutArgMapper.mapOut(fcargs.get(6), res.result); + return status2IntValue(res.status); + } catch (FmuInvocationException e) { + throw new InterpreterException(e); + } + + })); + + functions.put("getClock", new FunctionValue.ExternalFunctionValue(fcargs -> { + // int getClock(uint valueReferences[], int nValueReferences, bool values[]); + + checkArgLength(fcargs, 3); + try { + FmuResult res = instance.getClock((long[]) longArrayInArgMapper.map(fcargs.get(0))); + boolArrayOutArgMapper.mapOut(fcargs.get(2), res.result); + return status2IntValue(res.status); + } catch (FmuInvocationException e) { + throw new InterpreterException(e); + } + + })); + + + functions.put("getContinuousStateDerivatives", new FunctionValue.ExternalFunctionValue(fcargs -> { + //int getContinuousStateDerivatives(real derivatives[], int nContinuousStates); + + checkArgLength(fcargs, 2); + try { + FmuResult res = instance.getContinuousStateDerivatives((Integer) intInArgMapper.map(fcargs.get(1))); + doubleArrayOutArgMapper.mapOut(fcargs.get(0), res.result); + return status2IntValue(res.status); + } catch (FmuInvocationException e) { + throw new InterpreterException(e); + } + + })); + + functions.put("getContinuousStates", new FunctionValue.ExternalFunctionValue(fcargs -> { + //int getContinuousStates(real continuousStates[], int nContinuousStates); + + checkArgLength(fcargs, 2); + try { + FmuResult res = instance.getGetContinuousStates((Integer) intInArgMapper.map(fcargs.get(1))); + doubleArrayOutArgMapper.mapOut(fcargs.get(0), res.result); + return status2IntValue(res.status); + } catch (FmuInvocationException e) { + throw new InterpreterException(e); + } + + })); + + functions.put("getDirectionalDerivative", new FunctionValue.ExternalFunctionValue(fcargs -> { + // int getDirectionalDerivative(uint unknowns[], int nUnknowns, uint knowns[], int nKnowns, real seed[], int nSeed, + // real sensitivity[], int nSensitivity); + + checkArgLength(fcargs, 8); + try { + FmuResult res = instance.getDirectionalDerivative((long[]) longArrayInArgMapper.map(fcargs.get(0)), + (long[]) longArrayInArgMapper.map(fcargs.get(2)), (double[]) doubleArrayInArgMapper.map(fcargs.get(4))); + + doubleArrayOutArgMapper.mapOut(fcargs.get(6), res.result); + return status2IntValue(res.status); + } catch (FmuInvocationException e) { + throw new InterpreterException(e); + } + + })); + + + functions.put("getEventIndicators", new FunctionValue.ExternalFunctionValue(fcargs -> { + // int getEventIndicators(real eventIndicators[], int nEventIndicators); + + checkArgLength(fcargs, 2); + try { + FmuResult res = instance.getGetEventIndicators((Integer) intInArgMapper.map(fcargs.get(1))); + doubleArrayOutArgMapper.mapOut(fcargs.get(0), res.result); + return status2IntValue(res.status); + } catch (FmuInvocationException e) { + throw new InterpreterException(e); + } + + })); + + + functions.put("getIntervalDecimal", new FunctionValue.ExternalFunctionValue(fcargs -> { + // int getIntervalDecimal(uint valueReferences[], int nValueReferences, real intervals[], + // int qualifiers[]); + + checkArgLength(fcargs, 4); + try { + FmuResult res = instance.getIntervalDecimal( + (long[]) longArrayInArgMapper.map(fcargs.get(0))); + doubleArrayOutArgMapper.mapOut(fcargs.get(2), res.result.getIntervals()); + doubleArrayOutArgMapper.mapOut(fcargs.get(3), res.result.getQualifiers()); + return status2IntValue(res.status); + } catch (FmuInvocationException e) { + throw new InterpreterException(e); + } + + })); + + functions.put("getIntervalFraction", new FunctionValue.ExternalFunctionValue(fcargs -> { + // int getIntervalFraction(uint valueReferences[], int nValueReferences, uint intervalCounters[], uint resolutions[], + // int qualifiers[]); + + checkArgLength(fcargs, 5); + try { + FmuResult res = instance.getIntervalFraction( + (long[]) longArrayInArgMapper.map(fcargs.get(0))); + uintArrayOutArgMapper.mapOut(fcargs.get(2), res.result.getIntervalCounters()); + uintArrayOutArgMapper.mapOut(fcargs.get(3), res.result.getResolutions()); + intInArgMapper.mapOut(fcargs.get(3), Arrays.stream(res.result.getQualifiers()).map(q -> q.getValue()).toArray()); + return status2IntValue(res.status); + } catch (FmuInvocationException e) { + throw new InterpreterException(e); + } + + })); + + functions.put("getNominalsOfContinuousStates", new FunctionValue.ExternalFunctionValue(fcargs -> { + // int getNominalsOfContinuousStates(real nominals[], int nContinuousStates); + + checkArgLength(fcargs, 2); + try { + FmuResult res = instance.getGetNominalsOfContinuousStates((Integer) intInArgMapper.map(fcargs.get(1))); + doubleArrayOutArgMapper.mapOut(fcargs.get(0), res.result); + return status2IntValue(res.status); + } catch (FmuInvocationException e) { + throw new InterpreterException(e); + } + + })); + + functions.put("getNumberOfContinuousStates", new FunctionValue.ExternalFunctionValue(fcargs -> { + // int getNumberOfContinuousStates(int[] nContinuousStates); + + checkArgLength(fcargs, 1); + try { + FmuResult res = instance.getNumberOfContinuousStates(); + longArrayOutArgMapper.mapOut(fcargs.get(0), res.result); + return status2IntValue(res.status); + } catch (FmuInvocationException e) { + throw new InterpreterException(e); + } + + })); + + functions.put("getNumberOfEventIndicators", new FunctionValue.ExternalFunctionValue(fcargs -> { + // int getNumberOfEventIndicators(int[] nEventIndicators); + + checkArgLength(fcargs, 1); + try { + FmuResult res = instance.getNumberOfEventIndicators(); + intArrayOutArgMapper.mapOut(fcargs.get(0), res.result); + return status2IntValue(res.status); + } catch (FmuInvocationException e) { + throw new InterpreterException(e); + } + + })); + + + functions.put("doStep", new FunctionValue.ExternalFunctionValue(fcargs -> { + + checkArgLength(fcargs, 7); + + //in + double currentCommunicationPoint = getDouble(fcargs.get(0)); + double communicationStepSize = getDouble(fcargs.get(1)); + boolean noSetFMUStatePriorToCurrentPoint = getBool(fcargs.get(2)); + //out + + UpdatableValue eventHandlingNeeded = getUpdatable(fcargs.get(3)); + UpdatableValue terminateSimulation = getUpdatable(fcargs.get(4)); + UpdatableValue earlyReturn = getUpdatable(fcargs.get(5)); + UpdatableValue lastSuccessfulTime = getUpdatable(fcargs.get(6)); + /*int doStep(real currentCommunicationPoint, real communicationStepSize, bool nosetFMUStatePriorToCurrentPoint, + out bool eventHandlingNeeded,out bool terminateSimulation,out bool earlyReturn,out real lastSuccessfulTime);*/ + + try { + FmuResult res = instance.doStep(currentCommunicationPoint, communicationStepSize, + noSetFMUStatePriorToCurrentPoint); + + if (res.status == Fmi3Status.OK) { + eventHandlingNeeded.setValue(new BooleanValue(res.result.isEventHandlingNeeded())); + terminateSimulation.setValue(new BooleanValue(res.result.isTerminateSimulation())); + earlyReturn.setValue(new BooleanValue(res.result.isEarlyReturn())); + lastSuccessfulTime.setValue(new RealValue(res.result.getLastSuccessfulTime())); + } + return new IntegerValue(res.status.value); + } catch (FmuInvocationException e) { + throw new InterpreterException(e); + } + })); + + + functions.put("setFMUState", new FunctionValue.ExternalFunctionValue(fcargs -> { + checkArgLength(fcargs, 1); + + Value v = fcargs.get(0).deref(); + + if (v instanceof Fmu3StateValue) { + try { + Fmu3StateValue stateValue = (Fmu3StateValue) v; + Fmi3Status res = instance.setState(stateValue.getModule()); + return new IntegerValue(res.value); + } catch (FmuInvocationException e) { + throw new InterpreterException(e); + } + } + + throw new InterpreterException("Invalid value"); + })); + functions.put("getFMUState", new FunctionValue.ExternalFunctionValue(fcargs -> { + + checkArgLength(fcargs, 1); + + if (!(fcargs.get(0) instanceof UpdatableValue)) { + throw new InterpreterException("value not a reference value"); + } + + + try { + + org.intocps.fmi.jnifmuapi.fmi3.FmuResult res = instance.getState(); + + if (res.status == Fmi3Status.OK) { + UpdatableValue ref = (UpdatableValue) fcargs.get(0); + ref.setValue(new Fmu3StateValue(res.result)); + } + + + return new IntegerValue(res.status.value); + + } catch (FmuInvocationException e) { + throw new InterpreterException(e); + } + + + })); + functions.put("freeFMUState", new FunctionValue.ExternalFunctionValue(fcargs -> { + + checkArgLength(fcargs, 1); + + Value v = fcargs.get(0).deref(); + + if (v instanceof Fmu3StateValue) { + try { + Fmu3StateValue stateValue = (Fmu3StateValue) v; + Fmi3Status res = instance.freeState(stateValue.getModule()); + return new IntegerValue(res.value); + } catch (FmuInvocationException e) { + throw new InterpreterException(e); + } + } + + throw new InterpreterException("Invalid value"); + + + })); + + + checkRequiredFunctions(module, functions); + + return new Fmu3InstanceValue(functions, instance, fmuLogOutputStream); + } + + private static ExternalReflectCallHelper handleResultReturns(ExternalReflectCallHelper builder) { + + builder.addReturn(new ResultProxyArgMapper(new Fmi3StatusArgMapping(), + builder.stream().filter(arg -> arg.getDirection() == ExternalReflectCallHelper.ArgMapping.InOut.Output) + .collect(Collectors.toList()))); + + //turn off output mapping for these arguments + builder.stream().filter(arg -> arg.getDirection() == ExternalReflectCallHelper.ArgMapping.InOut.Output) + .forEach(arg -> arg.setDirection(ExternalReflectCallHelper.ArgMapping.InOut.OutputThroughReturn)); + + return builder; + } + + + public Value createFmiValue(String path, String guid) { + try { + long startExecTime = System.nanoTime(); + + URI uri = URI.create(path); + if (!uri.isAbsolute()) { + uri = new File(".").toURI().resolve(uri); + } + File file = new File(uri); + + final IFmi3Fmu fmu = new Fmu3(file); + + fmu.load(); + + Map functions = createFmuMembers(workingDirectory, guid, fmu); + + long stopTime = System.nanoTime(); + + System.out.println("Interpretation load took: " + (stopTime - startExecTime)); + + return new Fmu3Value(functions, fmu); + + } catch (Exception e) { + e.printStackTrace(); + return new NullValue(); + } + } + + +} diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/fmi3/Fmi3StateArgMapping.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/fmi3/Fmi3StateArgMapping.java new file mode 100644 index 000000000..5af1c6853 --- /dev/null +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/fmi3/Fmi3StateArgMapping.java @@ -0,0 +1,84 @@ +package org.intocps.maestro.interpreter.extensions.fmi3; + +import org.intocps.fmi.jnifmuapi.fmi3.Fmi3State; +import org.intocps.fmi.jnifmuapi.fmi3.Fmi3Status; +import org.intocps.maestro.ast.node.AReferenceType; +import org.intocps.maestro.ast.node.PType; +import org.intocps.maestro.interpreter.external.ExternalReflectCallHelper; +import org.intocps.maestro.interpreter.external.IArgMapping; +import org.intocps.maestro.interpreter.values.IntegerValue; +import org.intocps.maestro.interpreter.values.UpdatableValue; +import org.intocps.maestro.interpreter.values.Value; +import org.intocps.maestro.interpreter.values.fmi.Fmu3StateValue; + +import java.util.Map; + +class Fmi3StateArgMapping implements IArgMapping { + + + + private final boolean output; + + public Fmi3StateArgMapping(ExternalReflectCallHelper.ArgMappingContext tCtxt) { + + PType t = tCtxt.getArgType(); + output = t instanceof AReferenceType; + } + + @Override + public int getDimension() { + return 1; + } + + @Override + public long[] getLimits() { + return null; + } + + @Override + public ExternalReflectCallHelper.ArgMapping.InOut getDirection() { + return output ? ExternalReflectCallHelper.ArgMapping.InOut.Output : ExternalReflectCallHelper.ArgMapping.InOut.Input; + } + + @Override + public void setDirection(ExternalReflectCallHelper.ArgMapping.InOut direction) { + + } + + @Override + public Object map(Value v) { + if (v instanceof Fmu3StateValue) { + return ((Fmu3StateValue) v).getModule(); + } + return null; + } + + @Override + public void mapOut(Value original, Object value) { + if (original instanceof UpdatableValue) { + UpdatableValue up = (UpdatableValue) original; + up.setValue(new Fmu3StateValue((Fmi3State) value)); + } + + } + + @Override + public Value mapOut(Object value, Map outputThroughReturn) { + return null; + } + + @Override + public Class getType() { + return Fmi3State.class; + } + + @Override + public String getDescriptiveName() { + return "Fmi3State"; + } + + @Override + public String getDefaultTestValue() { + return null; + } +} diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/fmi3/Fmi3StatusArgMapping.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/fmi3/Fmi3StatusArgMapping.java new file mode 100644 index 000000000..8f0363eb9 --- /dev/null +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/fmi3/Fmi3StatusArgMapping.java @@ -0,0 +1,83 @@ +package org.intocps.maestro.interpreter.extensions.fmi3; + +import org.intocps.fmi.jnifmuapi.fmi3.Fmi3Status; +import org.intocps.fmi.jnifmuapi.fmi3.FmuResult; +import org.intocps.maestro.interpreter.external.ExternalReflectCallHelper; +import org.intocps.maestro.interpreter.external.IArgMapping; +import org.intocps.maestro.interpreter.values.IntegerValue; +import org.intocps.maestro.interpreter.values.Value; + +import java.util.Map; + +class Fmi3StatusArgMapping implements IArgMapping { + public static Value status2IntValue(Fmi3Status res) { + switch (res) { + + case OK: + return new IntegerValue(0); + case Warning: + return new IntegerValue(1); + case Discard: + return new IntegerValue(2); + case Error: + return new IntegerValue(3); + case Fatal: + return new IntegerValue(4); + } + return null; + } + @Override + public int getDimension() { + return 1; + } + + @Override + public long[] getLimits() { + return null; + } + + @Override + public ExternalReflectCallHelper.ArgMapping.InOut getDirection() { + return ExternalReflectCallHelper.ArgMapping.InOut.OutputThroughReturn; + } + + @Override + public void setDirection(ExternalReflectCallHelper.ArgMapping.InOut direction) { + + } + + @Override + public Object map(Value v) { + return null; + } + + @Override + public void mapOut(Value original, Object value) { + + } + + @Override + public Value mapOut(Object value, Map outputThroughReturn) { + if (value instanceof Fmi3Status) { + return status2IntValue((Fmi3Status) value); + } else if (value instanceof FmuResult) { + return status2IntValue(((FmuResult) value).status); + } + return null; + } + + @Override + public Class getType() { + return Object.class; + } + + @Override + public String getDescriptiveName() { + return "int"; + } + + @Override + public String getDefaultTestValue() { + return "0"; + } +} diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/fmi3/ResultProxyArgMapper.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/fmi3/ResultProxyArgMapper.java new file mode 100644 index 000000000..85b028723 --- /dev/null +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/fmi3/ResultProxyArgMapper.java @@ -0,0 +1,80 @@ +package org.intocps.maestro.interpreter.extensions.fmi3; + +import org.intocps.fmi.jnifmuapi.fmi3.FmuResult; +import org.intocps.maestro.interpreter.external.ExternalReflectCallHelper; +import org.intocps.maestro.interpreter.external.IArgMapping; +import org.intocps.maestro.interpreter.values.Value; + +import java.util.List; +import java.util.Map; + +class ResultProxyArgMapper implements IArgMapping { + private final Fmi3StatusArgMapping ret; + private final List outputArgs; + + public ResultProxyArgMapper(Fmi3StatusArgMapping fmi3StatusArgMapping, List directedOutputs) { + this.ret = fmi3StatusArgMapping; + this.outputArgs = directedOutputs; + } + + @Override + public int getDimension() { + return ret.getDimension(); + } + + @Override + public long[] getLimits() { + return ret.getLimits(); + } + + @Override + public ExternalReflectCallHelper.ArgMapping.InOut getDirection() { + return ret.getDirection(); + } + + @Override + public void setDirection(ExternalReflectCallHelper.ArgMapping.InOut direction) { + + } + + @Override + public Object map(Value v) { + return ret.map(v); + } + + @Override + public void mapOut(Value original, Object value) { + + } + + @Override + public Value mapOut(Object value, Map outputThroughReturn) { + + if (outputArgs.size() == 1) { + FmuResult result = (FmuResult) value; + IArgMapping outArg = outputArgs.get(0); + // var v = outArg.mapOut(result.result, null); + outArg.mapOut(outputThroughReturn.get(outArg), result.result); + // outArg.mapOut(result.result,outputThroughReturn.get(outArg)); + } else { + throw new RuntimeException("Ups.. not implemented. Need to know the output order of args: " + outputArgs.size()); + } + + return ret.mapOut(value, null); + } + + @Override + public Class getType() { + return ret.getType(); + } + + @Override + public String getDescriptiveName() { + return ret.getDescriptiveName(); + } + + @Override + public String getDefaultTestValue() { + return null; + } +} diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/external/ExternalReflectCallHelper.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/external/ExternalReflectCallHelper.java index b07937066..82c2b116d 100644 --- a/interpreter/src/main/java/org/intocps/maestro/interpreter/external/ExternalReflectCallHelper.java +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/external/ExternalReflectCallHelper.java @@ -27,7 +27,8 @@ public ExternalReflectCallHelper(String functionName, Object object) { this.object = object; } - public ExternalReflectCallHelper(AFunctionDeclaration functionDeclaration, Object object, Function costumeArgMapper) { + public ExternalReflectCallHelper(AFunctionDeclaration functionDeclaration, Object object, + Function costumeArgMapper) { this(functionDeclaration.getName().getText(), object); autoBuild(functionDeclaration, costumeArgMapper); } @@ -146,18 +147,48 @@ public synchronized String toString() { return sb.toString(); } - private void autoBuild(AFunctionDeclaration functionDeclaration, Function costumeArgMapper) { + public static class ArgMappingContext { + final String functionName; + final String argName; + + public String getFunctionName() { + return functionName; + } + + public String getArgName() { + return argName; + } + + public PType getArgType() { + return argType; + } + + final PType argType; + + public ArgMappingContext(String functionName, String argName, PType argType) { + this.functionName = functionName; + this.argName = argName; + this.argType = argType; + } + } + + private void autoBuild(AFunctionDeclaration functionDeclaration, Function costumeArgMapper) { PType returnType = functionDeclaration.getReturnType(); if (returnType != null && !(returnType instanceof AVoidType)) { try { - addReturn(getReverseType(returnType).getKey()); - } catch (ExceptionUnknownTypeMapping e) { IArgMapping ca; - if (costumeArgMapper != null && (ca = costumeArgMapper.apply(returnType)) != null) { + if (costumeArgMapper != null && (ca = costumeArgMapper.apply(new ArgMappingContext(this.functionName, null, returnType))) != null) { addReturn(ca); } else { - throw new RuntimeException(e); + addReturn(getReverseType(returnType).getKey()); } + } catch (ExceptionUnknownTypeMapping e) { + // IArgMapping ca; + // if (costumeArgMapper != null && (ca = costumeArgMapper.apply(new ArgMappingContext(this.functionName, null, returnType))) != null) { + // addReturn(ca); + // } else { + throw new RuntimeException(e); + // } } } @@ -167,7 +198,8 @@ private void autoBuild(AFunctionDeclaration functionDeclaration, Function args = Collections.unmodifiableList(this); final IArgMapping rArg = returnArg; - final Method method = object.getClass().getMethod(functionName, args.stream().map(IArgMapping::getType).toArray(Class[]::new)); + final Method method = object.getClass().getMethod(functionName, + args.stream().filter(arg -> arg.getDirection() != ArgMapping.InOut.OutputThroughReturn).map(IArgMapping::getType) + .toArray(Class[]::new)); return new FunctionValue.ExternalFunctionValue(fcargs -> { @@ -217,30 +251,41 @@ public FunctionValue.ExternalFunctionValue build() throws NoSuchMethodException checkArgLength(fcargs, args.size()); //map inputs - var vitr = fcargs.iterator(); - var mitr = args.iterator(); + var passedArgItr = fcargs.iterator(); + var declaredArgItr = args.iterator(); List argValues = new ArrayList(args.size()); - while (vitr.hasNext() && mitr.hasNext()) { - var v = vitr.next(); - IArgMapping mapper = mitr.next(); - // if (mapper.direction == ArgMapping.InOut.Input) { - argValues.add(mapper.map(v)); - //} + while (passedArgItr.hasNext() && declaredArgItr.hasNext()) { + var v = passedArgItr.next(); + IArgMapping mapper = declaredArgItr.next(); + if (mapper.getDirection() != ArgMapping.InOut.OutputThroughReturn) { + argValues.add(mapper.map(v)); + } } try { var ret = method.invoke(object, argValues.toArray()); //map outputs - vitr = fcargs.iterator(); - var voitr = argValues.iterator(); - mitr = args.iterator(); - while (vitr.hasNext() && voitr.hasNext() && mitr.hasNext()) { - var original = vitr.next(); - var passedValue = voitr.next(); - IArgMapping mapper = mitr.next(); - if (mapper.getDirection() == ArgMapping.InOut.Output) { - mapper.mapOut(original, passedValue); + passedArgItr = fcargs.iterator(); + var passedValuesItr = argValues.iterator(); + declaredArgItr = args.iterator(); + Map outputThroughReturn = new HashMap<>(); + + // process arguments. All inputs should be skipped and output mapped out. All out through return should be collected and handled + // through the mapout of return as additional info + while (passedArgItr.hasNext() && declaredArgItr.hasNext()) { + IArgMapping mapper = declaredArgItr.next(); + var original = passedArgItr.next(); + + if (mapper.getDirection() == ArgMapping.InOut.OutputThroughReturn) { + outputThroughReturn.put(mapper, original); + continue; + } + if (passedValuesItr.hasNext()) { + var passedValue = passedValuesItr.next(); + if (mapper.getDirection() == ArgMapping.InOut.Output) { + mapper.mapOut(original, passedValue); + } } } @@ -248,7 +293,7 @@ public FunctionValue.ExternalFunctionValue build() throws NoSuchMethodException if (rArg == null) { return new VoidValue(); } - return rArg.mapOut(ret); + return rArg.mapOut(ret, outputThroughReturn); } catch (IllegalAccessException | InvocationTargetException e) { @@ -269,7 +314,7 @@ public static class ArgMapping implements IArgMapping { final int dimension; final long[] limits; - final InOut direction; + InOut direction; public ArgMapping(TP type, int dimension, InOut direction, long[] limits) { this.type = type; @@ -297,6 +342,11 @@ public InOut getDirection() { return direction; } + @Override + public void setDirection(InOut direction) { + this.direction = direction; + } + @Override public Object map(Value v) { //map value to primitive type @@ -390,31 +440,32 @@ public void mapOut(Value original, Object value) { .limit(elementsToUse).map(BooleanValue::new).collect(Collectors.toList()); break; case Byte: - values = Arrays.stream(ArrayUtils.toObject((byte[]) (value.getClass().isArray() ?value: new byte[]{(byte) value}))).limit(elementsToUse).map(ByteValue::new) - .collect(Collectors.toList()); + values = Arrays.stream(ArrayUtils.toObject((byte[]) (value.getClass().isArray() ? value : new byte[]{(byte) value}))) + .limit(elementsToUse).map(ByteValue::new).collect(Collectors.toList()); break; case Float: - values = Arrays.stream(ArrayUtils.toObject((float[])(value.getClass().isArray() ? value: new float[]{(float) value}))).limit(elementsToUse).map(FloatValue::new) - .collect(Collectors.toList()); + values = Arrays.stream(ArrayUtils.toObject((float[]) (value.getClass().isArray() ? value : new float[]{(float) value}))) + .limit(elementsToUse).map(FloatValue::new).collect(Collectors.toList()); break; case Int: - values = Arrays.stream(ArrayUtils.toObject((int[])(value.getClass().isArray() ? value: new int[]{(int) value}))).limit(elementsToUse).map(IntegerValue::new) - .collect(Collectors.toList()); + values = Arrays.stream(ArrayUtils.toObject((int[]) (value.getClass().isArray() ? value : new int[]{(int) value}))) + .limit(elementsToUse).map(IntegerValue::new).collect(Collectors.toList()); break; case Long: - values = Arrays.stream(ArrayUtils.toObject((long[])(value.getClass().isArray() ? value: new long[]{(long) value}))).limit(elementsToUse).map(LongValue::new) - .collect(Collectors.toList()); + values = Arrays.stream(ArrayUtils.toObject((long[]) (value.getClass().isArray() ? value : new long[]{(long) value}))) + .limit(elementsToUse).map(LongValue::new).collect(Collectors.toList()); break; case Real: - values = Arrays.stream(ArrayUtils.toObject((double[])(value.getClass().isArray() ? value: new double[]{(double) value}))).limit(elementsToUse).map(RealValue::new) - .collect(Collectors.toList()); + values = Arrays.stream(ArrayUtils.toObject((double[]) (value.getClass().isArray() ? value : new double[]{(double) value}))) + .limit(elementsToUse).map(RealValue::new).collect(Collectors.toList()); break; case Short: - values = Arrays.stream(ArrayUtils.toObject((short[])(value.getClass().isArray() ? value: new short[]{(short) value}))).limit(elementsToUse).map(ShortValue::new) - .collect(Collectors.toList()); + values = Arrays.stream(ArrayUtils.toObject((short[]) (value.getClass().isArray() ? value : new short[]{(short) value}))) + .limit(elementsToUse).map(ShortValue::new).collect(Collectors.toList()); break; case String: - values = Arrays.stream((String[])(value.getClass().isArray() ? value: new String[]{(String) value})).limit(elementsToUse).map(StringValue::new).collect(Collectors.toList()); + values = Arrays.stream((String[]) (value.getClass().isArray() ? value : new String[]{(String) value})).limit(elementsToUse) + .map(StringValue::new).collect(Collectors.toList()); break; } ref.setValue(new ArrayValue<>(values)); @@ -423,26 +474,71 @@ public void mapOut(Value original, Object value) { } @Override - public Value mapOut(Object value) { + public Value mapOut(Object value, Map outputThroughReturn) { //todo create value from value - switch (type) { - case Bool: - return new BooleanValue((Boolean) value); - case Byte: - return new ByteValue((Integer) value); - case Float: - return new FloatValue((Float) value); - case Int: - return new IntegerValue((Integer) value); - case Long: - return new LongValue((Long) value); - case Real: - return new RealValue((Double) value); - case Short: - return new ShortValue((Short) value); - case String: - return new StringValue((String) value); + + if (dimension == 2) { + List values = null; + long elementsToUse = limits == null ? Long.MAX_VALUE : limits[0]; + switch (type) { + + case Bool: + values = Arrays.stream(ArrayUtils.toObject((boolean[]) (value.getClass().isArray() ? value : new boolean[]{(boolean) value}))) + .limit(elementsToUse).map(BooleanValue::new).collect(Collectors.toList()); + break; + case Byte: + values = Arrays.stream(ArrayUtils.toObject((byte[]) (value.getClass().isArray() ? value : new byte[]{(byte) value}))) + .limit(elementsToUse).map(ByteValue::new).collect(Collectors.toList()); + break; + case Float: + values = Arrays.stream(ArrayUtils.toObject((float[]) (value.getClass().isArray() ? value : new float[]{(float) value}))) + .limit(elementsToUse).map(FloatValue::new).collect(Collectors.toList()); + break; + case Int: + values = Arrays.stream(ArrayUtils.toObject((int[]) (value.getClass().isArray() ? value : new int[]{(int) value}))) + .limit(elementsToUse).map(IntegerValue::new).collect(Collectors.toList()); + break; + case Long: + values = Arrays.stream(ArrayUtils.toObject((long[]) (value.getClass().isArray() ? value : new long[]{(long) value}))) + .limit(elementsToUse).map(LongValue::new).collect(Collectors.toList()); + break; + case Real: + values = Arrays.stream(ArrayUtils.toObject((double[]) (value.getClass().isArray() ? value : new double[]{(double) value}))) + .limit(elementsToUse).map(RealValue::new).collect(Collectors.toList()); + break; + case Short: + values = Arrays.stream(ArrayUtils.toObject((short[]) (value.getClass().isArray() ? value : new short[]{(short) value}))) + .limit(elementsToUse).map(ShortValue::new).collect(Collectors.toList()); + break; + case String: + values = Arrays.stream((String[]) (value.getClass().isArray() ? value : new String[]{(String) value})).limit(elementsToUse) + .map(StringValue::new).collect(Collectors.toList()); + break; + } + return new ArrayValue<>(values); + } else { + + + switch (type) { + + case Bool: + return new BooleanValue((Boolean) value); + case Byte: + return new ByteValue((Integer) value); + case Float: + return new FloatValue((Float) value); + case Int: + return new IntegerValue((Integer) value); + case Long: + return new LongValue((Long) value); + case Real: + return new RealValue((Double) value); + case Short: + return new ShortValue((Short) value); + case String: + return new StringValue((String) value); + } } throw new IllegalArgumentException("No mapping for value:" + value); } diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/external/ExternalReflectModuleHelper.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/external/ExternalReflectModuleHelper.java index 2b74b0e09..20a477457 100644 --- a/interpreter/src/main/java/org/intocps/maestro/interpreter/external/ExternalReflectModuleHelper.java +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/external/ExternalReflectModuleHelper.java @@ -21,7 +21,8 @@ public static Map createMembers(AModuleDeclaration module, Object throw new IllegalArgumentException("Target must not be null"); } - Function costumeArgMapper = t -> { + Function costumeArgMapper = tctxt -> { + PType t = tctxt.getArgType(); if (t instanceof ANameType) { if (((ANameType) t).getName().getText().equals("FMI3Instance")) { return new IArgMapping() { @@ -40,6 +41,11 @@ public ExternalReflectCallHelper.ArgMapping.InOut getDirection() { return ExternalReflectCallHelper.ArgMapping.InOut.Input; } + @Override + public void setDirection(ExternalReflectCallHelper.ArgMapping.InOut direction) { + + } + @Override public Object map(Value v) { if (v instanceof ExternalModuleValue) { @@ -54,9 +60,8 @@ public void mapOut(Value original, Object value) { } @Override - public Value mapOut(Object value) { - return new ExternalModuleValue<>(null, value) { - }; + public Value mapOut(Object value, Map outputArgs) { + return new ExternalModuleValue<>(null, value) {}; } @Override diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/external/IArgMapping.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/external/IArgMapping.java index 17e66e49c..487082b1e 100644 --- a/interpreter/src/main/java/org/intocps/maestro/interpreter/external/IArgMapping.java +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/external/IArgMapping.java @@ -2,18 +2,21 @@ import org.intocps.maestro.interpreter.values.Value; +import java.util.Map; + public interface IArgMapping { int getDimension(); long[] getLimits(); ExternalReflectCallHelper.ArgMapping.InOut getDirection(); + void setDirection(ExternalReflectCallHelper.ArgMapping.InOut direction); Object map(Value v); void mapOut(Value original, Object value); - Value mapOut(Object value); + Value mapOut(Object value, Map outputThroughReturn); Class getType(); diff --git a/maestro/src/test/resources/fmi3/reference/bounchingball/fmi3_bb.mabl b/maestro/src/test/resources/fmi3/reference/bounchingball/fmi3_bb.mabl index 774b95044..77ccf9407 100644 --- a/maestro/src/test/resources/fmi3/reference/bounchingball/fmi3_bb.mabl +++ b/maestro/src/test/resources/fmi3/reference/bounchingball/fmi3_bb.mabl @@ -1,16 +1,18 @@ simulation import FMI3; +import Logger; { FMI3 x1 =null; try { + Logger logger = load("Logger"); x1 = load("FMI3", "{1AE5E10D-9521-4DE3-80B9-D0EAAA7D5AF1}", "file:BouncingBall.fmu"); if (x1 == null) { error; } - string instanceName="fmi3functiontest"; + string instanceName="bb"; bool visible=true; bool loggingOn=true; @@ -23,13 +25,82 @@ import FMI3; { error "instance not created"; } - uint sv[3]={0,1,2}; + + uint sv_out_h=1; + uint sv_out_v=3; + uint sv_par_g=5; + uint sv_par_e=6; + int res=0; + + + + uint svs[2]={sv_par_g, sv_par_e}; + float values_r[2]={-9.81,0.7}; + res=instance.setFloat32(svs,values_r); + logger.log(3,"setFloat32 status %d",res); + + res=instance.enterInitializationMode(false, 0.0, 0.0, true,10.0); + logger.log(3,"enterInitializationMode status %d",res); + + res=instance.exitInitializationMode(); + logger.log(3,"exitInitializationMode status %d",res); + + res=instance.enterStepMode(); + logger.log(3,"enterStepMode status %d",res); + + + real step =0.1; + real time=0; + real end=10; + + bool nosetFMUStatePriorToCurrentPoint=false; + bool eventHandlingNeeded=false; + bool terminateSimulation=false; + bool earlyReturn=false; + real lastSuccessfulTime=0.0; + + svs[0]=sv_out_h; + svs[1]=sv_out_v; + while(time < end-step) + { + res = instance.doStep(time, + step, + nosetFMUStatePriorToCurrentPoint, + ref eventHandlingNeeded, + ref terminateSimulation, + ref earlyReturn, + ref lastSuccessfulTime); + logger.log(3,"doStep status %d, earlyreturn %b, lassSuccessfulTime %f",res,earlyReturn, lastSuccessfulTime); + + + res = instance.getFloat64(svs,ref values_r); + logger.log(3,"doStep status %d, h %f, v %f",res,values_r[0], values_r[1]); + + + time = time + step; + } + + //int doStep(real currentCommunicationPoint, real communicationStepSize, bool nosetFMUStatePriorToCurrentPoint, + // out bool eventHandlingNeeded,out bool terminateSimulation,out bool earlyReturn,out real lastSuccessfulTime); + + + //int getFloat64(uint valueReferences[], real values[]); + + //int setFloat32(uint valueReferences[], float values[]); + + res = instance.terminate(); + logger.log(3,"terminate status %d",res); + + + unload(logger); + + /* uint sv[3]={0,1,2}; int i1 = 1; float f1 = 1; byte b1 = 2; byte valu8[3]={100,0,0}; instance.setUInt8(sv,valu8); - +*/ x1.freeInstance(instance); } diff --git a/typechecker/src/main/resources/org/intocps/maestro/typechecker/FMI3.mabl b/typechecker/src/main/resources/org/intocps/maestro/typechecker/FMI3.mabl index f6064a471..6b66e0824 100644 --- a/typechecker/src/main/resources/org/intocps/maestro/typechecker/FMI3.mabl +++ b/typechecker/src/main/resources/org/intocps/maestro/typechecker/FMI3.mabl @@ -59,31 +59,31 @@ module FMI3Instance import FMU3State;{ /* getting and setting variable values */ /* tag::getters[] */ - int getFloat32(uint valueReferences[], float values[]); + int getFloat32(uint valueReferences[], out float values[]); - int getFloat64(uint valueReferences[], real values[]); + int getFloat64(uint valueReferences[],out real values[]); - int getInt8(uint valueReferences[], byte values[]); + int getInt8(uint valueReferences[], out byte values[]); - int getUInt8(uint valueReferences[], byte values[]); + int getUInt8(uint valueReferences[],out byte values[]); - int getInt16(uint valueReferences[], short values[]); + int getInt16(uint valueReferences[], out short values[]); - int getUInt16(uint valueReferences[], short values[]); + int getUInt16(uint valueReferences[],out short values[]); - int getInt32(uint valueReferences[], int values[]); + int getInt32(uint valueReferences[], out int values[]); - int getUInt32(uint valueReferences[], int values[]); + int getUInt32(uint valueReferences[], out int values[]); - int getInt64(uint valueReferences[], long values[]); + int getInt64(uint valueReferences[], out long values[]); - int getUInt64(uint valueReferences[], long values[]); + int getUInt64(uint valueReferences[], out long values[]); - int getBoolean(uint valueReferences[], bool values[]); + int getBoolean(uint valueReferences[],out bool values[]); - int getString(uint valueReferences[], string values[]); + int getString(uint valueReferences[],out string values[]); - int getBinary(uint valueReferences[], byte values[][]); + int getBinary(uint valueReferences[], out byte values[][]); /* end::getters[] */ /* tag::setters[] */ @@ -232,7 +232,7 @@ module FMI3Instance import FMU3State;{ int enterContinuousTimeMode(); /* end::EnterContinuousTimeMode[] */ - /* tag::CompletedIntegratorStep[] */ + /* tag::CompletedIntegratorget[] */ int completedIntegratorStep(bool nosetFMUStatePriorToCurrentPoint, bool[] enterEventMode, bool[] terminateSimulation); /* end::CompletedIntegratorStep[] */ From 3d36e80fb71dcd3963517e1fff58d02901b96200 Mon Sep 17 00:00:00 2001 From: Kenneth Lausdahl Date: Tue, 8 Aug 2023 10:57:50 +0200 Subject: [PATCH 10/54] added .venv to ignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 292ba7375..b9d0bd74a 100644 --- a/.gitignore +++ b/.gitignore @@ -114,4 +114,5 @@ __pycache__/ *$py.class /external_tester/venv/ -*.ci-friendly-pom.xml \ No newline at end of file +*.ci-friendly-pom.xml +.venv From fbef8adccae64fc92b63f094e17175b114adaaa1 Mon Sep 17 00:00:00 2001 From: Kenneth Lausdahl Date: Tue, 8 Aug 2023 11:00:28 +0200 Subject: [PATCH 11/54] updated the assembly and surfire plugin versions --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index ad58bbf8c..ea038e62d 100644 --- a/pom.xml +++ b/pom.xml @@ -279,7 +279,7 @@ maven-surefire-plugin - 3.0.0-M5 + 3.1.2 true @@ -317,7 +317,7 @@ org.apache.maven.plugins maven-assembly-plugin - 3.4.2 + 3.6.0 From b0b49e3628e675f3ed57ce41eeb0b37602f996de Mon Sep 17 00:00:00 2001 From: Kenneth Lausdahl Date: Tue, 8 Aug 2023 11:33:31 +0200 Subject: [PATCH 12/54] updated kotlin and scala versions --- maestro-webapi/pom.xml | 11 +++++++++++ plugins/topologicalsorting/pom.xml | 3 +-- pom.xml | 4 ++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/maestro-webapi/pom.xml b/maestro-webapi/pom.xml index a80939f69..61086b7fd 100644 --- a/maestro-webapi/pom.xml +++ b/maestro-webapi/pom.xml @@ -196,6 +196,17 @@ 2.9.2 + + org.jetbrains.kotlin + kotlin-stdlib + ${kotlin.version} + + + org.jetbrains.kotlin + kotlin-reflect + ${kotlin.version} + + diff --git a/plugins/topologicalsorting/pom.xml b/plugins/topologicalsorting/pom.xml index 6d0863739..631d32351 100644 --- a/plugins/topologicalsorting/pom.xml +++ b/plugins/topologicalsorting/pom.xml @@ -67,7 +67,7 @@ net.alchim31.maven scala-maven-plugin - 4.4.0 + 4.8.1 @@ -87,7 +87,6 @@ org.apache.maven.plugins maven-surefire-plugin - 2.21.0 true diff --git a/pom.xml b/pom.xml index ea038e62d..1e8896238 100644 --- a/pom.xml +++ b/pom.xml @@ -26,8 +26,8 @@ 2.17.1 1.3.6-SNAPSHOT 1.0.10 - 1.5.0 - 2.13.5 + 1.9.0 + 2.13.11 11 1.7.10 2.13.3 From dfee2f8bf7389c6445e40acfa26f3e74c2af683b Mon Sep 17 00:00:00 2001 From: Kenneth Lausdahl Date: Tue, 8 Aug 2023 11:52:25 +0200 Subject: [PATCH 13/54] updated sha1 for snapshot --- .github/workflows/maven.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 2ba7ad5c2..6bbb7e83e 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -172,7 +172,7 @@ jobs: - name: Maven Deploy feature SNAPSHOT if: github.event_name == 'push' && (github.ref != 'refs/heads/development' && github.ref != 'refs/heads/master' ) - run: mvn -P au -B deploy -Dsha1=-`git rev-parse --abbrev-ref HEAD | sed "s|/|-|g"` -fae -Dgpg.passphrase=${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }} + run: mvn -P au -B deploy -Dsha1=-`git rev-parse --abbrev-ref HEAD | sed "s|/|-|g;s|#||g;s|<||g;s|>||g;s|:||g;s|\"||g;s|/||g;s|\|||g;s|?||g;s|*||g;s|;||g"` -fae -Dgpg.passphrase=${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }} env: MAVEN_USERNAME: ${{ secrets.ARTIFACTORY_USERNAME }} MAVEN_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }} From 6ee0bae98f218fdf57a6a04b6330d455ffe2a692 Mon Sep 17 00:00:00 2001 From: Kenneth Lausdahl Date: Tue, 8 Aug 2023 13:59:12 +0200 Subject: [PATCH 14/54] updated the fmi3 model description to also resolve for version 3 and added empty create calls and types for fmu3 --- .../maestro/fmi/Fmi3SchemaProvider.java | 30 +++ fmi/src/main/kotlin/ModelDescription.kt | 10 +- .../fmi/fmi2/Fmi2ModelDescriptionUnit.kt | 5 +- .../maestro/fmi/fmi3/Fmi3ModelDescription.kt | 25 +- .../ModelDefinitionSchemaValidatorTests.java | 5 +- .../framework/fmi2/api/Fmi2Builder.java | 11 + .../scoping/DynamicActiveBuilderScope.java | 11 + .../fmi2/api/mabl/scoping/IMablScope.java | 4 + .../fmi2/api/mabl/scoping/ScopeFmi2Api.java | 11 + .../mabl/variables/FmuVariableFmi3Api.java | 126 ++++++++++ .../org/intocps/maestro/BuilderFmi3Test.java | 228 ++++++++++++++++++ .../fmi3/Fmi3ModuleReferenceFmusTest.java | 10 +- 12 files changed, 454 insertions(+), 22 deletions(-) create mode 100644 fmi/src/main/java/org/intocps/maestro/fmi/Fmi3SchemaProvider.java create mode 100644 frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/FmuVariableFmi3Api.java create mode 100644 maestro/src/test/java/org/intocps/maestro/BuilderFmi3Test.java diff --git a/fmi/src/main/java/org/intocps/maestro/fmi/Fmi3SchemaProvider.java b/fmi/src/main/java/org/intocps/maestro/fmi/Fmi3SchemaProvider.java new file mode 100644 index 000000000..ddb111937 --- /dev/null +++ b/fmi/src/main/java/org/intocps/maestro/fmi/Fmi3SchemaProvider.java @@ -0,0 +1,30 @@ +package org.intocps.maestro.fmi; + +import org.intocps.fmi.jnifmuapi.xml.SchemaProvider; + +import java.io.InputStream; + +/** + * This should be moved to the native place where Fmi3Schema is located + */ +@Deprecated +public class Fmi3SchemaProvider implements SchemaProvider { + + + public InputStream getSchema() { + return getSchema("fmi3ModelDescription.xsd"); + } + + public InputStream getSchema(String path) { + + + InputStream is = org.intocps.fmi.jnifmuapi.fmi3.schemas.Fmi3Schema.class.getResourceAsStream(path); + + + return is; + + } + + +} + diff --git a/fmi/src/main/kotlin/ModelDescription.kt b/fmi/src/main/kotlin/ModelDescription.kt index 980446964..7122ade04 100644 --- a/fmi/src/main/kotlin/ModelDescription.kt +++ b/fmi/src/main/kotlin/ModelDescription.kt @@ -1,6 +1,6 @@ package org.intocps.maestro.fmi -import org.intocps.fmi.jnifmuapi.fmi2.schemas.Fmi2Schema +import org.intocps.fmi.jnifmuapi.xml.SchemaProvider import org.intocps.fmi.jnifmuapi.xml.SchemaResourceResolver import org.intocps.maestro.fmi.xml.NamedNodeMapIterator import org.intocps.maestro.fmi.xml.NodeIterator @@ -27,7 +27,7 @@ abstract class ModelDescription SAXException::class, IOException::class, ParserConfigurationException::class -) constructor(xmlInputStream: InputStream, schemaModelDescription: Source) { +) constructor(xmlInputStream: InputStream, schemaModelDescription: Source, provider: SchemaProvider) { private val DEBUG = false @JvmField @@ -38,7 +38,7 @@ abstract class ModelDescription init { val docBuilderFactory = DocumentBuilderFactory.newInstance() - validateAgainstXSD(StreamSource(xmlInputStream), schemaModelDescription) + validateAgainstXSD(StreamSource(xmlInputStream), schemaModelDescription, provider) xmlInputStream.reset() doc = docBuilderFactory.newDocumentBuilder().parse(xmlInputStream) val xPathfactory = XPathFactory.newInstance() @@ -173,9 +173,9 @@ abstract class ModelDescription companion object { @Throws(SAXException::class, IOException::class) - fun validateAgainstXSD(document: Source, schemaSource: Source) { + fun validateAgainstXSD(document: Source, schemaSource: Source, provider: SchemaProvider) { SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI).run { - this.resourceResolver = SchemaResourceResolver(Fmi2Schema()) + this.resourceResolver = SchemaResourceResolver(provider) this.newSchema(schemaSource).newValidator().validate(document) } } diff --git a/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi2/Fmi2ModelDescriptionUnit.kt b/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi2/Fmi2ModelDescriptionUnit.kt index 3bbb48ae7..3ccc1cca1 100644 --- a/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi2/Fmi2ModelDescriptionUnit.kt +++ b/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi2/Fmi2ModelDescriptionUnit.kt @@ -1,5 +1,6 @@ package org.intocps.maestro.fmi.fmi2 +import org.intocps.fmi.jnifmuapi.fmi2.schemas.Fmi2Schema import org.intocps.maestro.fmi.ModelDescription import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi2.Fmi2Unit import org.intocps.maestro.fmi.xml.NodeIterator @@ -18,7 +19,7 @@ abstract class Fmi2ModelDescriptionUnit : ModelDescription { ParserConfigurationException::class ) constructor(xmlInputStream: InputStream, schemaModelDescription: Source) : super( - xmlInputStream, schemaModelDescription + xmlInputStream, schemaModelDescription, Fmi2Schema() ) // Unit definitions attribute @@ -33,9 +34,11 @@ abstract class Fmi2ModelDescriptionUnit : ModelDescription { "BaseUnit" -> { setBaseUnit(parseBaseUnit(childNode)) } + "DisplayUnit" -> { // displayUnits.add(parseDisplayUnit(childNode)) } + "Annotations" -> { } } diff --git a/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi3/Fmi3ModelDescription.kt b/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi3/Fmi3ModelDescription.kt index 767ba403d..9b0d42ab5 100644 --- a/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi3/Fmi3ModelDescription.kt +++ b/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi3/Fmi3ModelDescription.kt @@ -1,12 +1,12 @@ package org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3 import org.apache.commons.io.IOUtils +import org.intocps.fmi.jnifmuapi.fmi3.schemas.Fmi3Schema +import org.intocps.maestro.fmi.Fmi3SchemaProvider import org.intocps.maestro.fmi.ModelDescription import org.intocps.maestro.fmi.xml.NodeIterator import org.w3c.dom.Node import java.io.ByteArrayInputStream -import java.io.File -import java.io.FileInputStream import java.io.InputStream import java.lang.reflect.InvocationTargetException import javax.xml.transform.stream.StreamSource @@ -21,17 +21,17 @@ class Fmi3ModelDescription : ModelDescription { private var derivatives: List? = null private var derivativeToDerivativeSource: Map? = null - constructor(file: File) : super( - ByteArrayInputStream(IOUtils.toByteArray(FileInputStream(file))), StreamSource( - Fmi3ModelDescription::class.java.classLoader.getResourceAsStream( - "fmi3ModelDescription.xsd" - ) - ) - ) +// constructor(file: File) : super( +// ByteArrayInputStream(IOUtils.toByteArray(FileInputStream(file))), StreamSource( +// Fmi3ModelDescription::class.java.classLoader.getResourceAsStream( +// "fmi3ModelDescription.xsd" +// ) +// ) +// ) constructor(file: InputStream) : super( file, - StreamSource(Fmi3ModelDescription::class.java.classLoader.getResourceAsStream("fmi3ModelDescription.xsd")) + StreamSource(ByteArrayInputStream(IOUtils.toByteArray(Fmi3Schema().schema))), Fmi3SchemaProvider() ) fun getScalarVariables(): List { @@ -100,12 +100,15 @@ class Fmi3ModelDescription : ModelDescription { Fmi3ModelStructureElementEnum.Output -> variable.outputDependencies.putAll( dependencyScalarVariableToDependencyKinds ) + Fmi3ModelStructureElementEnum.ContinuousStateDerivative -> variable.derivativesDependencies.putAll( dependencyScalarVariableToDependencyKinds ) + Fmi3ModelStructureElementEnum.ClockedState -> { //TODO: Implement } + Fmi3ModelStructureElementEnum.InitialUnknown -> variable.initialUnknownsDependencies.putAll( dependencyScalarVariableToDependencyKinds ) @@ -218,9 +221,11 @@ class Fmi3ModelDescription : ModelDescription { "BaseUnit" -> { setBaseUnit(parseBaseUnit(childNode)) } + "DisplayUnit" -> { displayUnits.add(parseDisplayUnit(childNode)) } + "Annotations" -> { } } diff --git a/fmi/src/test/java/org/intocps/maestro/fmi/ModelDefinitionSchemaValidatorTests.java b/fmi/src/test/java/org/intocps/maestro/fmi/ModelDefinitionSchemaValidatorTests.java index 81e4fa3a5..4097de7bb 100644 --- a/fmi/src/test/java/org/intocps/maestro/fmi/ModelDefinitionSchemaValidatorTests.java +++ b/fmi/src/test/java/org/intocps/maestro/fmi/ModelDefinitionSchemaValidatorTests.java @@ -35,6 +35,7 @@ package org.intocps.maestro.fmi; import org.apache.commons.io.FileUtils; +import org.intocps.fmi.jnifmuapi.fmi2.schemas.Fmi2Schema; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.xml.sax.SAXException; @@ -57,7 +58,7 @@ public void test() throws IOException, SAXException { InputStream resourceAsStream = Fmi2ModelDescription.class.getClassLoader().getResourceAsStream("fmi2ModelDescription.xsd"); try { - Fmi2ModelDescription.Companion.validateAgainstXSD(new StreamSource(in), new StreamSource(resourceAsStream)); + Fmi2ModelDescription.Companion.validateAgainstXSD(new StreamSource(in), new StreamSource(resourceAsStream), new Fmi2Schema()); } catch (SAXParseException e) { } @@ -72,7 +73,7 @@ public void modelDescriptionWithUnitDefinitionInWrongPosition() { InputStream resourceAsStream = Fmi2ModelDescription.class.getClassLoader().getResourceAsStream("fmi2ModelDescription.xsd"); - Fmi2ModelDescription.Companion.validateAgainstXSD(new StreamSource(in), new StreamSource(resourceAsStream)); + Fmi2ModelDescription.Companion.validateAgainstXSD(new StreamSource(in), new StreamSource(resourceAsStream), new Fmi2Schema()); }); } } diff --git a/frameworks/builder/src/main/java/org/intocps/maestro/framework/fmi2/api/Fmi2Builder.java b/frameworks/builder/src/main/java/org/intocps/maestro/framework/fmi2/api/Fmi2Builder.java index aa302a355..3c15dcb2e 100644 --- a/frameworks/builder/src/main/java/org/intocps/maestro/framework/fmi2/api/Fmi2Builder.java +++ b/frameworks/builder/src/main/java/org/intocps/maestro/framework/fmi2/api/Fmi2Builder.java @@ -267,6 +267,8 @@ interface Scope extends Scoping { Fmu2Variable createFMU(String name, String loaderName, String... args) throws Exception; + Fmu3Variable createFMU3(String name, String loaderName, String... args) throws Exception; + void markTransferPoint(String... names); void addTransferAs(String... names); @@ -518,6 +520,15 @@ Fmi2ComponentVariable instantiate(String namePrefix, Fmi2Builder.TryScope scope); + } + + /** + * Handle for an fmu for the creation of component + */ + interface Fmu3Variable extends Variable> { + + + } /** diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/DynamicActiveBuilderScope.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/DynamicActiveBuilderScope.java index d15c4c49e..86f7adbb4 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/DynamicActiveBuilderScope.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/DynamicActiveBuilderScope.java @@ -2,6 +2,7 @@ import org.intocps.maestro.ast.node.PStm; import org.intocps.maestro.fmi.Fmi2ModelDescription; +import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; import org.intocps.maestro.framework.fmi2.api.mabl.variables.*; @@ -209,6 +210,16 @@ public FmuVariableFmi2Api createFMU(String name, String loaderName, String... ar return activeScope.createFMU(name, loaderName, args); } + @Override + public FmuVariableFmi3Api createFMU(String name, Fmi3ModelDescription modelDescription, URI path) throws Exception { + return activeScope.createFMU(name, modelDescription, path); + } + + @Override + public FmuVariableFmi3Api createFMU3(String name, String loaderName, String... args) throws Exception { + return activeScope.createFMU3(name, loaderName, args); + } + @Override public void markTransferPoint(String... names) { activeScope.markTransferPoint(names); diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/IMablScope.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/IMablScope.java index 3677f37d6..f3f010ed5 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/IMablScope.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/IMablScope.java @@ -2,6 +2,7 @@ import org.intocps.maestro.ast.node.PStm; import org.intocps.maestro.fmi.Fmi2ModelDescription; +import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; import org.intocps.maestro.framework.fmi2.api.mabl.variables.*; @@ -97,6 +98,9 @@ public interface IMablScope extends Fmi2Builder.Scope { @Override FmuVariableFmi2Api createFMU(String name, String loaderName, String... args) throws Exception; + FmuVariableFmi3Api createFMU(String name, Fmi3ModelDescription modelDescription, URI path) throws Exception; + FmuVariableFmi3Api createFMU3(String name, String loaderName, String... args) throws Exception; + Var copy(String name, Var variable); /** diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/ScopeFmi2Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/ScopeFmi2Api.java index de441e8a6..407b79240 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/ScopeFmi2Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/ScopeFmi2Api.java @@ -5,6 +5,7 @@ import org.intocps.maestro.ast.MableAstFactory; import org.intocps.maestro.ast.node.*; import org.intocps.maestro.fmi.Fmi2ModelDescription; +import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; import org.intocps.maestro.framework.fmi2.api.mabl.MablApiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.PredicateFmi2Api; @@ -495,6 +496,16 @@ public FmuVariableFmi2Api createFMU(String name, String loaderName, String... ar return VariableCreatorFmi2Api.createFMU(builder, builder.getNameGenerator(), builder.getDynamicScope(), name, loaderName, args, this); } + @Override + public FmuVariableFmi3Api createFMU(String name, Fmi3ModelDescription modelDescription, URI path) throws Exception { + return null; + } + + @Override + public FmuVariableFmi3Api createFMU3(String name, String loaderName, String... args) throws Exception { + return null; + } + @Override public void markTransferPoint(String... names) { diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/FmuVariableFmi3Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/FmuVariableFmi3Api.java new file mode 100644 index 000000000..d056455e8 --- /dev/null +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/FmuVariableFmi3Api.java @@ -0,0 +1,126 @@ +package org.intocps.maestro.framework.fmi2.api.mabl.variables; + +import org.intocps.maestro.ast.MableAstFactory; +import org.intocps.maestro.ast.node.*; +import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.mabl.MablApiBuilder; +import org.intocps.maestro.framework.fmi2.api.mabl.ModelDescriptionContext; +import org.intocps.maestro.framework.fmi2.api.mabl.PredicateFmi2Api; +import org.intocps.maestro.framework.fmi2.api.mabl.scoping.IMablScope; +import org.intocps.maestro.framework.fmi2.api.mabl.scoping.ScopeFmi2Api; +import org.intocps.maestro.framework.fmi2.api.mabl.scoping.TryMaBlScope; + +import static org.intocps.maestro.ast.MableAstFactory.*; +import static org.intocps.maestro.ast.MableBuilder.call; +import static org.intocps.maestro.ast.MableBuilder.newVariable; + +public class FmuVariableFmi3Api extends VariableFmi2Api> implements Fmi2Builder.Fmu3Variable { + public FmuVariableFmi3Api(PStm declaration, PType type, IMablScope declaredScope, Fmi2Builder.DynamicActiveScope dynamicScope, + PStateDesignator designator, PExp referenceExp) { + super(declaration, type, declaredScope, dynamicScope, designator, referenceExp); + } + + // private final ModelDescriptionContext modelDescriptionContext; +// private final MablApiBuilder builder; +// private String fmuIdentifier; +// +// public FmuVariableFmi2Api(String fmuIdentifier, MablApiBuilder builder, ModelDescriptionContext modelDescriptionContext, PStm declaration, +// PType type, IMablScope declaredScope, Fmi2Builder.DynamicActiveScope dynamicScope, PStateDesignator designator, PExp referenceExp) { +// this(builder, modelDescriptionContext, declaration, type, declaredScope, dynamicScope, designator, referenceExp); +// this.fmuIdentifier = fmuIdentifier; +// } +// +// public FmuVariableFmi2Api(MablApiBuilder builder, ModelDescriptionContext modelDescriptionContext, PStm declaration, PType type, +// IMablScope declaredScope, Fmi2Builder.DynamicActiveScope dynamicScope, PStateDesignator designator, PExp referenceExp) { +// super(declaration, type, declaredScope, dynamicScope, designator, referenceExp); +// this.builder = builder; +// this.modelDescriptionContext = modelDescriptionContext; +// } +// +// public ModelDescriptionContext getModelDescriptionContext() { +// return modelDescriptionContext; +// } +// +// @Override +// public ComponentVariableFmi2Api instantiate(String name, String environmentName) { +// IMablScope scope = builder.getDynamicScope().getActiveScope(); +// return instantiate(name, scope.findParentScope(TryMaBlScope.class), scope, environmentName); +// } +// +// @Override +// public ComponentVariableFmi2Api instantiate(String name) { +// IMablScope scope = builder.getDynamicScope().getActiveScope(); +// return instantiate(name, scope.findParentScope(TryMaBlScope.class), scope); +// } +// +// +// @Override +// public ComponentVariableFmi2Api instantiate(String namePrefix, Fmi2Builder.TryScope enclosingTryScope, Fmi2Builder.Scope scope, +// String environmentName) { +// return instantiate(namePrefix, enclosingTryScope, scope, environmentName, true); +// } +// +// @Override +// public ComponentVariableFmi2Api instantiate(String namePrefix, Fmi2Builder.TryScope enclosingTryScope, Fmi2Builder.Scope scope, +// String environmentName, boolean loggingOn) { +// +// String name = builder.getNameGenerator().getName(namePrefix); +// //TODO: Extract bool visible and bool loggingOn from configuration +// var var = newVariable(name, newANameType("FMI2Component"), newNullExp()); +// +// PStm instantiateAssign = newAAssignmentStm(newAIdentifierStateDesignator(name), +// call(getReferenceExp().clone(), "instantiate", newAStringLiteralExp(name), newABoolLiteralExp(true), newABoolLiteralExp(loggingOn))); +// +// +// if (enclosingTryScope == null) { +// throw new IllegalArgumentException("Call to instantiate is not allowed with a null enclosing try scope"); +// } +// +// +// TryMaBlScope mTryScope = (TryMaBlScope) enclosingTryScope; +// mTryScope.parent().addBefore(mTryScope.getDeclaration(), var); +// +// ComponentVariableFmi2Api compVar; +// if (environmentName == null) { +// compVar = new ComponentVariableFmi2Api(var, this, name, this.modelDescriptionContext, builder, mTryScope.parent(), +// newAIdentifierStateDesignator(newAIdentifier(name)), newAIdentifierExp(name)); +// } else { +// +// AInstanceMappingStm mapping = newAInstanceMappingStm(newAIdentifier(name), environmentName); +// compVar = new ComponentVariableFmi2Api(var, this, name, this.modelDescriptionContext, builder, mTryScope.parent(), +// newAIdentifierStateDesignator(newAIdentifier(name)), newAIdentifierExp(name), environmentName); +// scope.add(mapping); +// } +// +// scope.add(instantiateAssign); +// +// mTryScope.getFinallyBody().addAfterOrTop(null, newIf(newNotEqual(compVar.getReferenceExp().clone(), newNullExp()), +// newABlockStm(MableAstFactory.newExpressionStm(call(getReferenceExp().clone(), "freeInstance", compVar.getReferenceExp().clone())), +// newAAssignmentStm(compVar.getDesignatorClone(), newNullExp())), null)); +// +// scope.activate(); +// +// if (builder.getSettings().fmiErrorHandlingEnabled) { +// ScopeFmi2Api thenScope = +// (ScopeFmi2Api) scope.enterIf(new PredicateFmi2Api(newEqual(compVar.getReferenceExp().clone(), newNullExp()))).enterThen(); +// +// builder.getLogger().error(thenScope, "Instantiate failed on fmu: '%s' for instance: '%s'", this.getFmuIdentifier(), namePrefix); +// thenScope.add(new AErrorStm( +// newAStringLiteralExp(String.format("Instantiate failed on fmu: '%s' for instance: '%s'", this.getFmuIdentifier(), namePrefix)))); +// thenScope.leave(); +// } +// +// ((IMablScope) scope).registerComponentVariableFmi2Api(compVar); +// +// return compVar; +// } +// +// @Override +// public ComponentVariableFmi2Api instantiate(String namePrefix, Fmi2Builder.TryScope enclosingTryScope, Fmi2Builder.Scope scope) { +// return instantiate(namePrefix, enclosingTryScope, scope, null); +// } +// +// public String getFmuIdentifier() { +// return fmuIdentifier; +// } +} \ No newline at end of file diff --git a/maestro/src/test/java/org/intocps/maestro/BuilderFmi3Test.java b/maestro/src/test/java/org/intocps/maestro/BuilderFmi3Test.java new file mode 100644 index 000000000..562337156 --- /dev/null +++ b/maestro/src/test/java/org/intocps/maestro/BuilderFmi3Test.java @@ -0,0 +1,228 @@ +package org.intocps.maestro; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.intocps.fmi.jnifmuapi.fmi3.Fmu3; +import org.intocps.maestro.ast.display.PrettyPrinter; +import org.intocps.maestro.ast.node.ASimulationSpecificationCompilationUnit; +import org.intocps.maestro.ast.node.PStm; +import org.intocps.maestro.core.Framework; +import org.intocps.maestro.core.messages.ErrorReporter; +import org.intocps.maestro.core.messages.IErrorReporter; +import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; +import org.intocps.maestro.fmi3.Fmi3ModuleReferenceFmusTest; +import org.intocps.maestro.framework.fmi2.Fmi2SimulationEnvironment; +import org.intocps.maestro.framework.fmi2.Fmi2SimulationEnvironmentConfiguration; +import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.mabl.LoggerFmi2Api; +import org.intocps.maestro.framework.fmi2.api.mabl.MablApiBuilder; +import org.intocps.maestro.framework.fmi2.api.mabl.PortFmi2Api; +import org.intocps.maestro.framework.fmi2.api.mabl.scoping.DynamicActiveBuilderScope; +import org.intocps.maestro.framework.fmi2.api.mabl.variables.ComponentVariableFmi2Api; +import org.intocps.maestro.framework.fmi2.api.mabl.variables.FmuVariableFmi2Api; +import org.intocps.maestro.framework.fmi2.api.mabl.variables.VariableFmi2Api; +import org.intocps.maestro.interpreter.DefaultExternalValueFactory; +import org.intocps.maestro.interpreter.MableInterpreter; +import org.intocps.maestro.typechecker.TypeChecker; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintWriter; +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.Map; +import java.util.Objects; + +public class BuilderFmi3Test { + + @BeforeAll + public static void downloadFmus() throws IOException { + Fmi3ModuleReferenceFmusTest.downloadReferenceFmus(); + + } + + @Test + public void wt() throws Exception { + + InputStream is = this.getClass().getClassLoader().getResourceAsStream("buildertester/buildertester.json"); + Fmi2SimulationEnvironmentConfiguration simulationEnvironmentConfiguration = + Fmi2SimulationEnvironmentConfiguration.createFromJsonString(new String(Objects.requireNonNull(is).readAllBytes())); + + + Fmi2SimulationEnvironment env = Fmi2SimulationEnvironment.of(simulationEnvironmentConfiguration, new IErrorReporter.SilentReporter()); + + MablApiBuilder builder = new MablApiBuilder(); + + /* Fmi2Builder.RuntimeModule logger = builder.loadRuntimeModule("Logger"); + Fmi2Builder.RuntimeFunction func = + builder.getFunctionBuilder().setName("log").addArgument("msg", Fmi2Builder.RuntimeFunction.FunctionType.Type.String) + .setReturnType(Fmi2Builder.RuntimeFunction.FunctionType.Type.Void).build(); + Fmi2Builder.RuntimeFunction func2 = + builder.getFunctionBuilder().setName("log").addArgument("msg", Fmi2Builder.RuntimeFunction.FunctionType.Type.String) + .addArgument("code", Fmi2Builder.RuntimeFunction.FunctionType.Type.Int) + .addArgument("other", Fmi2Builder.RuntimeFunction.FunctionType.Type.Int) + .setReturnType(Fmi2Builder.RuntimeFunction.FunctionType.Type.Int).build(); + logger.initialize(func, func2); + logger.call(func, "ddd"); + */ + + LoggerFmi2Api logger = builder.getLogger(); + + Fmi2Builder.IntVariable v8 = builder.getDynamicScope().enterTry().enter().store(6); + // Fmi2Builder.Variable logReturnValue = logger.call(func2, "ddd", 6, v8); + + + URI ballUri = new File("target/Fmi3ModuleReferenceFmusTest/cache/BouncingBall.fmu").getAbsoluteFile().toURI(); + Fmu3 ball = new Fmu3(new File(ballUri)); + Fmi3ModelDescription md3Ball = new Fmi3ModelDescription(ball.getModelDescription()); + + + builder.getDynamicScope().createFMU("ball", md3Ball, ballUri); + + // Create the two FMUs + FmuVariableFmi2Api controllerFMU = builder.getDynamicScope() + .createFMU("controllerFMU", env.getModelDescription("{controllerFMU}"), env.getUriFromFMUName("{controllerFMU}")); + FmuVariableFmi2Api tankFMU = + builder.getDynamicScope().createFMU("tankFMU", env.getModelDescription("{tankFMU}"), env.getUriFromFMUName("{tankFMU}")); + + // Create the controller and tank instanes + ComponentVariableFmi2Api controller = controllerFMU.instantiate("controller"); + ComponentVariableFmi2Api tank = tankFMU.instantiate("tank"); + DynamicActiveBuilderScope dynamicScope = builder.getDynamicScope(); + + tank.setupExperiment(0d, 10d, null); + controller.setupExperiment(0d, 10d, null); + + controller.enterInitializationMode(); + tank.enterInitializationMode(); + + controller.exitInitializationMode(); + tank.exitInitializationMode(); + /* + IMablScope scope1 = dynamicScope.getActiveScope(); + for (int i = 0; i < 4; i++) { + dynamicScope.enterIf(null); + AMablFmi2ComponentAPI tank2 = tankFMU.create("tank"); + } + scope1.activate();*/ + ComponentVariableFmi2Api tank2 = tankFMU.instantiate("tank"); + + + controller.getPort("valve").linkTo(tank.getPort("valvecontrol")); + tank.getPort("level").linkTo(controller.getPort("level")); + + Map> allVars = tank.get(); + tank.share(allVars); + + + controller.getAndShare("valve"); + controller.getAndShare(); + + tank.setLinked(); + // tank.set(); + Fmi2Builder.DoubleVariable var = dynamicScope.store(123.123); + Fmi2Builder.DoubleVariable current_time_point = dynamicScope.store(0.0); + Fmi2Builder.DoubleVariable step = dynamicScope.store(0.1); + tank.step(current_time_point, step); + //Fmi2Builder.StateVariable s = tank.getState(); + + logger.warn("Something is wrong %f -- %f. Fmu %s, Instance %s", 1.3, step, controllerFMU, controller); + //s.set(); + //s.destroy(); + + //no this will not stay this way + // tank.set(tank.getPort("valvecontrol"), new AMablValue(newBoleanType(), true)); + + var.set(456.678); + // PortVariableMapImpl allVars2 = new PortVariableMapImpl<>(); + // allVars2.put(allVars.keySet().iterator().next(), var); + //tank.set(allVars); + + + // controllerFMU.unload(); + // tankFMU.unload(); + // logger.destroy(); + ASimulationSpecificationCompilationUnit program = builder.build(); + + String test = PrettyPrinter.print(program); + + System.out.println(PrettyPrinter.printLineNumbers(program)); + + File workingDirectory = new File("target/apitest"); + workingDirectory.mkdirs(); + File specFile = new File(workingDirectory, "m.mabl"); + FileUtils.write(specFile, test, StandardCharsets.UTF_8); + Mabl mabl = new Mabl(workingDirectory, workingDirectory); + IErrorReporter reporter = new ErrorReporter(); + mabl.setReporter(reporter); + mabl.setVerbose(true); + + mabl.parse(Collections.singletonList(specFile)); + + var tcRes = mabl.typeCheck(); + mabl.verify(Framework.FMI2); + if (reporter.getErrorCount() > 0) { + reporter.printErrors(new PrintWriter(System.err, true)); + Assertions.fail(); + } + mabl.dump(workingDirectory); + new MableInterpreter(new DefaultExternalValueFactory(workingDirectory, name -> TypeChecker.findModule(tcRes.getValue(), name), + IOUtils.toInputStream(mabl.getRuntimeDataAsJsonString(), StandardCharsets.UTF_8))).execute(mabl.getMainSimulationUnit()); + + } + + public interface Ext { + //void initialize(Fmi2Builder.Variable owner, List declaredFuncs); + + //not sure how to allow a mix of double, int and var except for object + void callVoid(ExtFunc func, Object... args); + + void call(ExtFunc func, Object... args); + + void destroy(); + } + + public interface ExtFunc { + String getName(); + + String getArgNames(); + + Class getArgTypes(); + } + + static class Logger extends ExternalVariable { + final ExtFunc logFunc = null; + + void log(Level level, String message, Fmi2Builder.IntVariable errorCode) { + this.callVoid(logFunc, level == Level.Debug ? 1 : 0, message, errorCode); + } + + enum Level { + Info, + Debug + } + } + + static class ExternalVariable implements Ext { + + @Override + public void callVoid(ExtFunc func, Object... args) { + + } + + @Override + public void call(ExtFunc func, Object... args) { + + } + + @Override + public void destroy() { + + } + } +} \ No newline at end of file diff --git a/maestro/src/test/java/org/intocps/maestro/fmi3/Fmi3ModuleReferenceFmusTest.java b/maestro/src/test/java/org/intocps/maestro/fmi3/Fmi3ModuleReferenceFmusTest.java index 1c74d313a..327804467 100644 --- a/maestro/src/test/java/org/intocps/maestro/fmi3/Fmi3ModuleReferenceFmusTest.java +++ b/maestro/src/test/java/org/intocps/maestro/fmi3/Fmi3ModuleReferenceFmusTest.java @@ -25,7 +25,7 @@ public class Fmi3ModuleReferenceFmusTest extends FullSpecTest { private static Stream data() { - return Arrays.stream(Objects.requireNonNull(Paths.get("src", "test", "resources", "fmi3","reference").toFile().listFiles())) + return Arrays.stream(Objects.requireNonNull(Paths.get("src", "test", "resources", "fmi3", "reference").toFile().listFiles())) .filter(n -> !n.getName().startsWith(".")).filter(hasMablSpec).map(f -> Arguments.arguments(f.getName(), f)); } @@ -52,12 +52,14 @@ protected List getSpecificationFiles(File specFolder) { return specFiles; } -final static Path destination = Paths.get("target", Fmi3ModuleReferenceFmusTest.class.getSimpleName(), "cache"); + + final static Path destination = Paths.get("target", Fmi3ModuleReferenceFmusTest.class.getSimpleName(), "cache"); + @BeforeAll public static void downloadReferenceFmus() throws IOException { final String referenceFmuBundle = "https://github.com/modelica/Reference-FMUs/releases/download/v0.0.23/Reference-FMUs-0.0.23.zip"; - Path referenceFmuZipPath = destination.resolve( "Reference-FMUs.zip"); + Path referenceFmuZipPath = destination.resolve("Reference-FMUs.zip"); if (referenceFmuZipPath.toFile().exists()) { return; } @@ -66,7 +68,7 @@ public static void downloadReferenceFmus() throws IOException { FileUtils.copyURLToFile(new URL(referenceFmuBundle), referenceFmuZipPath.toFile()); -// Path destination = referenceFmuZipPath.getParent(); + // Path destination = referenceFmuZipPath.getParent(); ZipInputStream zipIn = new ZipInputStream(new FileInputStream(referenceFmuZipPath.toFile())); ZipEntry entry = zipIn.getNextEntry(); From ea12c23f9a13c8d28af1127495af4a47d3cbfb99 Mon Sep 17 00:00:00 2001 From: Kenneth Lausdahl Date: Thu, 17 Aug 2023 12:04:28 +0200 Subject: [PATCH 15/54] remove deployment for all builds as artifactory is broken --- .github/workflows/maven.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 6bbb7e83e..2da7633ea 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -170,17 +170,17 @@ jobs: maven-version: ${{ ENV.MAVEN_VERSION }} - - name: Maven Deploy feature SNAPSHOT + - name: Maven Package feature SNAPSHOT if: github.event_name == 'push' && (github.ref != 'refs/heads/development' && github.ref != 'refs/heads/master' ) - run: mvn -P au -B deploy -Dsha1=-`git rev-parse --abbrev-ref HEAD | sed "s|/|-|g;s|#||g;s|<||g;s|>||g;s|:||g;s|\"||g;s|/||g;s|\|||g;s|?||g;s|*||g;s|;||g"` -fae -Dgpg.passphrase=${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }} + run: mvn -P au -B package -Dsha1=-`git rev-parse --abbrev-ref HEAD | sed "s|/|-|g;s|#||g;s|<||g;s|>||g;s|:||g;s|\"||g;s|/||g;s|\|||g;s|?||g;s|*||g;s|;||g"` -fae -Dgpg.passphrase=${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }} env: MAVEN_USERNAME: ${{ secrets.ARTIFACTORY_USERNAME }} MAVEN_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }} MAVEN_GPG_PASSPHRASE: ${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }} - - name: Maven Deploy SNAPSHOT + - name: Maven Package SNAPSHOT if: github.event_name == 'push' && (github.ref == 'refs/heads/development' ) - run: mvn -P au -B deploy -Dsha1= -fae -Dgpg.passphrase=${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }} + run: mvn -P au -B package -Dsha1= -fae -Dgpg.passphrase=${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }} env: MAVEN_USERNAME: ${{ secrets.ARTIFACTORY_USERNAME }} MAVEN_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }} From 30db2ac1c7c2deb7ed7b7a8ed03e3aaf3f6a5e07 Mon Sep 17 00:00:00 2001 From: Nestor Date: Thu, 31 Aug 2023 10:04:27 +0200 Subject: [PATCH 16/54] Initial commit. First few lines of mabl added. Compiles cleanly Signed-off-by: Nestor --- .../fmi2/api/mabl/variables/VariableCreatorFmi3Api.java | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/VariableCreatorFmi3Api.java diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/VariableCreatorFmi3Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/VariableCreatorFmi3Api.java new file mode 100644 index 000000000..ac49a5d96 --- /dev/null +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/VariableCreatorFmi3Api.java @@ -0,0 +1,2 @@ +package org.intocps.maestro.framework.fmi2.api.mabl.variables;public class VariableCreatorFmi3Api { +} From 2ea6d6a2c620b9efcc258b50b005349ae3b55a20 Mon Sep 17 00:00:00 2001 From: Nestor Date: Thu, 31 Aug 2023 10:12:36 +0200 Subject: [PATCH 17/54] First lines of mabl. Compiles Signed-off-by: Nestor --- .../fmi2/api/mabl/MablApiBuilder.java | 6 +- .../api/mabl/ModelDescriptionContext.java | 4 +- .../api/mabl/ModelDescriptionContext3.java | 27 +++ .../fmi2/api/mabl/scoping/ScopeFmi2Api.java | 2 +- .../variables/ComponentVariableFmi2Api.java | 3 - .../mabl/variables/FmuVariableFmi3Api.java | 43 ++--- .../variables/InstanceVariableFmi3Api.java | 5 + .../variables/VariableCreatorFmi3Api.java | 159 +++++++++++++++++- .../org/intocps/maestro/BuilderFmi3Test.java | 4 +- .../java/org/intocps/maestro/BuilderTest.java | 1 - .../fmi3/basic/basic1/fmi3_basic.mabl | 1 - .../org/intocps/maestro/typechecker/FMI3.mabl | 3 - 12 files changed, 226 insertions(+), 32 deletions(-) create mode 100644 frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/ModelDescriptionContext3.java create mode 100644 frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/InstanceVariableFmi3Api.java diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/MablApiBuilder.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/MablApiBuilder.java index c893fcc18..d4c83d2eb 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/MablApiBuilder.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/MablApiBuilder.java @@ -508,9 +508,13 @@ public void defaultInPStm(PStm node) throws AnalysisException { config.setName(newAIdentifier("FMI2")); //config.setConfig(StringEscapeUtils.escapeJava(simulationEnvironment.)); // unit.setFrameworkConfigs(Arrays.asList(config)); - unit.setImports(Stream.concat(Stream.of(newAIdentifier("FMI2")), importedModules.stream().map(MableAstFactory::newAIdentifier)) + + // TODO: added "import FMI3" after "import FMI2". Should probably figure out a smarter way to do this + unit.setImports(Stream.concat(Stream.of(newAIdentifier("FMI2")), + Stream.concat(Stream.of(newAIdentifier("FMI3")), importedModules.stream().map(MableAstFactory::newAIdentifier))) .collect(Collectors.toList())); + return unit; } diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/ModelDescriptionContext.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/ModelDescriptionContext.java index 03f0c4403..b926d197f 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/ModelDescriptionContext.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/ModelDescriptionContext.java @@ -1,6 +1,7 @@ package org.intocps.maestro.framework.fmi2.api.mabl; import org.intocps.maestro.fmi.Fmi2ModelDescription; +import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; import javax.xml.xpath.XPathExpressionException; import java.lang.reflect.InvocationTargetException; @@ -20,8 +21,9 @@ public ModelDescriptionContext( this.valRefToSv.put(sv.valueReference, sv); }); } - public Fmi2ModelDescription getModelDescription() { return modelDescription; } } + + diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/ModelDescriptionContext3.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/ModelDescriptionContext3.java new file mode 100644 index 000000000..bfa39b0d3 --- /dev/null +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/ModelDescriptionContext3.java @@ -0,0 +1,27 @@ +package org.intocps.maestro.framework.fmi2.api.mabl; + +import kotlin.UInt; +import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; + +import javax.xml.xpath.XPathExpressionException; +import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; +import java.util.Map; + +public class ModelDescriptionContext3 { + + private final Fmi3ModelDescription modelDescription; + public Map nameToSv = new HashMap<>(); + public Map valRefToSv = new HashMap<>(); + public ModelDescriptionContext3( + Fmi3ModelDescription modelDescription) throws IllegalAccessException, XPathExpressionException, InvocationTargetException { + this.modelDescription = modelDescription; + modelDescription.getScalarVariables().forEach((sv) -> { + this.nameToSv.put(sv.getVariable().getName(), sv); + this.valRefToSv.put((long) 1, sv); //TODO: sv.getVariable().getValueReference() + }); + } + public Fmi3ModelDescription getModelDescription() { + return modelDescription; + } +} diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/ScopeFmi2Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/ScopeFmi2Api.java index 407b79240..3630fc7e0 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/ScopeFmi2Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/ScopeFmi2Api.java @@ -498,7 +498,7 @@ public FmuVariableFmi2Api createFMU(String name, String loaderName, String... ar @Override public FmuVariableFmi3Api createFMU(String name, Fmi3ModelDescription modelDescription, URI path) throws Exception { - return null; + return VariableCreatorFmi3Api.createFMU(builder, builder.getNameGenerator(), builder.getDynamicScope(), name, modelDescription, path, this); } @Override diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/ComponentVariableFmi2Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/ComponentVariableFmi2Api.java index 87acf0fef..2531b1622 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/ComponentVariableFmi2Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/ComponentVariableFmi2Api.java @@ -1242,14 +1242,11 @@ private ArrayVariableFmi2Api growBuffer(ArrayVariableFmi2Api buf @Override public Fmi2Builder.StateVariable getState() throws XPathExpressionException { - return getState(builder.getDynamicScope()); - } @Override public Fmi2Builder.StateVariable getState(Fmi2Builder.Scope scope) throws XPathExpressionException { - if (!this.modelDescriptionContext.getModelDescription().getCanGetAndSetFmustate()) { throw new RuntimeException("Unable to get state on fmu: " + this.getOwner() + " with instance name: " + this.getName()); } diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/FmuVariableFmi3Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/FmuVariableFmi3Api.java index d056455e8..f5ad360be 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/FmuVariableFmi3Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/FmuVariableFmi3Api.java @@ -1,10 +1,12 @@ package org.intocps.maestro.framework.fmi2.api.mabl.variables; +import org.intocps.fmi.jnifmuapi.fmi3.Fmi3Instance; import org.intocps.maestro.ast.MableAstFactory; import org.intocps.maestro.ast.node.*; import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; import org.intocps.maestro.framework.fmi2.api.mabl.MablApiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.ModelDescriptionContext; +import org.intocps.maestro.framework.fmi2.api.mabl.ModelDescriptionContext3; import org.intocps.maestro.framework.fmi2.api.mabl.PredicateFmi2Api; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.IMablScope; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.ScopeFmi2Api; @@ -15,29 +17,32 @@ import static org.intocps.maestro.ast.MableBuilder.newVariable; public class FmuVariableFmi3Api extends VariableFmi2Api> implements Fmi2Builder.Fmu3Variable { - public FmuVariableFmi3Api(PStm declaration, PType type, IMablScope declaredScope, Fmi2Builder.DynamicActiveScope dynamicScope, - PStateDesignator designator, PExp referenceExp) { +// public FmuVariableFmi3Api(PStm declaration, PType type, IMablScope declaredScope, Fmi2Builder.DynamicActiveScope dynamicScope, +// PStateDesignator designator, PExp referenceExp) { +// super(declaration, type, declaredScope, dynamicScope, designator, referenceExp); +// } + + + private final ModelDescriptionContext3 modelDescriptionContext; + private final MablApiBuilder builder; + private String fmuIdentifier; +// + public FmuVariableFmi3Api(String fmuIdentifier, MablApiBuilder builder, ModelDescriptionContext3 modelDescriptionContext, PStm declaration, + PType type, IMablScope declaredScope, Fmi2Builder.DynamicActiveScope dynamicScope, PStateDesignator designator, PExp referenceExp) { + this(builder, modelDescriptionContext, declaration, type, declaredScope, dynamicScope, designator, referenceExp); + this.fmuIdentifier = fmuIdentifier; + } + + + public FmuVariableFmi3Api(MablApiBuilder builder, ModelDescriptionContext3 modelDescriptionContext, PStm declaration, PType type, + IMablScope declaredScope, Fmi2Builder.DynamicActiveScope dynamicScope, PStateDesignator designator, PExp referenceExp) { super(declaration, type, declaredScope, dynamicScope, designator, referenceExp); + this.builder = builder; + this.modelDescriptionContext = modelDescriptionContext; } - // private final ModelDescriptionContext modelDescriptionContext; -// private final MablApiBuilder builder; -// private String fmuIdentifier; -// -// public FmuVariableFmi2Api(String fmuIdentifier, MablApiBuilder builder, ModelDescriptionContext modelDescriptionContext, PStm declaration, -// PType type, IMablScope declaredScope, Fmi2Builder.DynamicActiveScope dynamicScope, PStateDesignator designator, PExp referenceExp) { -// this(builder, modelDescriptionContext, declaration, type, declaredScope, dynamicScope, designator, referenceExp); -// this.fmuIdentifier = fmuIdentifier; -// } -// -// public FmuVariableFmi2Api(MablApiBuilder builder, ModelDescriptionContext modelDescriptionContext, PStm declaration, PType type, -// IMablScope declaredScope, Fmi2Builder.DynamicActiveScope dynamicScope, PStateDesignator designator, PExp referenceExp) { -// super(declaration, type, declaredScope, dynamicScope, designator, referenceExp); -// this.builder = builder; -// this.modelDescriptionContext = modelDescriptionContext; -// } // -// public ModelDescriptionContext getModelDescriptionContext() { +// public ModelDescriptionContext3 getModelDescriptionContext() { // return modelDescriptionContext; // } // diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/InstanceVariableFmi3Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/InstanceVariableFmi3Api.java new file mode 100644 index 000000000..9f2d45c65 --- /dev/null +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/InstanceVariableFmi3Api.java @@ -0,0 +1,5 @@ +package org.intocps.maestro.framework.fmi2.api.mabl.variables; + +public class InstanceVariableFmi3Api { + +} diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/VariableCreatorFmi3Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/VariableCreatorFmi3Api.java index ac49a5d96..b6db8eaa4 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/VariableCreatorFmi3Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/VariableCreatorFmi3Api.java @@ -1,2 +1,159 @@ -package org.intocps.maestro.framework.fmi2.api.mabl.variables;public class VariableCreatorFmi3Api { +package org.intocps.maestro.framework.fmi2.api.mabl.variables; + +import org.intocps.fmi.IFmu; +import org.intocps.maestro.ast.MableAstFactory; +import org.intocps.maestro.ast.MableBuilder; +import org.intocps.maestro.ast.node.AErrorStm; +import org.intocps.maestro.ast.node.ALoadExp; +import org.intocps.maestro.ast.node.PStm; +import org.intocps.maestro.ast.node.PType; +import org.intocps.maestro.fmi.Fmi2ModelDescription; +import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; +import org.intocps.maestro.framework.fmi2.FmuFactory; +import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.mabl.*; +import org.intocps.maestro.framework.fmi2.api.mabl.scoping.DynamicActiveBuilderScope; +import org.intocps.maestro.framework.fmi2.api.mabl.scoping.IMablScope; +import org.intocps.maestro.framework.fmi2.api.mabl.scoping.ScopeFmi2Api; +import org.intocps.maestro.framework.fmi2.api.mabl.scoping.TryMaBlScope; + +import javax.xml.xpath.XPathExpressionException; +import java.lang.reflect.InvocationTargetException; +import java.net.URI; +import java.util.Arrays; +import java.util.List; +import java.util.function.Supplier; + +import static org.intocps.maestro.ast.MableAstFactory.*; +import static org.intocps.maestro.ast.MableBuilder.newVariable; + + +public class VariableCreatorFmi3Api { + + private final IMablScope scope; + private final MablApiBuilder builder; + + public VariableCreatorFmi3Api(IMablScope scope, MablApiBuilder builder) { + this.scope = scope; + this.builder = builder; + } + + + public static PType fmitypetomabltype(Fmi2ModelDescription.Types type) { + switch (type) { + case Boolean: + return newABoleanPrimitiveType(); + case Real: + return newARealNumericPrimitiveType(); + case Integer: + return newAIntNumericPrimitiveType(); + case String: + return newAStringPrimitiveType(); + default: + throw new UnsupportedOperationException("Converting fmi type: " + type + " to mabl type is not supported."); + } + } + +// public static VariableFmi2Api createVariableForPort(TagNameGenerator nameGenerator, PortFmi2Api port, IMablScope scope, +// Fmi2Builder.DynamicActiveScope dynamicScope) { +// var name = nameGenerator.getName(port.toLexName()); +// var type = MableAstFactory.newAArrayType(fmitypetomabltype(port.scalarVariable.type.type)); +// var size = 1; +// PStm stm = MableBuilder.newVariable(name, type, size); +// scope.add(stm); +// VariableFmi2Api variable = new VariableFmi2Api(stm, type, scope, dynamicScope, +// newAArayStateDesignator(newAIdentifierStateDesignator(newAIdentifier(name)), newAIntLiteralExp(0)), +// newAArrayIndexExp(newAIdentifierExp(name), Arrays.asList(newAIntLiteralExp(0)))); +// return variable; +// } + + public static FmuVariableFmi3Api createFMU(MablApiBuilder builder, TagNameGenerator nameGenerator, DynamicActiveBuilderScope dynamicScope, + String name, URI uriPath, IMablScope scope) throws Exception { + String path = uriPath.toString(); + if (uriPath.getScheme() != null && uriPath.getScheme().equals("file")) { + path = uriPath.getPath(); + } + + IFmu fmu = FmuFactory.create(null, URI.create(path)); + //check schema. The constructor checks the schema + Fmi3ModelDescription modelDescription = new Fmi3ModelDescription(fmu.getModelDescription()); + + return createFMU(builder, nameGenerator, dynamicScope, name, modelDescription, uriPath, scope); + } + + public static FmuVariableFmi3Api createFMU(MablApiBuilder builder, TagNameGenerator nameGenerator, DynamicActiveBuilderScope dynamicScope, + String name, String loaderName, String[] args, IMablScope scope) throws Exception { + + if (loaderName.equals("FMI3")) { + return createFMU(builder, nameGenerator, dynamicScope, name, URI.create(args[0]), scope); + } else if (loaderName.equals("JFMI3")) { + return createFMU(builder, nameGenerator, dynamicScope, name, args[0], scope); + } + return null; + } + + + public static FmuVariableFmi3Api createFMU(MablApiBuilder builder, TagNameGenerator nameGenerator, DynamicActiveBuilderScope dynamicScope, + String name, String className, IMablScope scope) throws Exception { + + ALoadExp loadExp = newALoadExp(Arrays.asList(newAStringLiteralExp("JFMI3"), newAStringLiteralExp(className))); + + IFmu fmu = (IFmu) VariableCreatorFmi2Api.class.getClassLoader().loadClass(className).getConstructor().newInstance(); + final ModelDescriptionContext3 ctxt = new ModelDescriptionContext3(new Fmi3ModelDescription(fmu.getModelDescription())); + return createFmu(builder, nameGenerator, dynamicScope, name, scope, loadExp, () -> ctxt, + "FMU load failed on fmu: '%s' for classpath: '" + className + "'"); + } + + public static FmuVariableFmi3Api createFMU(MablApiBuilder builder, TagNameGenerator nameGenerator, DynamicActiveBuilderScope dynamicScope, + String name, Fmi3ModelDescription modelDescription, URI uriPath, + IMablScope scope) throws IllegalAccessException, XPathExpressionException, InvocationTargetException { + String path = uriPath.toString(); + if (uriPath.getScheme() != null && uriPath.getScheme().equals("file")) { + path = uriPath.getPath(); + } + + ALoadExp loadExp = newALoadExp( + Arrays.asList(newAStringLiteralExp("FMI3"), newAStringLiteralExp(modelDescription.getInstantiationToken()), newAStringLiteralExp(path))); + + final ModelDescriptionContext3 ctxt = new ModelDescriptionContext3(modelDescription); + + return createFmu(builder, nameGenerator, dynamicScope, name, scope, loadExp, () -> ctxt, + "FMU load failed on fmu: '%s' for uri: '" + uriPath + "'"); + } + + + private static FmuVariableFmi3Api createFmu(MablApiBuilder builder, TagNameGenerator nameGenerator, DynamicActiveBuilderScope dynamicScope, + String name, IMablScope scope, ALoadExp loadExp, Supplier modelDescriptionSupplier, + String loadErrorMsgWithNameStringArgument) { + String uniqueName = nameGenerator.getName(name); + + PStm var = newVariable(uniqueName, newANameType("FMI3"), newNullExp()); + var assign = newAAssignmentStm(newAIdentifierStateDesignator(uniqueName), loadExp); + + var enclosingTryScope = scope.findParentScope(TryMaBlScope.class); + if (enclosingTryScope == null) { + throw new IllegalArgumentException("Call to load FMU is only allowed within a try scope"); + } + + enclosingTryScope.parent().addBefore(enclosingTryScope.getDeclaration(), var); + scope.add(assign); + + FmuVariableFmi3Api fmuVar = new FmuVariableFmi3Api(name, builder, modelDescriptionSupplier.get(), var, MableAstFactory.newANameType("FMI3"), + enclosingTryScope.parent(), dynamicScope, newAIdentifierStateDesignator(newAIdentifier(uniqueName)), newAIdentifierExp(uniqueName)); + + enclosingTryScope.getFinallyBody().addAfterOrTop(null, newIf(newNotEqual(fmuVar.getReferenceExp().clone(), newNullExp()), + newABlockStm(newExpressionStm(newUnloadExp(List.of(fmuVar.getReferenceExp().clone()))), + newAAssignmentStm(fmuVar.getDesignator().clone(), newNullExp())), null)); + + if (builder.getSettings().fmiErrorHandlingEnabled) { + ScopeFmi2Api thenScope = scope.enterIf(new PredicateFmi2Api(newEqual(fmuVar.getReferenceExp().clone(), newNullExp()))).enterThen(); + + builder.getLogger().error(thenScope, loadErrorMsgWithNameStringArgument, name); + + thenScope.add(new AErrorStm(newAStringLiteralExp(String.format(loadErrorMsgWithNameStringArgument, name)))); + + thenScope.leave(); + } + return fmuVar; + } } diff --git a/maestro/src/test/java/org/intocps/maestro/BuilderFmi3Test.java b/maestro/src/test/java/org/intocps/maestro/BuilderFmi3Test.java index 562337156..71814e928 100644 --- a/maestro/src/test/java/org/intocps/maestro/BuilderFmi3Test.java +++ b/maestro/src/test/java/org/intocps/maestro/BuilderFmi3Test.java @@ -20,6 +20,7 @@ import org.intocps.maestro.framework.fmi2.api.mabl.scoping.DynamicActiveBuilderScope; import org.intocps.maestro.framework.fmi2.api.mabl.variables.ComponentVariableFmi2Api; import org.intocps.maestro.framework.fmi2.api.mabl.variables.FmuVariableFmi2Api; +import org.intocps.maestro.framework.fmi2.api.mabl.variables.FmuVariableFmi3Api; import org.intocps.maestro.framework.fmi2.api.mabl.variables.VariableFmi2Api; import org.intocps.maestro.interpreter.DefaultExternalValueFactory; import org.intocps.maestro.interpreter.MableInterpreter; @@ -82,7 +83,8 @@ public void wt() throws Exception { Fmi3ModelDescription md3Ball = new Fmi3ModelDescription(ball.getModelDescription()); - builder.getDynamicScope().createFMU("ball", md3Ball, ballUri); + FmuVariableFmi3Api ballFmu = builder.getDynamicScope().createFMU("ball", md3Ball, ballUri); + // Create the two FMUs FmuVariableFmi2Api controllerFMU = builder.getDynamicScope() diff --git a/maestro/src/test/java/org/intocps/maestro/BuilderTest.java b/maestro/src/test/java/org/intocps/maestro/BuilderTest.java index 1685e145a..38dfb37ed 100644 --- a/maestro/src/test/java/org/intocps/maestro/BuilderTest.java +++ b/maestro/src/test/java/org/intocps/maestro/BuilderTest.java @@ -202,7 +202,6 @@ public void call(ExtFunc func, Object... args) { @Override public void destroy() { - } } } \ No newline at end of file diff --git a/maestro/src/test/resources/fmi3/basic/basic1/fmi3_basic.mabl b/maestro/src/test/resources/fmi3/basic/basic1/fmi3_basic.mabl index 5c4f408d4..cd1738d60 100644 --- a/maestro/src/test/resources/fmi3/basic/basic1/fmi3_basic.mabl +++ b/maestro/src/test/resources/fmi3/basic/basic1/fmi3_basic.mabl @@ -9,7 +9,6 @@ import FMI3; { error; } - string instanceName="fmi3functiontest"; bool visible=true; diff --git a/typechecker/src/main/resources/org/intocps/maestro/typechecker/FMI3.mabl b/typechecker/src/main/resources/org/intocps/maestro/typechecker/FMI3.mabl index 6b66e0824..657f40d04 100644 --- a/typechecker/src/main/resources/org/intocps/maestro/typechecker/FMI3.mabl +++ b/typechecker/src/main/resources/org/intocps/maestro/typechecker/FMI3.mabl @@ -14,9 +14,6 @@ import FMI2; } - - - module FMU3State{} module FMI3Instance import FMU3State;{ From 9fe0c2cbf8e0d5851454ad2f789785f9edd8dbbd Mon Sep 17 00:00:00 2001 From: Nestor Date: Thu, 7 Sep 2023 12:38:33 +0200 Subject: [PATCH 18/54] InstanceVariableFmi3Api, instantiateCoSimulation in mabl, compiles succesfully --- .../intocps/maestro/ast/MableAstFactory.java | 1 + .../maestro/fmi/fmi3/Fmi3ModelDescription.kt | 1 + .../intocps/maestro/fmi/fmi3/Fmi3Variables.kt | 4 +- .../api/mabl/ModelDescriptionContext3.java | 2 +- .../framework/fmi2/api/mabl/PortFmi3Api.java | 148 ++ .../scoping/DynamicActiveBuilderScope.java | 6 + .../fmi2/api/mabl/scoping/IMablScope.java | 3 + .../fmi2/api/mabl/scoping/ScopeFmi2Api.java | 16 +- .../variables/ComponentVariableFmi2Api.java | 1 + .../mabl/variables/FmuVariableFmi3Api.java | 174 +- .../variables/InstanceVariableFmi3Api.java | 1404 ++++++++++++++++- .../variables/StateMablVariableFmi2Api.java | 3 + .../variables/StateMablVariableFmi3Api.java | 75 + .../org/intocps/maestro/BuilderFmi3Test.java | 8 +- 14 files changed, 1752 insertions(+), 94 deletions(-) create mode 100644 frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/PortFmi3Api.java create mode 100644 frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/StateMablVariableFmi3Api.java diff --git a/ast/src/main/java/org/intocps/maestro/ast/MableAstFactory.java b/ast/src/main/java/org/intocps/maestro/ast/MableAstFactory.java index a00cdf72c..ee3df3adc 100644 --- a/ast/src/main/java/org/intocps/maestro/ast/MableAstFactory.java +++ b/ast/src/main/java/org/intocps/maestro/ast/MableAstFactory.java @@ -376,6 +376,7 @@ public static AIntLiteralExp newAIntLiteralExp(Integer value) { return exp; } + public static AStringLiteralExp newAStringLiteralExp(String value) { AStringLiteralExp exp = new AStringLiteralExp(); exp.setValue(value); diff --git a/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi3/Fmi3ModelDescription.kt b/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi3/Fmi3ModelDescription.kt index 9b0d42ab5..72fe09eac 100644 --- a/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi3/Fmi3ModelDescription.kt +++ b/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi3/Fmi3ModelDescription.kt @@ -12,6 +12,7 @@ import java.lang.reflect.InvocationTargetException import javax.xml.transform.stream.StreamSource import javax.xml.xpath.XPathExpressionException + class Fmi3ModelDescription : ModelDescription { private var variables: Collection? = null private var typeDefinitions: Collection? = null diff --git a/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi3/Fmi3Variables.kt b/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi3/Fmi3Variables.kt index a5d1c88eb..f0b774653 100644 --- a/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi3/Fmi3Variables.kt +++ b/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi3/Fmi3Variables.kt @@ -14,7 +14,9 @@ abstract class Fmi3Variable protected constructor( val previous: UInt? = null, val clocks: List? = null, val typeIdentifier: Fmi3TypeEnum // This is for easier type identification and is not part of the official spec -) +) { + fun getValueReferenceAsLong():Long { return valueReference.toLong() } +} data class Dimension(val valueReference: UInt?, val start: List?) diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/ModelDescriptionContext3.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/ModelDescriptionContext3.java index bfa39b0d3..3c9e75125 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/ModelDescriptionContext3.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/ModelDescriptionContext3.java @@ -18,7 +18,7 @@ public ModelDescriptionContext3( this.modelDescription = modelDescription; modelDescription.getScalarVariables().forEach((sv) -> { this.nameToSv.put(sv.getVariable().getName(), sv); - this.valRefToSv.put((long) 1, sv); //TODO: sv.getVariable().getValueReference() + this.valRefToSv.put((long) sv.getVariable().getValueReferenceAsLong(), sv); }); } public Fmi3ModelDescription getModelDescription() { diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/PortFmi3Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/PortFmi3Api.java new file mode 100644 index 000000000..b92a01244 --- /dev/null +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/PortFmi3Api.java @@ -0,0 +1,148 @@ +package org.intocps.maestro.framework.fmi2.api.mabl; + +import org.intocps.maestro.ast.node.PType; +import org.intocps.maestro.fmi.Fmi2ModelDescription; +import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3Causality; +import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; +import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.mabl.variables.ComponentVariableFmi2Api; +import org.intocps.maestro.framework.fmi2.api.mabl.variables.InstanceVariableFmi3Api; +import org.intocps.maestro.framework.fmi2.api.mabl.variables.VariableFmi2Api; + +import java.util.ArrayList; +import java.util.List; + +import static org.intocps.maestro.ast.MableAstFactory.*; + +public class PortFmi3Api implements Fmi2Builder.Port { + + public final InstanceVariableFmi3Api aMablFmi3InstanceAPI; + public final Fmi3ModelDescription.Fmi3ScalarVariable scalarVariable; + private final List targetPorts = new ArrayList<>(); + private VariableFmi2Api sharedAsVariable; + private PortFmi3Api sourcePort; + + + // TODO model description fmi3 + public PortFmi3Api(InstanceVariableFmi3Api aMablFmi3InstanceAPI, Fmi3ModelDescription.Fmi3ScalarVariable scalarVariable) { + + this.aMablFmi3InstanceAPI = aMablFmi3InstanceAPI; + this.scalarVariable = scalarVariable; + } + + @Override + public String toString() { + return "Port( '" + aMablFmi3InstanceAPI.getName() + "." + scalarVariable.getVariable().getName() + "' , '" + scalarVariable.getVariable().getTypeIdentifier().name() + "')"; + } + + public VariableFmi2Api getSharedAsVariable() { + return sharedAsVariable; + } + + public void setSharedAsVariable(VariableFmi2Api sharedAsVariable) { + this.sharedAsVariable = sharedAsVariable; + } + + public PType getType() { + switch (scalarVariable.getVariable().getTypeIdentifier()) { +// case Boolean: +// return newBoleanType(); +// case Real: +// return newRealType(); +// case Integer: +// return newIntType(); +// case String: +// return newStringType(); +// case Enumeration: + default: + return null; + } + } + + @Override + public String getName() { + return this.scalarVariable.getVariable().getName(); + } + + @Override + public Long getPortReferenceValue() { + return this.scalarVariable.getVariable().getValueReferenceAsLong(); + } + + + @Override + public void linkTo(Fmi2Builder.Port... receivers) throws PortLinkException { + + if (receivers == null || receivers.length == 0) { + return; + } + + if (this.scalarVariable.getVariable().getCausality() != Fmi3Causality.Output) { + throw new PortLinkException("Can only link output ports. This port is: " + this.scalarVariable.getVariable().getCausality(), this); + } + + for (Fmi2Builder.Port receiver : receivers) { + PortFmi3Api receiverPort = (PortFmi3Api) receiver; + + if (receiverPort.scalarVariable.getVariable().getCausality() != Fmi3Causality.Input) { + throw new PortLinkException("Receivers must be input ports. This receiver is: " + receiverPort.scalarVariable.getVariable().getCausality(), + receiverPort); + } + + // HEJ: TBD - This check fails with "already linked" in expansion since both rbmq fmus connect to single actuation + if (receiverPort.getSourcePort() != null) { + throw new PortLinkException("Cannot port already linked please break link first", receiver); + } + receiverPort.sourcePort = this; + if (!this.targetPorts.contains(receiverPort)) { + this.targetPorts.add(receiverPort); + } + } + } + + public PortFmi3Api getSourcePort() { + return this.sourcePort; + } + + @Override + public void breakLink() { + if (sourcePort != null) { + //delete this from the source port + sourcePort.targetPorts.remove(this); + } + sourcePort = null; + } + + @Override + public boolean isLinked() { + return isLinkedAsInputConsumer() || isLinkedAsOutputProvider(); + } + + @Override + public boolean isLinkedAsOutputProvider() { + return targetPorts.isEmpty(); + } + + @Override + public boolean isLinkedAsInputConsumer() { + return this.sourcePort != null; + } + + public String toLexName() { + return this.aMablFmi3InstanceAPI.getOwner().getName() + "_" + this.aMablFmi3InstanceAPI.getName() + "_" + this.getName(); + } + + public String getMultiModelScalarVariableName() { + return this.aMablFmi3InstanceAPI.getOwner().getFmuIdentifier() + "." + this.aMablFmi3InstanceAPI.getEnvironmentName() + "." + + this.getName(); + } + + public String getMultiModelScalarVariableNameWithoutFmu() { + return this.aMablFmi3InstanceAPI.getEnvironmentName() + "." + this.getName(); + } + + public List getTargetPorts() { + return this.targetPorts; + } +} + diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/DynamicActiveBuilderScope.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/DynamicActiveBuilderScope.java index 86f7adbb4..c0821a3e7 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/DynamicActiveBuilderScope.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/DynamicActiveBuilderScope.java @@ -252,6 +252,12 @@ public void registerComponentVariableFmi2Api(ComponentVariableFmi2Api componentV } + + @Override + public void registerInstanceVariableFmi3Api(InstanceVariableFmi3Api instanceVariableFmi3Api) { + // TODO stuff goes here. + } + @Override public S findParentScope(Class type) { return this.activeScope.findParentScope(type); diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/IMablScope.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/IMablScope.java index f3f010ed5..85bcc8d43 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/IMablScope.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/IMablScope.java @@ -115,5 +115,8 @@ public interface IMablScope extends Fmi2Builder.Scope { */ void registerComponentVariableFmi2Api(ComponentVariableFmi2Api componentVariableFmi2Api); + void registerInstanceVariableFmi3Api(InstanceVariableFmi3Api instanceVariableFmi3Api); + + S findParentScope(Class type); } diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/ScopeFmi2Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/ScopeFmi2Api.java index 3630fc7e0..721c4847c 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/ScopeFmi2Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/ScopeFmi2Api.java @@ -373,6 +373,11 @@ protected ArrayVariableFmi2Api store(Supplier nameProvider, V[] v if (length > 1 && value[0] != null) { initializer = newAArrayInitializer(Arrays.stream(value).map(v -> newAIntLiteralExp((Integer) v)).collect(Collectors.toList())); } + } else if (value instanceof Long[]) { + type = new AUIntNumericPrimitiveType(); + if (length > 1 && value[0] != null) { + initializer = newAArrayInitializer(Arrays.stream(value).map(v -> newAUIntLiteralExp((Long) v)).collect(Collectors.toList())); + } } else if (value instanceof Boolean[]) { type = new ABooleanPrimitiveType(); if (length > 1 && value[0] != null) { @@ -472,7 +477,6 @@ private Fmi2Builder.Variable storePrivate(String name, Fmi2Builder. if (v.get() != null) { initial = newAIntLiteralExp((Integer) v.get()); } - } else if (v.getType() instanceof ABooleanPrimitiveType) { if (v.get() != null) { initial = newABoolLiteralExp((Boolean) v.get()); @@ -506,6 +510,14 @@ public FmuVariableFmi3Api createFMU3(String name, String loaderName, String... a return null; } + + // TODO stuff goes here. + @Override + public void registerInstanceVariableFmi3Api(InstanceVariableFmi3Api instanceVariableFmi3Api) { + + } + + @Override public void markTransferPoint(String... names) { @@ -601,6 +613,8 @@ public void registerComponentVariableFmi2Api(ComponentVariableFmi2Api componentV this.fmi2ComponentVariables.add(componentVariableFmi2Api); } + + @Override public S findParentScope(Class type) { Fmi2Builder.ScopeElement p = this; diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/ComponentVariableFmi2Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/ComponentVariableFmi2Api.java index 2531b1622..77c99921c 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/ComponentVariableFmi2Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/ComponentVariableFmi2Api.java @@ -1247,6 +1247,7 @@ public Fmi2Builder.StateVariable getState() throws XPathExpressionExceptio @Override public Fmi2Builder.StateVariable getState(Fmi2Builder.Scope scope) throws XPathExpressionException { + if (!this.modelDescriptionContext.getModelDescription().getCanGetAndSetFmustate()) { throw new RuntimeException("Unable to get state on fmu: " + this.getOwner() + " with instance name: " + this.getName()); } diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/FmuVariableFmi3Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/FmuVariableFmi3Api.java index f5ad360be..0b18e53f2 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/FmuVariableFmi3Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/FmuVariableFmi3Api.java @@ -12,6 +12,10 @@ import org.intocps.maestro.framework.fmi2.api.mabl.scoping.ScopeFmi2Api; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.TryMaBlScope; +import java.util.Arrays; +import java.util.HashMap; +import java.util.stream.Collectors; + import static org.intocps.maestro.ast.MableAstFactory.*; import static org.intocps.maestro.ast.MableBuilder.call; import static org.intocps.maestro.ast.MableBuilder.newVariable; @@ -41,91 +45,89 @@ public FmuVariableFmi3Api(MablApiBuilder builder, ModelDescriptionContext3 model this.modelDescriptionContext = modelDescriptionContext; } -// -// public ModelDescriptionContext3 getModelDescriptionContext() { -// return modelDescriptionContext; -// } -// -// @Override -// public ComponentVariableFmi2Api instantiate(String name, String environmentName) { -// IMablScope scope = builder.getDynamicScope().getActiveScope(); -// return instantiate(name, scope.findParentScope(TryMaBlScope.class), scope, environmentName); -// } -// -// @Override -// public ComponentVariableFmi2Api instantiate(String name) { -// IMablScope scope = builder.getDynamicScope().getActiveScope(); -// return instantiate(name, scope.findParentScope(TryMaBlScope.class), scope); -// } -// -// -// @Override -// public ComponentVariableFmi2Api instantiate(String namePrefix, Fmi2Builder.TryScope enclosingTryScope, Fmi2Builder.Scope scope, -// String environmentName) { -// return instantiate(namePrefix, enclosingTryScope, scope, environmentName, true); -// } -// -// @Override -// public ComponentVariableFmi2Api instantiate(String namePrefix, Fmi2Builder.TryScope enclosingTryScope, Fmi2Builder.Scope scope, -// String environmentName, boolean loggingOn) { -// -// String name = builder.getNameGenerator().getName(namePrefix); -// //TODO: Extract bool visible and bool loggingOn from configuration -// var var = newVariable(name, newANameType("FMI2Component"), newNullExp()); -// -// PStm instantiateAssign = newAAssignmentStm(newAIdentifierStateDesignator(name), -// call(getReferenceExp().clone(), "instantiate", newAStringLiteralExp(name), newABoolLiteralExp(true), newABoolLiteralExp(loggingOn))); -// -// -// if (enclosingTryScope == null) { -// throw new IllegalArgumentException("Call to instantiate is not allowed with a null enclosing try scope"); -// } -// -// -// TryMaBlScope mTryScope = (TryMaBlScope) enclosingTryScope; -// mTryScope.parent().addBefore(mTryScope.getDeclaration(), var); -// -// ComponentVariableFmi2Api compVar; -// if (environmentName == null) { -// compVar = new ComponentVariableFmi2Api(var, this, name, this.modelDescriptionContext, builder, mTryScope.parent(), -// newAIdentifierStateDesignator(newAIdentifier(name)), newAIdentifierExp(name)); -// } else { -// -// AInstanceMappingStm mapping = newAInstanceMappingStm(newAIdentifier(name), environmentName); -// compVar = new ComponentVariableFmi2Api(var, this, name, this.modelDescriptionContext, builder, mTryScope.parent(), -// newAIdentifierStateDesignator(newAIdentifier(name)), newAIdentifierExp(name), environmentName); -// scope.add(mapping); -// } -// -// scope.add(instantiateAssign); -// -// mTryScope.getFinallyBody().addAfterOrTop(null, newIf(newNotEqual(compVar.getReferenceExp().clone(), newNullExp()), -// newABlockStm(MableAstFactory.newExpressionStm(call(getReferenceExp().clone(), "freeInstance", compVar.getReferenceExp().clone())), -// newAAssignmentStm(compVar.getDesignatorClone(), newNullExp())), null)); -// -// scope.activate(); -// -// if (builder.getSettings().fmiErrorHandlingEnabled) { -// ScopeFmi2Api thenScope = -// (ScopeFmi2Api) scope.enterIf(new PredicateFmi2Api(newEqual(compVar.getReferenceExp().clone(), newNullExp()))).enterThen(); -// -// builder.getLogger().error(thenScope, "Instantiate failed on fmu: '%s' for instance: '%s'", this.getFmuIdentifier(), namePrefix); -// thenScope.add(new AErrorStm( -// newAStringLiteralExp(String.format("Instantiate failed on fmu: '%s' for instance: '%s'", this.getFmuIdentifier(), namePrefix)))); -// thenScope.leave(); -// } -// -// ((IMablScope) scope).registerComponentVariableFmi2Api(compVar); -// -// return compVar; -// } -// + public ModelDescriptionContext3 getModelDescriptionContext() { + return modelDescriptionContext; + } + // @Override -// public ComponentVariableFmi2Api instantiate(String namePrefix, Fmi2Builder.TryScope enclosingTryScope, Fmi2Builder.Scope scope) { -// return instantiate(namePrefix, enclosingTryScope, scope, null); -// } -// -// public String getFmuIdentifier() { -// return fmuIdentifier; -// } + public InstanceVariableFmi3Api instantiate(String name, String environmentName, ArrayVariableFmi2Api variables) { + IMablScope scope = builder.getDynamicScope().getActiveScope(); + return instantiate(name, scope.findParentScope(TryMaBlScope.class), scope, environmentName, variables); + } + + public InstanceVariableFmi3Api instantiate(String name, ArrayVariableFmi2Api variables) { + IMablScope scope = builder.getDynamicScope().getActiveScope(); + return instantiate(name, scope.findParentScope(TryMaBlScope.class), scope, variables); + } + + + public InstanceVariableFmi3Api instantiate(String namePrefix, Fmi2Builder.TryScope enclosingTryScope, Fmi2Builder.Scope scope, + String environmentName, ArrayVariableFmi2Api variables) { + return instantiate(namePrefix, enclosingTryScope, scope, environmentName, true, variables ); + } + public InstanceVariableFmi3Api instantiate(String namePrefix, Fmi2Builder.TryScope enclosingTryScope, Fmi2Builder.Scope scope, + String environmentName, boolean loggingOn, ArrayVariableFmi2Api variables) { + + String name = builder.getNameGenerator().getName(namePrefix); + //TODO: Extract bool visible and bool loggingOn from configuration + var var = newVariable(name, newANameType("FMI3Instance"), newNullExp()); + + + + + + PStm instantiateAssign = newAAssignmentStm(newAIdentifierStateDesignator(name), + call(getReferenceExp().clone(), "instantiateCoSimulation", newAStringLiteralExp(name), newABoolLiteralExp(true), + newABoolLiteralExp(loggingOn), newABoolLiteralExp(true), newABoolLiteralExp(true), + variables.getReferenceExp().clone())); + + if (enclosingTryScope == null) { + throw new IllegalArgumentException("Call to instantiate is not allowed with a null enclosing try scope"); + } + + + TryMaBlScope mTryScope = (TryMaBlScope) enclosingTryScope; + mTryScope.parent().addBefore(mTryScope.getDeclaration(), var); + + InstanceVariableFmi3Api compVar; + if (environmentName == null) { + compVar = new InstanceVariableFmi3Api(var, this, name, this.modelDescriptionContext, builder, mTryScope.parent(), + newAIdentifierStateDesignator(newAIdentifier(name)), newAIdentifierExp(name)); + } else { + + AInstanceMappingStm mapping = newAInstanceMappingStm(newAIdentifier(name), environmentName); + compVar = new InstanceVariableFmi3Api(var, this, name, this.modelDescriptionContext, builder, mTryScope.parent(), + newAIdentifierStateDesignator(newAIdentifier(name)), newAIdentifierExp(name), environmentName); + scope.add(mapping); + } + + scope.add(instantiateAssign); + + mTryScope.getFinallyBody().addAfterOrTop(null, newIf(newNotEqual(compVar.getReferenceExp().clone(), newNullExp()), + newABlockStm(MableAstFactory.newExpressionStm(call(getReferenceExp().clone(), "freeInstance", compVar.getReferenceExp().clone())), + newAAssignmentStm(compVar.getDesignatorClone(), newNullExp())), null)); + + scope.activate(); + + if (builder.getSettings().fmiErrorHandlingEnabled) { + ScopeFmi2Api thenScope = + (ScopeFmi2Api) scope.enterIf(new PredicateFmi2Api(newEqual(compVar.getReferenceExp().clone(), newNullExp()))).enterThen(); + + builder.getLogger().error(thenScope, "Instantiate failed on fmu: '%s' for instance: '%s'", this.getFmuIdentifier(), namePrefix); + thenScope.add(new AErrorStm( + newAStringLiteralExp(String.format("Instantiate failed on fmu: '%s' for instance: '%s'", this.getFmuIdentifier(), namePrefix)))); + thenScope.leave(); + } + + ((IMablScope) scope).registerInstanceVariableFmi3Api(compVar); + + return compVar; + } + public InstanceVariableFmi3Api instantiate(String namePrefix, Fmi2Builder.TryScope enclosingTryScope, Fmi2Builder.Scope scope, ArrayVariableFmi2Api variables) { + return instantiate(namePrefix, enclosingTryScope, scope, null, variables); + } + + public String getFmuIdentifier() { + return fmuIdentifier; + } } \ No newline at end of file diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/InstanceVariableFmi3Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/InstanceVariableFmi3Api.java index 9f2d45c65..ea1a2e208 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/InstanceVariableFmi3Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/InstanceVariableFmi3Api.java @@ -1,5 +1,1407 @@ package org.intocps.maestro.framework.fmi2.api.mabl.variables; -public class InstanceVariableFmi3Api { +import org.intocps.maestro.ast.AVariableDeclaration; +import org.intocps.maestro.ast.LexIdentifier; +import org.intocps.maestro.ast.MableAstFactory; +import org.intocps.maestro.ast.analysis.AnalysisException; +import org.intocps.maestro.ast.analysis.DepthFirstAnalysisAdaptor; +import org.intocps.maestro.ast.node.*; +import org.intocps.maestro.fmi.Fmi2ModelDescription; +import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3Causality; +import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; +import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3TypeEnum; +import org.intocps.maestro.framework.fmi2.RelationVariable; +import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.mabl.*; +import org.intocps.maestro.framework.fmi2.api.mabl.scoping.IMablScope; +import org.intocps.maestro.framework.fmi2.api.mabl.scoping.ScopeFmi2Api; +import org.intocps.maestro.framework.fmi2.api.mabl.values.PortValueExpresssionMapImpl; +import org.intocps.maestro.framework.fmi2.api.mabl.values.PortValueMapImpl; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.xml.xpath.XPathExpressionException; +import java.lang.reflect.InvocationTargetException; +import java.util.*; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import static java.util.stream.Collectors.toSet; +import static org.intocps.maestro.ast.MableAstFactory.*; +import static org.intocps.maestro.ast.MableBuilder.call; +import static org.intocps.maestro.ast.MableBuilder.newVariable; + + +@SuppressWarnings("rawtypes") +public class InstanceVariableFmi3Api extends VariableFmi2Api> implements Fmi2Builder.Fmi2ComponentVariable { + final static Logger logger = LoggerFactory.getLogger(InstanceVariableFmi3Api.class); + private final static int FMI_OK = 0; + private final static int FMI_WARNING = 1; + private final static int FMI_DISCARD = 2; + private final static int FMI_ERROR = 3; + private final static int FMI_FATAL = 4; + private final static int FMI_PENDING = 5; + private final static int FMI_STATUS_LAST_SUCCESSFUL = 2; + private static final String LOGLEVELS_POSTFIX = "_log_levels"; + private final static String CATEGORY_STATUS = "category_status"; + final List outputPorts; + final List inputPorts; + final List ports; + private final FmuVariableFmi3Api owner; + private final String name; + private final MablApiBuilder builder; + private final Map> ioBuffer = new HashMap<>(); + private final Map> sharedBuffer = new HashMap<>(); + private final Map>> tentativeBuffer = new HashMap<>(); + private final Map> tentativeBufferIndexMap = new HashMap<>(); + private final String environmentName; + Predicate isLinked = p -> ((PortFmi3Api) p).getSourcePort() != null; + ModelDescriptionContext3 modelDescriptionContext; + private ArrayVariableFmi2Api derSharedBuffer; + private DoubleVariableFmi2Api currentTimeVar = null; + private BooleanVariableFmi2Api currentTimeStepFullStepVar = null; + private ArrayVariableFmi2Api valueRefBuffer; + private Map>> derivativePortsToShare; + private List variabesToLog; + + public InstanceVariableFmi3Api(PStm declaration, FmuVariableFmi3Api parent, String name, ModelDescriptionContext3 modelDescriptionContext, + MablApiBuilder builder, IMablScope declaringScope, PStateDesignator designator, PExp referenceExp) { + this(declaration, parent, name, modelDescriptionContext, builder, declaringScope, designator, referenceExp, name); + } + + public InstanceVariableFmi3Api(PStm declaration, FmuVariableFmi3Api parent, String name, ModelDescriptionContext3 modelDescriptionContext, + MablApiBuilder builder, IMablScope declaringScope, PStateDesignator designator, PExp referenceExp, String environmentName) { + super(declaration, newANameType("FMI3Instance"), declaringScope, builder.getDynamicScope(), designator, referenceExp); + this.owner = parent; + this.name = name; + + this.modelDescriptionContext = modelDescriptionContext; + this.builder = builder; + + ports = modelDescriptionContext.nameToSv.values().stream().map(sv -> new PortFmi3Api(this, sv)) + .sorted(Comparator.comparing(PortFmi3Api::getPortReferenceValue)).collect(Collectors.toUnmodifiableList()); + + outputPorts = ports.stream().filter(p -> p.scalarVariable.getVariable().getCausality() == Fmi3Causality.Output) + .sorted(Comparator.comparing(PortFmi3Api::getPortReferenceValue)).collect(Collectors.toUnmodifiableList()); + + inputPorts = + ports.stream().filter(p -> p.scalarVariable.getVariable().getCausality() == Fmi3Causality.Input) + .sorted(Comparator.comparing(PortFmi3Api::getPortReferenceValue)).collect(Collectors.toUnmodifiableList()); + + this.environmentName = environmentName; + } + + // TODO fmi3 model description. + public Fmi3ModelDescription getModelDescription() { + return modelDescriptionContext.getModelDescription(); + } + + public List getVariablesToLog() { + return this.getPorts(this.variabesToLog.toArray(new String[0])); + } + + public void setVariablesToLog(List variablesToLog) { + this.variabesToLog = variablesToLog.stream().map(x -> x.scalarVariable.getName()).collect(Collectors.toList()); + } + + @Override + public void share(Fmi2Builder.Port port, Fmi2Builder.Variable value) { + Map> map = new HashMap<>(); + map.put(port, value); + share(map); + } + + private DoubleVariableFmi2Api getCurrentTimeVar() { + if (currentTimeVar == null) { + String name = builder.getNameGenerator().getName(this.name, "current", "time"); + PStm var = newVariable(name, newRealType(), newARealLiteralExp(0d)); + this.getDeclaredScope().addAfter(this.getDeclaringStm(), var); + currentTimeVar = new DoubleVariableFmi2Api(var, this.getDeclaredScope(), dynamicScope, newAIdentifierStateDesignator(name), + newAIdentifierExp(name)); + } + return currentTimeVar; + } + + private BooleanVariableFmi2Api getCurrentTimeFullStepVar() { + if (currentTimeStepFullStepVar == null) { + String name = builder.getNameGenerator().getName(this.name, "current", "time", "full", "step"); + PStm var = newVariable(name, newBoleanType(), newABoolLiteralExp(true)); + this.getDeclaredScope().addAfter(this.getDeclaringStm(), var); + + currentTimeStepFullStepVar = new BooleanVariableFmi2Api(var, this.getDeclaredScope(), dynamicScope, newAIdentifierStateDesignator(name), + newAIdentifierExp(name)); + } + return currentTimeStepFullStepVar; + } + + private ArrayVariableFmi2Api getValueReferenceBuffer() { + if (this.valueRefBuffer == null) { + this.valueRefBuffer = createBuffer(newUIntType(), "VRef", modelDescriptionContext.valRefToSv.size(), getDeclaredScope()); + } + return this.valueRefBuffer; + } + + private ArrayVariableFmi2Api getBuffer(Map> buffer, PType type, String prefix, int size, + IMablScope scope) { + Optional first = buffer.keySet().stream().filter(x -> x.toString().equals(type.toString())).findFirst(); + if (first.isEmpty()) { + ArrayVariableFmi2Api value = createBuffer(type, prefix, size, scope); + buffer.put(type, value); + return value; + + } else { + return buffer.get(first.get()); + } + } + + private ArrayVariableFmi2Api getIOBuffer(PType type) { + return getBuffer(this.ioBuffer, type, "IO", modelDescriptionContext.valRefToSv.size(), getDeclaredScope()); + } + + private ArrayVariableFmi2Api getSharedDerBuffer() { + if (this.derSharedBuffer == null) { + try { + this.derSharedBuffer = createDerValBuffer("DerShare", List.of(1, getModelDescription().getMaxOutputDerivativeOrder())); + } catch (XPathExpressionException e) { + throw new RuntimeException("Exception occurred when accessing modeldescription: " + e); + } + } + return this.derSharedBuffer; + } + + + private ArrayVariableFmi2Api getSharedBuffer(PType type) { + return this.getBuffer(this.sharedBuffer, type, "Share", 0, getDeclaredScope()); + } + + private ArrayVariableFmi2Api createMDArrayRecursively(List arraySizes, PStm declaringStm, PStateDesignatorBase stateDesignator, + PExpBase indexExp) { + + if (arraySizes.size() > 1) { + List arrays = new ArrayList<>(); + for (int i = 0; i < arraySizes.get(0); i++) { + arrays.add(createMDArrayRecursively(arraySizes.subList(1, arraySizes.size()), declaringStm, + newAArayStateDesignator(stateDesignator, newAIntLiteralExp(i)), newAArrayIndexExp(indexExp, List.of(newAIntLiteralExp(i))))); + } + return new ArrayVariableFmi2Api(declaringStm, arrays.get(0).getType(), getDeclaredScope(), builder.getDynamicScope(), stateDesignator, + indexExp.clone(), arrays); + } + + List> variables = new ArrayList<>(); + for (int i = 0; i < arraySizes.get(0); i++) { + variables.add(new VariableFmi2Api<>(declaringStm, type, getDeclaredScope(), builder.getDynamicScope(), + newAArayStateDesignator(stateDesignator.clone(), newAIntLiteralExp(i)), + newAArrayIndexExp(indexExp.clone(), List.of(newAIntLiteralExp(i))))); + } + return new ArrayVariableFmi2Api<>(declaringStm, variables.get(0).getType(), getDeclaredScope(), builder.getDynamicScope(), + ((AArrayStateDesignator) variables.get(0).getDesignatorClone()).getTarget(), indexExp.clone(), variables); + } + + private ArrayVariableFmi2Api createDerValBuffer(String identifyingName, List lengths) { + String bufferName = builder.getNameGenerator().getName(this.name, identifyingName); + + PStm arrayVariableStm = newALocalVariableStm( + newAVariableDeclarationMultiDimensionalArray(newAIdentifier(bufferName), newARealNumericPrimitiveType(), lengths)); + + getDeclaredScope().addAfter(getDeclaringStm(), arrayVariableStm); + + return createMDArrayRecursively(lengths, arrayVariableStm, newAIdentifierStateDesignator(newAIdentifier(bufferName)), + newAIdentifierExp(bufferName)); + } + + private ArrayVariableFmi2Api createBuffer(PType type, String prefix, int length, IMablScope scope) { + + //lets find a good place to store the buffer. + String ioBufName = builder.getNameGenerator().getName(this.name, type + "", prefix); + + PStm var = newALocalVariableStm(newAVariableDeclaration(newAIdentifier(ioBufName), type, length, null)); + + getDeclaredScope().addAfter(getDeclaringStm(), var); + + List> items = IntStream.range(0, length).mapToObj( + i -> new VariableFmi2Api<>(var, type, scope, builder.getDynamicScope(), + newAArayStateDesignator(newAIdentifierStateDesignator(newAIdentifier(ioBufName)), newAIntLiteralExp(i)), + newAArrayIndexExp(newAIdentifierExp(ioBufName), Collections.singletonList(newAIntLiteralExp(i))))) + .collect(Collectors.toList()); + + return new ArrayVariableFmi2Api<>(var, type, scope, builder.getDynamicScope(), newAIdentifierStateDesignator(newAIdentifier(ioBufName)), + newAIdentifierExp(ioBufName), items); + + } + + @Override + public void setDebugLogging(List categories, boolean enableLogging) { + AArrayInitializer loglevelsArrayInitializer = null; + String arrayName = name + LOGLEVELS_POSTFIX; + IMablScope scope = builder.getDynamicScope().getActiveScope(); + if (!categories.isEmpty()) { + loglevelsArrayInitializer = + newAArrayInitializer(categories.stream().map(MableAstFactory::newAStringLiteralExp).collect(Collectors.toList())); + } + ALocalVariableStm arrayContent = MableAstFactory.newALocalVariableStm( + MableAstFactory.newAVariableDeclaration(MableAstFactory.newAIdentifier(arrayName), + MableAstFactory.newAArrayType(MableAstFactory.newAStringPrimitiveType()), categories.size(), loglevelsArrayInitializer)); + + LexIdentifier statusIdentifier = newAIdentifier(getEnvironmentName() + "_" + CATEGORY_STATUS); + + ALocalVariableStm callStm = newALocalVariableStm(newAVariableDeclaration(statusIdentifier, newAIntNumericPrimitiveType(), newAExpInitializer( + newACallExp(newAIdentifierExp(name), newAIdentifier("setDebugLogging"), + Arrays.asList(newABoolLiteralExp(enableLogging), MableAstFactory.newAIntLiteralExp(categories.size()), + MableAstFactory.newAIdentifierExp(arrayName)))))); + + scope.add(arrayContent, callStm); + + if (builder.getSettings().fmiErrorHandlingEnabled) { + FmiStatusErrorHandlingBuilder.generate(builder, "setDebugLogging", this, (IMablScope) scope, MablApiBuilder.FmiStatus.FMI_ERROR, + MablApiBuilder.FmiStatus.FMI_FATAL); + } + } + + @Override + public void setupExperiment(Fmi2Builder.DoubleVariable startTime, Fmi2Builder.DoubleVariable endTime, + Fmi2Builder.BoolVariable endTimeDefined, Double tolerance) { + this.setupExperiment(((DoubleVariableFmi2Api) startTime).getReferenceExp().clone(), + ((DoubleVariableFmi2Api) endTime).getReferenceExp().clone(), ((BooleanVariableFmi2Api) endTimeDefined).getReferenceExp().clone(), + tolerance); + } + + @Override + public void setupExperiment(double startTime, Double endTime, Double tolerance) { + this.setupExperiment(newARealLiteralExp(startTime), newARealLiteralExp(endTime), newABoolLiteralExp(true), tolerance); + } + + private void setupExperiment(PExp startTime, PExp endTime, PExp endTimeDefined, Double tolerance) { + IMablScope scope = builder.getDynamicScope().getActiveScope(); + this.setupExperiment(scope, startTime, endTime, endTimeDefined, tolerance); + } + + private void setupExperiment(Fmi2Builder.Scope scope, PExp startTime, PExp endTime, PExp endTimeDefined, Double tolerance) { + AAssigmentStm stm = newAAssignmentStm(((IMablScope) scope).getFmiStatusVariable().getDesignator().clone(), + call(this.getReferenceExp().clone(), createFunctionName(FmiFunctionType.SETUPEXPERIMENT), new ArrayList<>( + Arrays.asList(newABoolLiteralExp(tolerance != null), newARealLiteralExp(tolerance != null ? tolerance : 0d), + startTime.clone(), endTimeDefined, endTime != null ? endTime.clone() : newARealLiteralExp(0d))))); + scope.add(stm); + if (builder.getSettings().fmiErrorHandlingEnabled) { + FmiStatusErrorHandlingBuilder.generate(builder, "setupExperiment", this, (IMablScope) scope, MablApiBuilder.FmiStatus.FMI_ERROR, + MablApiBuilder.FmiStatus.FMI_FATAL); + } + } + + @Override + public void enterInitializationMode() { + this.enterInitializationMode(builder.getDynamicScope()); + + } + + @Override + public void exitInitializationMode() { + this.exitInitializationMode(builder.getDynamicScope()); + } + + @Override + public void setupExperiment(Fmi2Builder.Scope scope, Fmi2Builder.DoubleVariable startTime, Fmi2Builder.DoubleVariable endTime, + Fmi2Builder.BoolVariable endTimeDefined, Double tolerance) { + this.setupExperiment(scope, ((DoubleVariableFmi2Api) startTime).getReferenceExp().clone(), + ((DoubleVariableFmi2Api) endTime).getReferenceExp().clone(), endTimeDefined.getExp().clone(), tolerance); + } + + @Override + public void setupExperiment(Fmi2Builder.Scope scope, double startTime, Double endTime, Double tolerance) { + this.setupExperiment(scope, newARealLiteralExp(startTime), newARealLiteralExp(endTime), newABoolLiteralExp(true), tolerance); + } + + @Override + public void enterInitializationMode(Fmi2Builder.Scope scope) { + PStm stm = stateTransitionFunction(FmiFunctionType.ENTERINITIALIZATIONMODE); + scope.add(stm); + if (builder.getSettings().fmiErrorHandlingEnabled) { + FmiStatusErrorHandlingBuilder.generate(builder, "enterInitializationMode", this, (IMablScope) scope, MablApiBuilder.FmiStatus.FMI_ERROR, + MablApiBuilder.FmiStatus.FMI_FATAL); + } + } + + @Override + public void exitInitializationMode(Fmi2Builder.Scope scope) { + PStm stm = stateTransitionFunction(FmiFunctionType.EXITINITIALIZATIONMODE); + scope.add(stm); + if (builder.getSettings().fmiErrorHandlingEnabled) { + FmiStatusErrorHandlingBuilder.generate(builder, "exitInitializationMode", this, (IMablScope) scope, MablApiBuilder.FmiStatus.FMI_ERROR, + MablApiBuilder.FmiStatus.FMI_FATAL); + } + } + + @Override + public Map.Entry, Fmi2Builder.DoubleVariable> step(Fmi2Builder.Scope scope, + Fmi2Builder.DoubleVariable currentCommunicationPoint, Fmi2Builder.DoubleVariable communicationStepSize, + Fmi2Builder.BoolVariable noSetFMUStatePriorToCurrentPoint) { + return step(scope, currentCommunicationPoint, communicationStepSize, ((VariableFmi2Api) noSetFMUStatePriorToCurrentPoint).getReferenceExp()); + } + + @Override + public Map.Entry, Fmi2Builder.DoubleVariable> step(Fmi2Builder.Scope scope, + Fmi2Builder.DoubleVariable currentCommunicationPoint, Fmi2Builder.DoubleVariable communicationStepSize) { + return step(scope, currentCommunicationPoint, communicationStepSize, newABoolLiteralExp(false)); + } + + @Override + public Map.Entry, Fmi2Builder.DoubleVariable> step( + Fmi2Builder.DoubleVariable currentCommunicationPoint, Fmi2Builder.DoubleVariable communicationStepSize, + Fmi2Builder.BoolVariable noSetFMUStatePriorToCurrentPoint) { + return step(dynamicScope, currentCommunicationPoint, communicationStepSize, noSetFMUStatePriorToCurrentPoint); + } + + @Override + public Map.Entry, Fmi2Builder.DoubleVariable> step( + Fmi2Builder.DoubleVariable currentCommunicationPoint, Fmi2Builder.DoubleVariable communicationStepSize) { + return step(dynamicScope, currentCommunicationPoint, communicationStepSize, newABoolLiteralExp(false)); + } + + private Map.Entry, Fmi2Builder.DoubleVariable> step(Fmi2Builder.Scope scope, + Fmi2Builder.DoubleVariable currentCommunicationPoint, Fmi2Builder.DoubleVariable communicationStepSize, + PExp noSetFMUStatePriorToCurrentPoint) { + + scope.add(newAAssignmentStm(((IMablScope) scope).getFmiStatusVariable().getDesignator().clone(), + newACallExp(this.getReferenceExp().clone(), newAIdentifier("doStep"), + Arrays.asList(((VariableFmi2Api) currentCommunicationPoint).getReferenceExp().clone(), + ((VariableFmi2Api) communicationStepSize).getReferenceExp().clone(), noSetFMUStatePriorToCurrentPoint.clone())))); + + if (builder.getSettings().fmiErrorHandlingEnabled) { + FmiStatusErrorHandlingBuilder.generate(builder, "doStep", this, (IMablScope) scope, MablApiBuilder.FmiStatus.FMI_ERROR, + MablApiBuilder.FmiStatus.FMI_FATAL); + } + + + scope.add(newIf(newNotEqual(((IMablScope) scope).getFmiStatusVariable().getReferenceExp().clone(), + builder.getFmiStatusConstant(MablApiBuilder.FmiStatus.FMI_OK).getReferenceExp().clone()), newABlockStm( + newIf(newEqual(((IMablScope) scope).getFmiStatusVariable().getReferenceExp().clone(), + builder.getFmiStatusConstant(MablApiBuilder.FmiStatus.FMI_DISCARD).getReferenceExp().clone()), newABlockStm( + newAAssignmentStm(((IMablScope) scope).getFmiStatusVariable().getDesignator().clone(), + newACallExp(this.getReferenceExp().clone(), newAIdentifier("getRealStatus"), + Arrays.asList(newAIntLiteralExp(FMI_STATUS_LAST_SUCCESSFUL), + newARefExp(getCurrentTimeVar().getReferenceExp().clone())))), + newAAssignmentStm(getCurrentTimeFullStepVar().getDesignator().clone(), newABoolLiteralExp(false))), null)), newABlockStm( + newAAssignmentStm(this.getCurrentTimeVar().getDesignator().clone(), + newPlusExp(((VariableFmi2Api) currentCommunicationPoint).getReferenceExp().clone(), + ((VariableFmi2Api) communicationStepSize).getReferenceExp().clone())), + newAAssignmentStm(getCurrentTimeFullStepVar().getDesignator().clone(), newABoolLiteralExp(true))))); + + return Map.entry(getCurrentTimeFullStepVar(), getCurrentTimeVar()); + } + + private PStm stateTransitionFunction(FmiFunctionType type) { + switch (type) { + case ENTERINITIALIZATIONMODE: + break; + case EXITINITIALIZATIONMODE: + break; + case TERMINATE: + break; + default: + throw new RuntimeException("Attempting to call state transition function with non-state transition function type: " + type); + } + + AAssigmentStm stm = newAAssignmentStm(((IMablScope) this.dynamicScope).getFmiStatusVariable().getDesignator().clone(), + call(this.getReferenceExp().clone(), createFunctionName(type))); + return stm; + } + + @Override + public List getPorts() { + return ports; + } + + @Override + public List getPorts(String... names) { + List accept = Arrays.asList(names); + return ports.stream().filter(p -> accept.contains(p.getName())).collect(Collectors.toList()); + } + + @Override + public List getPorts(int... valueReferences) { + List accept = Arrays.stream(valueReferences).boxed().collect(Collectors.toList()); + return ports.stream().filter(p -> accept.contains(p.getPortReferenceValue().intValue())).collect(Collectors.toList()); + } + + @Override + public PortFmi3Api getPort(String name) { + return (PortFmi3Api) this.getPorts(name).get(0); + } + + @Override + public PortFmi3Api getPort(int valueReference) { + return (PortFmi3Api) this.getPorts(valueReference).get(0); + } + + //TODO: Move tentative buffer and global share buffer logic to its own module so that it is not coupled with the component logic? + public Map> getTentative(IMablScope scope, String... names) { + // Get filtered port values + Fmi2Builder.Port[] filteredPorts = this.ports.stream() + .filter(p -> Arrays.asList(names).contains(p.getName()) && (p.scalarVariable.getVariable().getCausality() == Fmi3Causality.Output)) + .toArray(Fmi2Builder.Port[]::new); + Map> portToValueMap = get(scope, filteredPorts); + if (portToValueMap.isEmpty()) { + return Map.of(); + } + + // Get tentative buffer index map for the scope + tentativeBufferIndexMap.computeIfAbsent(scope, (s) -> new HashMap<>()); + Map portToVariableIndexMap = tentativeBufferIndexMap.get(scope); + + // Return a port value map where the value is an index in a tentative buffer for the given scope instead of the global IO buffer + return portToValueMap.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> { + PType type = entry.getKey().getType(); + PortFmi3Api port = entry.getKey(); + VariableFmi2Api variable = entry.getValue(); + VariableFmi2Api varToReturn; + + // Get the tentative buffer for the given scope + tentativeBuffer.computeIfAbsent(scope, (s) -> new HashMap<>()); + ArrayVariableFmi2Api buffer = + this.getBuffer(tentativeBuffer.getOrDefault(scope, new HashMap<>()), type, "TentativeBuffer", 0, scope); + + // Expand the buffer if the port has not been indexed + if (!portToVariableIndexMap.containsKey(port)) { + portToVariableIndexMap.put(port, portToVariableIndexMap.entrySet().size()); + ArrayVariableFmi2Api newBuf = growBuffer(buffer, 1); + tentativeBuffer.get(scope).entrySet().removeIf(x -> x.getKey().toString().equals(type.toString())); + tentativeBuffer.get(scope).put(type, newBuf); + varToReturn = (VariableFmi2Api) newBuf.items().get(newBuf.items().size() - 1); + } else { + varToReturn = (VariableFmi2Api) buffer.items().get(portToVariableIndexMap.get(port)); + } + + // Create the assignment from the IO buffer to the tentative buffer in MaBL + scope.add(MableAstFactory.newAAssignmentStm(varToReturn.getDesignator(), variable.getExp())); + return varToReturn; + })); + } + + @Override + public Map> get(Fmi2Builder.Port... ports) { + return get(builder.getDynamicScope().getActiveScope(), ports); + } + + @Override + public Map> get(Fmi2Builder.Scope scope, Fmi2Builder.Port... ports) { + + List selectedPorts; + if (ports == null || ports.length == 0) { + return Map.of(); + } else { + selectedPorts = Arrays.stream(ports).map(PortFmi3Api.class::cast).collect(Collectors.toList()); + } + + Map> results = new HashMap<>(); + + Map> typeToSortedPorts = new HashMap<>(); + ArrayVariableFmi2Api vrefBuf = getValueReferenceBuffer(); + + selectedPorts.stream().map(p -> p.scalarVariable.getVariable().getTypeIdentifier()).distinct() + .map(t -> selectedPorts.stream().filter(p -> p.scalarVariable.getVariable().getTypeIdentifier().equals(t)) + .sorted(Comparator.comparing(Fmi2Builder.Port::getPortReferenceValue)).collect(Collectors.toList())) + .forEach(l -> typeToSortedPorts.put(l.get(0).scalarVariable.getVariable().getTypeIdentifier(), l)); + + for (Map.Entry> e : typeToSortedPorts.entrySet()) { + for (int i = 0; i < e.getValue().size(); i++) { + PortFmi3Api p = e.getValue().get(i); + PStateDesignator designator = vrefBuf.items().get(i).getDesignator().clone(); + scope.add(newAAssignmentStm(designator, newAIntLiteralExp(p.getPortReferenceValue().intValue()))); + } + + + PType type; + switch (e.getKey()) { +// case Boolean: +// type = new ABooleanPrimitiveType(); +// break; +// case Real: +// type = new ARealNumericPrimitiveType(); +// break; +// case Integer: +// type = new AIntNumericPrimitiveType(); +// break; +// case String: +// type = new AStringPrimitiveType(); +// break; +// case Enumeration: +// throw new RuntimeException("Cannot assign enumeration port type."); +// default: +// throw new RuntimeException("Cannot match port types."); + default: + type = new AIntNumericPrimitiveType(); // TODO For now for testing + } + + ArrayVariableFmi2Api valBuf = getIOBuffer(type); + + AAssigmentStm stm = newAAssignmentStm(((IMablScope) scope).getFmiStatusVariable().getDesignator().clone(), + call(this.getReferenceExp().clone(), createFunctionName(FmiFunctionType.GET, e.getValue().get(0)), + vrefBuf.getReferenceExp().clone(), newAUIntLiteralExp((long) e.getValue().size()), valBuf.getReferenceExp().clone())); + scope.add(stm); + + if (builder.getSettings().fmiErrorHandlingEnabled) { + FmiStatusErrorHandlingBuilder.generate(builder, createFunctionName(FmiFunctionType.GET, e.getValue().get(0)), this, + (IMablScope) scope, MablApiBuilder.FmiStatus.FMI_ERROR, MablApiBuilder.FmiStatus.FMI_FATAL); + } + + if (builder.getSettings().setGetDerivatives && type.equals(new ARealNumericPrimitiveType())) { + derivativePortsToShare = getDerivatives(e.getValue(), scope); + } + + for (int i = 0; i < e.getValue().size(); i++) { + results.put(e.getValue().get(i), (VariableFmi2Api) valBuf.items().get(i)); + } + } + return results; + } + + /** + * @param ports The ports for which derivatives should be retrieved + * @param scope The builder scope. + * @return Derivative ports with a list of derivative values up to max derivative order + */ + public Map>> getDerivatives(List ports, Fmi2Builder.Scope scope) { + Map>> derivativePortsToReturn = new HashMap<>(); + +// // If any target ports exists that can interpolate the port is also linked and derivatives should be retrieved. +// // TODO: interpolation for FMI3? +// List portsLinkedToTargetsThatInterpolates = ports.stream().filter(p1 -> p1.getTargetPorts().stream().anyMatch(p2 -> { +// try { +// return p2.aMablFmi3InstanceAPI.getModelDescription().getCanInterpolateInputs(); +// } catch (XPathExpressionException e) { +// throw new RuntimeException("Exception occurred when accessing modeldescription: ", e); +// } +// })).collect(Collectors.toList()); +// +// try { +// int maxOutputDerOrder = modelDescriptionContext.getModelDescription().getMaxOutputDerivativeOrder(); +// if (portsLinkedToTargetsThatInterpolates.size() > 0 && maxOutputDerOrder > 0) { +// +// // Find derivative ports +// List derivativePorts = new ArrayList<>(); +// modelDescriptionContext.getModelDescription().getDerivativeToDerivativeSourceMap().entrySet().stream() +// .filter(entry -> portsLinkedToTargetsThatInterpolates.stream() +// .anyMatch(p -> p.getPortReferenceValue().equals(entry.getKey().getVariable().getValueReference()))).forEach(e -> +// // Find the PortFmi3Api representation of the scalarvariable derivative port. +// getPorts().stream().filter(p -> p.getPortReferenceValue().equals(e.getValue().getVariable().getValueReference())).findAny() +// .ifPresent(derivativePorts::add)); +// +// if (derivativePorts.size() > 0) { +// // Array size: number of ports for which to get derivatives multiplied the max derivative order. +// int arraySize = derivativePorts.size() * maxOutputDerOrder; +// +// ArrayVariableFmi2Api derValOutBuf = createBuffer(newRealType(), "DVal_OUT", arraySize, getDeclaredScope()); +// ArrayVariableFmi2Api derOrderOutBuf = createBuffer(newIntType(), "DOrder_OUT", arraySize, getDeclaredScope()); +// ArrayVariableFmi2Api derRefOutBuf = createBuffer(newUIntType(), "DRef_OUT", arraySize, getDeclaredScope()); +// +// // Loop arrays and assign derivative value reference and derivative order. +// // E.g for two ports with and a max derivative order of two: derRefOutBuf = [derPortRef1, derPortRef1, derPortRef2,derPortRef2], +// // derOrderOutBuf = [1,2,1,2] +// PortFmi3Api derivativePort = null; +// for (int arrayIndex = 0, portIndex = 0, order = 1; arrayIndex < arraySize; arrayIndex++) { +// // Switch to the next port when we have traversed a length of 'maxOutputDerOrder' in the arrays and reset order. +// if (arrayIndex % maxOutputDerOrder == 0) { +// order = 1; +// derivativePort = derivativePorts.get(portIndex); +// derivativePortsToReturn.put(derivativePort, derValOutBuf.items().subList(arrayIndex, arrayIndex + maxOutputDerOrder)); +// portIndex++; +// } +// +// PStateDesignator dRefDesignator = derRefOutBuf.items().get(arrayIndex).getDesignator().clone(); +// scope.add(newAAssignmentStm(dRefDesignator, newAIntLiteralExp(derivativePort.getPortReferenceValue().intValue()))); +// +// PStateDesignator derOrderDesignator = derOrderOutBuf.items().get(arrayIndex).getDesignator().clone(); +// scope.add(newAAssignmentStm(derOrderDesignator, newAIntLiteralExp(order))); +// order++; +// } +// +// // Create assignment statement which assigns derivatives to derValOutBuf by calling getRealOutputDerivatives with +// // derRefOutBuf, arraySize and derOrderOutBuf. +// PStm AStm = newAAssignmentStm(builder.getGlobalFmiStatus().getDesignator().clone(), +// call(this.getReferenceExp().clone(), createFunctionName(FmiFunctionType.GETREALOUTPUTDERIVATIVES), +// derRefOutBuf.getReferenceExp().clone(), newAUIntLiteralExp((long) arraySize), +// derOrderOutBuf.getReferenceExp().clone(), derValOutBuf.getReferenceExp().clone())); +// scope.add(AStm); +// +// // If enabled handle potential errors from calling getRealOutputDerivatives +// if (builder.getSettings().fmiErrorHandlingEnabled) { +// FmiStatusErrorHandlingBuilder.generate(builder, createFunctionName(FmiFunctionType.GETREALOUTPUTDERIVATIVES), this, +// (IMablScope) scope, MablApiBuilder.FmiStatus.FMI_ERROR, MablApiBuilder.FmiStatus.FMI_FATAL); +// } +// } +// } +// // TODO InvocationTargetException | IllegalAccessException ? +// } catch (XPathExpressionException e) { +// throw new RuntimeException("Exception occurred when retrieving derivatives: ", e); +// } + + return derivativePortsToReturn; + } + + @Override + public Map> get() { + return get(builder.getDynamicScope(), outputPorts.toArray(Fmi2Builder.Port[]::new)); + } + + @Override + public Map> get(int... valueReferences) { + List accept = Arrays.stream(valueReferences).boxed().collect(Collectors.toList()); + return get(builder.getDynamicScope(), + outputPorts.stream().filter(p -> accept.contains(p.getPortReferenceValue().intValue())).toArray(Fmi2Builder.Port[]::new)); + } + + @Override + public Map> get(String... names) { + List accept = Arrays.asList(names); + Fmi2Builder.Port[] ports = this.ports.stream().filter(p -> accept.contains(p.getName())).toArray(Fmi2Builder.Port[]::new); + return get(builder.getDynamicScope(), ports); + } + + /** + * Stores the final value in rootScope + * Uses the rootScope for valueReferences + */ + @Override + public Map> getAndShare(String... names) { + + Map> values = get(names); + share(values); + return values; + } + + @Override + public Map> getAndShare(Fmi2Builder.Port... ports) { + Map> values = get(ports); + share(values); + return values; + } + + @Override + public Map> getAndShare() { + Map> values = get(); + share(values); + return values; + } + + @Override + public VariableFmi2Api getShared(String name) { + return this.getPort(name).getSharedAsVariable(); + } + + @Override + public VariableFmi2Api getShared(Fmi2Builder.Port port) { + return ((PortFmi3Api) port).getSharedAsVariable(); + } + + @Override + public VariableFmi2Api getSingle(Fmi2Builder.Port port) { + return (VariableFmi2Api) this.get(port).entrySet().iterator().next().getValue(); + } + + private String createFunctionName(FmiFunctionType fun) { + switch (fun) { + case ENTERINITIALIZATIONMODE: + return "enterInitializationMode"; + case EXITINITIALIZATIONMODE: + return "exitInitializationMode"; + case SETUPEXPERIMENT: + return "setupExperiment"; + case GETREALOUTPUTDERIVATIVES: + return "getRealOutputDerivatives"; + case SETREALINPUTDERIVATIVES: + return "setRealInputDerivatives"; + case TERMINATE: + return "terminate"; + default: + throw new RuntimeException("Attempting to call function that is type dependant without specifying type: " + fun); + } + + } + + private String createFunctionName(FmiFunctionType fun, PortFmi3Api p) { + return createFunctionName(fun, p.scalarVariable.getVariable().getTypeIdentifier()); + } + + private String createFunctionName(FmiFunctionType f, Fmi3TypeEnum type) { + String functionName = ""; + switch (f) { + case GET: + functionName += "get"; + break; + case SET: + functionName += "set"; + break; + default: + throw new RuntimeException("Attempting to call non type-dependant function with type: " + type); + } + functionName += type.name(); + return functionName; + } + + @Override + public VariableFmi2Api getSingle(String name) { + return this.get(name).entrySet().iterator().next().getValue(); + } + + + + public void set(Fmi2Builder.Port p, Fmi2Builder.ExpressionValue v) { + this.set(new PortValueExpresssionMapImpl(Map.of(p, v))); + ; + } + + public void set(Fmi2Builder.Scope scope, Fmi2Builder.Port p, Fmi2Builder.ExpressionValue v) { + this.set(scope, new PortValueMapImpl(Map.of(p, v))); + } + + public void set(PortExpressionValueMap value) { + this.set(builder.getDynamicScope().getActiveScope(), value); + } + + public void set(Fmi2Builder.Scope scope, PortExpressionValueMap value) { + if (value == null || value.isEmpty()) { + return; + } + + List selectedPorts = value.keySet().stream().map(PortFmi3Api.class::cast).collect(Collectors.toList()); + + set(scope, selectedPorts, port -> { + Fmi2Builder.ExpressionValue value_ = value.get(port); + return Map.entry(value_.getExp(), value_.getType()); + }); + } + + @Override + public void set(Fmi2Builder.Scope scope, PortValueMap value) { + + + if (value == null || value.isEmpty()) { + return; + } + + List selectedPorts = value.keySet().stream().map(PortFmi3Api.class::cast).collect(Collectors.toList()); + + + set(scope, selectedPorts, port -> { + Object val = (value.get(port)).get(); + if (val instanceof Double) { + return Map.entry(newARealLiteralExp((Double) val), newRealType()); + } + if (val instanceof Long) { + return Map.entry(newAUIntLiteralExp((Long) val), newUIntType()); + } + if (val instanceof Integer) { + return Map.entry(newAIntLiteralExp((Integer) val), newIntType()); + } + if (val instanceof Boolean) { + return Map.entry(newABoolLiteralExp((Boolean) val), newBoleanType()); + } + if (val instanceof String) { + return Map.entry(newAStringLiteralExp((String) val), newStringType()); + } + return null; + }); + } + + @Override + public void set(Fmi2Builder.Scope scope, PortVariableMap value) { + + List selectedPorts; + if (value == null || value.isEmpty()) { + return; + } else { + selectedPorts = value.keySet().stream().map(PortFmi3Api.class::cast).collect(Collectors.toList()); + } + + final PortVariableMap valueFinal = value; + set(scope, selectedPorts, + port -> Map.entry(((VariableFmi2Api) valueFinal.get(port)).getReferenceExp().clone(), ((VariableFmi2Api) valueFinal.get(port)).type)); + } + + public void set(Fmi2Builder.Scope scope, List selectedPorts, Function> portToValue) { + + Set selectedPortsAsStrings = selectedPorts.stream() + .map(p -> p.getName() + "-" + p.aMablFmi3InstanceAPI.getName() + "-" + p.aMablFmi3InstanceAPI.getOwner().getName()) + .collect(toSet()); + selectedPortsAsStrings.removeAll( + ports.stream().map(p -> p.getName() + "-" + p.aMablFmi3InstanceAPI.getName() + "-" + p.aMablFmi3InstanceAPI.getOwner().getName()) + .collect(toSet())); + if (selectedPortsAsStrings.size() > 0) { + throw new RuntimeException("Unable to set port(s) that is not declared in the FMU: " + + selectedPortsAsStrings.stream().map(name -> name.split("-")[0]).collect(Collectors.joining(", "))); + } + + List sortedPorts = + selectedPorts.stream().sorted(Comparator.comparing(Fmi2Builder.Port::getPortReferenceValue)).collect(Collectors.toList()); + + // Group by the string value of the port type as grouping by the port type itself doesnt utilise equals + sortedPorts.stream().collect(Collectors.groupingBy(i -> i.getType().toString())).forEach((key, value) -> { + ArrayVariableFmi2Api vrefBuf = getValueReferenceBuffer(); + PType type = value.get(0).getType(); + for (int i = 0; i < value.size(); i++) { + Fmi2Builder.Port p = value.get(i); + PStateDesignator designator = vrefBuf.items().get(i).getDesignator().clone(); + scope.add(newAAssignmentStm(designator, newAIntLiteralExp(p.getPortReferenceValue().intValue()))); + } + + ArrayVariableFmi2Api valBuf = getIOBuffer(type); + for (int i = 0; i < value.size(); i++) { + PortFmi3Api p = value.get(i); + PStateDesignator designator = valBuf.items().get(i).getDesignator(); + + scope.addAll(BuilderUtil.createTypeConvertingAssignment(builder, scope, designator.clone(), portToValue.apply(p).getKey().clone(), + portToValue.apply(p).getValue(), valBuf.type)); + } + + AAssigmentStm stm = newAAssignmentStm(((IMablScope) scope).getFmiStatusVariable().getDesignator().clone(), + call(this.getReferenceExp().clone(), createFunctionName(FmiFunctionType.SET, value.get(0)), vrefBuf.getReferenceExp().clone(), + newAUIntLiteralExp((long) value.size()), valBuf.getReferenceExp().clone())); + scope.add(stm); + + if (builder.getSettings().fmiErrorHandlingEnabled) { + FmiStatusErrorHandlingBuilder.generate(builder, createFunctionName(FmiFunctionType.SET, sortedPorts.get(0)), this, (IMablScope) scope, + MablApiBuilder.FmiStatus.FMI_ERROR, MablApiBuilder.FmiStatus.FMI_FATAL); + } + + // TODO: IntermediateUpdateMode instead of CanInterpolateInputs? + // TODO: commented out for no so it compiles +// try { +// if (builder.getSettings().setGetDerivatives && modelDescriptionContext.getModelDescription().getCanInterpolateInputs() && +// type.equals(new ARealNumericPrimitiveType())) { +// setDerivativesForSharedPorts(value, scope); +// } +// } catch (XPathExpressionException e) { +// throw new RuntimeException("Exception occurred when when setting derivatives.", e); +// } + }); + } +// +// /** +// * @param ports The ports for which derivative should be set from SHARED derivative ports +// * @param scope The builder scope +// */ +// private void setDerivativesForSharedPorts(List ports, Fmi2Builder.Scope scope) { +// // Find all ports for which derivatives should be passed together with the derivatives and their order. +// LinkedHashMap> mapPortsToDerPortsWithOrder = +// ports.stream().filter(port -> port.getSourcePort() != null).map(port -> { +// try { +// Map.Entry innerEntry; +// // Find if port is in map of derivatives +// Optional> derivativePortEntry = +// port.getSourcePort().aMablFmi3InstanceAPI.getModelDescription().getDerivativeToDerivativeSourceMap().entrySet().stream() +// .filter(e -> e.getKey().getVariable().getValueReferenceAsLong().equals(port.getSourcePort().getPortReferenceValue())).findAny(); +// +// +// if (derivativePortEntry.isPresent()) { +// // Find PortFmi3Api value of the scalarvariable derivative port and the components max output derivative. +// innerEntry = Map.entry(port.getSourcePort().aMablFmi3InstanceAPI.getPort((int) +// derivativePortEntry.get().getValue().getVariable().getValueReferenceAsLong()), +// port.getSourcePort().aMablFmi3InstanceAPI.getModelDescription().getMaxOutputDerivativeOrder()); +// return Map.entry(port, innerEntry); +// } +// +// return null; +// } catch (XPathExpressionException | IllegalAccessException | InvocationTargetException e) { +// throw new RuntimeException("Exception occurred when accessing modeldescription: ", e); +// } +// }).filter(Objects::nonNull).collect(LinkedHashMap::new, (map, item) -> map.put(item.getKey(), item.getValue()), // Accumulator +// Map::putAll); +// +// if (mapPortsToDerPortsWithOrder.size() > 0) { +// // Get the total array size as the sum of derivative orders. +// int arraySize = mapPortsToDerPortsWithOrder.values().stream().mapToInt(Map.Entry::getValue).sum(); +// +// // Create input arrays +// ArrayVariableFmi2Api derValInBuf = createBuffer(newRealType(), "DVal_IN", arraySize, getDeclaredScope()); +// ArrayVariableFmi2Api derOrderInBuf = createBuffer(newIntType(), "DOrder_IN", arraySize, getDeclaredScope()); +// ArrayVariableFmi2Api derRefInBuf = createBuffer(newUIntType(), "DRef_IN", arraySize, getDeclaredScope()); +// +// // Loop through arrays and assign the port reference, derivative order and derivative value. +// // E.g: for two derivative ports Out1 (linked to In1) and Out2 (linked to In2) with a max derivative order of 2 and 1: derValInBuf = [der +// // (Out1), der(der(Out1)),der(Out2))], derOrderInBuf = [1,2,1], derRefInBuf = [In1, In1, In2] +// int arrayIndex = 0; +// for (Map.Entry> entry : mapPortsToDerPortsWithOrder.entrySet()) { +// PortFmi3Api port = entry.getKey(); +// int maxOrder = entry.getValue().getValue(); +// for (int order = 1; order <= maxOrder; order++, arrayIndex++) { +// // Assign to array variables +// PStateDesignator derRefDesignator = derRefInBuf.items().get(arrayIndex).getDesignator().clone(); +// scope.add(newAAssignmentStm(derRefDesignator, newAIntLiteralExp(port.getPortReferenceValue().intValue()))); +// +// PStateDesignator derOrderDesignator = derOrderInBuf.items().get(arrayIndex).getDesignator().clone(); +// scope.add(newAAssignmentStm(derOrderDesignator, newAIntLiteralExp(order))); +// +// PStateDesignator derValInDesignator = derValInBuf.items().get(arrayIndex).getDesignator().clone(); +// scope.add(newAAssignmentStm(derValInDesignator, +// ((VariableFmi2Api) ((ArrayVariableFmi2Api) entry.getValue().getKey().getSharedAsVariable()).items() +// .get(order - 1)).getReferenceExp().clone())); +// } +// } +// +// setDerivatives(derValInBuf, derOrderInBuf, derRefInBuf, scope); +// } +// } + + /** + * If two derivative ports 'Out1' (linked to 'In1') and 'Out2' (linked to 'In2') with a max derivative order of 2 and 1 then derValInBuf = + * [der(Out1), der(der(Out1)), der(Out2))], derOrderInBuf = [1,2,1], derRefInBuf = [In1, In1, In2] + * + * @param derValInBuf derivative values + * @param derOrderInBuf derivative value orders + * @param derRefInBuf ports for which to set the derivative + * @param scope the builder scope + */ + public void setDerivatives(ArrayVariableFmi2Api derValInBuf, ArrayVariableFmi2Api derOrderInBuf, ArrayVariableFmi2Api derRefInBuf, + Fmi2Builder.Scope scope) { + int arraySize = derValInBuf.size(); + + // Create set derivatives statement which calls setRealOutputDerivatives with derRefInBuf, arraySize, derOrderInBuf and + // derValInBuf. + PStm ifStm = newAAssignmentStm(builder.getGlobalFmiStatus().getDesignator().clone(), + call(this.getReferenceExp().clone(), createFunctionName(FmiFunctionType.SETREALINPUTDERIVATIVES), + derRefInBuf.getReferenceExp().clone(), newAUIntLiteralExp((long) arraySize), derOrderInBuf.getReferenceExp().clone(), + derValInBuf.getReferenceExp().clone())); + scope.add(ifStm); + + // If enabled handle potential errors from calling setRealInputDerivatives + if (builder.getSettings().fmiErrorHandlingEnabled) { + FmiStatusErrorHandlingBuilder.generate(builder, createFunctionName(FmiFunctionType.SETREALINPUTDERIVATIVES), this, (IMablScope) scope, + MablApiBuilder.FmiStatus.FMI_ERROR, MablApiBuilder.FmiStatus.FMI_FATAL); + } + } + + @Override + public void set(PortValueMap value) { + set(builder.getDynamicScope(), value); + } + + @Override + public void set(Fmi2Builder.Port port, Fmi2Builder.Variable value) { + this.set(new PortVariableMapImpl(Map.of(port, value))); + } + + @Override + public void set(Fmi2Builder.Scope scope, Fmi2Builder.Port port, Fmi2Builder.Variable value) { + this.set(scope, new PortVariableMapImpl(Map.of(port, value))); + } + + @Override + public void set(Fmi2Builder.Port port, Fmi2Builder.Value value) { + PortValueMap map = new PortValueMapImpl(); + map.put(port, value); + set(map); + + } + + + @Override + public void set(PortVariableMap value) { + set(builder.getDynamicScope(), value); + } + + @Override + public void setLinked(Fmi2Builder.Scope scope, Fmi2Builder.Port... filterPorts) { + + List selectedPorts = ports.stream().filter(isLinked).collect(Collectors.toList()); + if (filterPorts != null && filterPorts.length != 0) { + + List filterList = Arrays.asList(filterPorts); + + for (Fmi2Builder.Port p : filterList) { + if (!isLinked.test(p)) { + logger.warn("Filter for setLinked contains unlined port. Its ignored. {}", p); + } + } + + selectedPorts = selectedPorts.stream().filter(filterList::contains).collect(Collectors.toList()); + } + if (selectedPorts.size() == 0) { + logger.warn("No linked input variables for FMU instance: " + this.getName()); + return; + } + + + for (PortFmi3Api port : selectedPorts) { + if (port.getSourcePort() == null) { + throw new RuntimeException( + "Attempting to obtain shared value from a port that is not linked. This port is missing a required " + "link: " + port); + } + + if (port.getSourcePort().getSharedAsVariable() == null) { + throw new RuntimeException( + "Attempting to obtain shared values from a port that is linked but has no value shared. Share a value " + "first. " + port); + + } + } + + set(scope, selectedPorts, + k -> Map.entry(k.getSourcePort().getSharedAsVariable().getReferenceExp().clone(), k.getSourcePort().getSharedAsVariable().type)); + + } + + @Override + public void setLinked() { + this.setLinked(dynamicScope, (Fmi2Builder.Port[]) null); + } + + @Override + public void setLinked(Fmi2Builder.Port... filterPorts) { + + this.setLinked(dynamicScope, filterPorts); + } + + @Override + public void setLinked(String... filterNames) { + List accept = Arrays.asList(filterNames); + this.setLinked(dynamicScope, getPorts().stream().filter(p -> accept.contains(p.getName())).toArray(Fmi2Builder.Port[]::new)); + + } + + @Override + public void setLinked(long... filterValueReferences) { + List accept = Arrays.stream(filterValueReferences).boxed().collect(Collectors.toList()); + this.setLinked(dynamicScope, getPorts().stream().filter(p -> accept.contains(p.getPortReferenceValue())).toArray(Fmi2Builder.Port[]::new)); + + } + + @Override + public void setInt(Map> values) { + + } + + @Override + public void setString(Map> value) { + + } + + @Override + public void terminate() { + this.terminate(builder.getDynamicScope()); + } + + @Override + public void terminate(Fmi2Builder.Scope scope) { + PStm stm = stateTransitionFunction(FmiFunctionType.TERMINATE); + scope.add(stm); + if (builder.getSettings().fmiErrorHandlingEnabled) { + FmiStatusErrorHandlingBuilder.generate(builder, "terminate", this, (IMablScope) scope, MablApiBuilder.FmiStatus.FMI_ERROR, + MablApiBuilder.FmiStatus.FMI_FATAL); + } + } + + // TODO: implement this from the other share function below. This for now to build. + @Override + public void share(Map> values) { + ; + } + +// @Override +// public void share(Map> values) { +// // Group by the string value of the port type as grouping by the port type itself doesnt utilise equals +// values.entrySet().stream().collect(Collectors.groupingBy(map -> ((PortFmi3Api) map.getKey()).getType().toString())).entrySet().stream() +// .forEach(map -> { +// PType type = ((PortFmi3Api) map.getValue().get(0).getKey()).getType(); +// +// Map data = +// map.getValue().stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); +// +// data.keySet().stream().map(PortFmi3Api.class::cast).sorted(Comparator.comparing(PortFmi3Api::getPortReferenceValue)) +// .forEach(port -> { +// //this is the sorted set of assignments, these can be replaced by a memcopy later +// ArrayVariableFmi2Api buffer = getSharedBuffer(type); +// if (port.getSharedAsVariable() == null) { +// ArrayVariableFmi2Api newBuf = growBuffer(buffer, 1); +// this.setSharedBuffer(newBuf, type); +// +// VariableFmi2Api newShared = newBuf.items().get(newBuf.items().size() - 1); +// port.setSharedAsVariable(newShared); +// } +// +// PStateDesignator designator = port.getSharedAsVariable().getDesignator(); +// builder.getDynamicScope().addAll(BuilderUtil.createTypeConvertingAssignment(builder, dynamicScope, designator.clone(), +// ((VariableFmi2Api) data.get(port)).getReferenceExp().clone(), port.getType(), +// ((VariableFmi2Api) ((VariableFmi2Api) data.get(port))).type)); +// +// +// if (type.equals(new ARealNumericPrimitiveType()) && derivativePortsToShare != null) { +// // Find match a derivativePortsToShare where both port reference and derivative port reference matches. +// derivativePortsToShare.keySet().stream().filter(derivativePort -> { +// try { +// return modelDescriptionContext.getModelDescription().getDerivativesMap().entrySet().stream().anyMatch( +// e -> e.getKey().getValueReference().equals(port.getPortReferenceValue()) && +// e.getValue().getValueReference().equals(derivativePort.getPortReferenceValue())); +// } catch (XPathExpressionException | InvocationTargetException | IllegalAccessException e) { +// throw new RuntimeException( +// "Attempting to obtain shared values from a port that is linked but has no value shared. Share a value " + +// "first. " + port); +// } +// }).findFirst().ifPresent((derivativePort) -> { +// // If the derivative port is not yet shared then get shared derivative buffer, grow it by one and set the port as shared +// // with the new array. +// if (derivativePort.getSharedAsVariable() == null) { +// ArrayVariableFmi2Api sharedDerBuf = growSharedDerBuf(1); +// +// ArrayVariableFmi2Api newSharedArray = +// (ArrayVariableFmi2Api) sharedDerBuf.items().get(sharedDerBuf.items().size() - 1); +// derivativePort.setSharedAsVariable(newSharedArray); +// } +// +// // DerivativePorts.get(derivativePort).size should equal derivativePort.getSharedAsVariable().items().size() as they are +// // both determined by the max derivative order. +// List derivatives = ((ArrayVariableFmi2Api) derivativePort.getSharedAsVariable()).items(); +// for (int i = 0; i < derivatives.size(); i++) { +// PExp val = derivativePortsToShare.get(derivativePort).get(i).getReferenceExp().clone(); +// builder.getDynamicScope().add(newAAssignmentStm(derivatives.get(i).getDesignator().clone(), val)); +// } +// }); +// } +// }); +// }); +// } + + /** + * @param increaseByCount the length of which the outer array should grow + * @return a two dimensional non-jagged array for derivatives. + * e.g.: [originalSize+increaseByCount][maxDerivativeOrder] + */ + private ArrayVariableFmi2Api growSharedDerBuf(int increaseByCount) { + + // Get shared buffer creates the buffer with one element. + if (this.derSharedBuffer == null && increaseByCount == 1) { + return getSharedDerBuffer(); + } + + ArrayVariableFmi2Api sharedBuffer = getSharedDerBuffer(); + + int innerArraySize; + try { + innerArraySize = modelDescriptionContext.getModelDescription().getMaxOutputDerivativeOrder(); + } catch (XPathExpressionException e) { + throw new RuntimeException("Exception occurred when accessing model description: ", e); + } + + String bufferName = ((AIdentifierExp) sharedBuffer.getReferenceExp()).getName().getText(); + int outerArraySize = sharedBuffer.size() + increaseByCount; + + PStm outerArrayVariableStm = newALocalVariableStm( + newAVariableDeclarationMultiDimensionalArray(newAIdentifier(bufferName), newARealNumericPrimitiveType(), + Arrays.asList(outerArraySize, innerArraySize))); + + sharedBuffer.getDeclaringStm().parent().replaceChild(sharedBuffer.getDeclaringStm(), outerArrayVariableStm); + + List> items = new ArrayList<>(); + + // Add new element(s) to array. + // E.g: buff[1][1] with increaseByCount of 2 will become: buff[3][1] where 1 equals the max derivative order. + for (int i = 0; i < increaseByCount; i++) { + int outerIndex = sharedBuffer.size() + i; + + List> variables = new ArrayList<>(); + // Create variables + for (int l = 0; l < innerArraySize; l++) { + AArrayStateDesignator designator = newAArayStateDesignator( + newAArayStateDesignator(newAIdentifierStateDesignator(newAIdentifier(bufferName)), newAIntLiteralExp(outerIndex)), + newAIntLiteralExp(l)); + + AArrayIndexExp indexExp = + newAArrayIndexExp(newAIdentifierExp(bufferName), Arrays.asList(newAIntLiteralExp(outerIndex), newAIntLiteralExp(l))); + + variables.add( + new VariableFmi2Api<>(outerArrayVariableStm, type, this.getDeclaredScope(), builder.getDynamicScope(), designator, indexExp)); + } + // Create array with variables + ArrayVariableFmi2Api innerArrayVariable = + new ArrayVariableFmi2Api<>(outerArrayVariableStm, newARealNumericPrimitiveType(), getDeclaredScope(), builder.getDynamicScope(), + newAArayStateDesignator(newAIdentifierStateDesignator(newAIdentifier(bufferName)), newAIntLiteralExp(outerIndex)), + newAArrayIndexExp(newAIdentifierExp(bufferName), Collections.singletonList(newAIntLiteralExp(outerIndex))), variables); + + items.add(innerArrayVariable); + } + // Add new array(s) to existing arrays + items.addAll(0, sharedBuffer.items()); + + return new ArrayVariableFmi2Api<>(outerArrayVariableStm, newAArrayType(newARealNumericPrimitiveType()), getDeclaredScope(), + builder.getDynamicScope(), newAIdentifierStateDesignator(newAIdentifier(bufferName)), newAIdentifierExp(bufferName), items); + + } + + private void setSharedBuffer(ArrayVariableFmi2Api newBuf, PType type) { + this.sharedBuffer.entrySet().removeIf(x -> x.getKey().toString().equals(type.toString())); + this.sharedBuffer.put(type, newBuf); + + } + + private ArrayVariableFmi2Api growBuffer(ArrayVariableFmi2Api buffer, int increaseByCount) { + + String ioBufName = ((AIdentifierExp) buffer.getReferenceExp()).getName().getText(); + + int length = buffer.size() + increaseByCount; + PStm var = newALocalVariableStm(newAVariableDeclaration(newAIdentifier(ioBufName), buffer.type, length, null)); + + buffer.getDeclaringStm().parent().replaceChild(buffer.getDeclaringStm(), var); + // getDeclaredScope().addAfter(getDeclaringStm(), var); + + List> items = IntStream.range(buffer.size(), length).mapToObj( + i -> new VariableFmi2Api<>(var, buffer.type, this.getDeclaredScope(), builder.getDynamicScope(), + newAArayStateDesignator(newAIdentifierStateDesignator(newAIdentifier(ioBufName)), newAIntLiteralExp(i)), + newAArrayIndexExp(newAIdentifierExp(ioBufName), Collections.singletonList(newAIntLiteralExp(i))))) + .collect(Collectors.toList()); + + //we can not replace these as some of them may be used and could potential have reference problems (they should not but just to be sure) + items.addAll(0, buffer.items()); + + return new ArrayVariableFmi2Api<>(var, buffer.type, getDeclaredScope(), builder.getDynamicScope(), + newAIdentifierStateDesignator(newAIdentifier(ioBufName)), newAIdentifierExp(ioBufName), items); + + } + + @Override + public Fmi2Builder.StateVariable getState() throws XPathExpressionException { + return getState(builder.getDynamicScope()); + } + + @Override + public Fmi2Builder.StateVariable getState(Fmi2Builder.Scope scope) throws XPathExpressionException { + if (!this.modelDescriptionContext.getModelDescription().getCanGetAndSetFmustate()) { + throw new RuntimeException("Unable to get state on fmu: " + this.getOwner() + " with instance name: " + this.getName()); + } + + String stateName = builder.getNameGenerator().getName(name, "state"); + PStm stateVar = newVariable(stateName, newANameType("FmiComponentState")); + scope.add(stateVar); + + StateMablVariableFmi3Api state = + new StateMablVariableFmi3Api(stateVar, newANameType("FmiComponentState"), (IMablScope) scope, builder.getDynamicScope(), + newAIdentifierStateDesignator(stateName), newAIdentifierExp(stateName), builder, this); + + AAssigmentStm stm = newAAssignmentStm(((IMablScope) scope).getFmiStatusVariable().getDesignator().clone(), + call(this.getReferenceExp().clone(), "getState", Collections.singletonList(newARefExp(state.getReferenceExp().clone())))); + scope.add(stm); + if (builder.getSettings().fmiErrorHandlingEnabled) { + FmiStatusErrorHandlingBuilder.generate(builder, "getState", this, (IMablScope) scope, MablApiBuilder.FmiStatus.FMI_ERROR, + MablApiBuilder.FmiStatus.FMI_FATAL); + } + + return state; + } + + public FmuVariableFmi3Api getOwner() { + return this.owner; + } + + public List getAllConnectedOutputs() { + return this.ports.stream().filter(x -> x.scalarVariable.getVariable().getCausality() == Fmi3Causality.Output && x.getTargetPorts().size() > 0) + .collect(Collectors.toList()); + } + + @Override + public String getName() { + return this.name; + } + + public String getEnvironmentName() { + return environmentName; + } + + + public enum FmiFunctionType { + GET, + SET, + ENTERINITIALIZATIONMODE, + EXITINITIALIZATIONMODE, + SETUPEXPERIMENT, + GETREALOUTPUTDERIVATIVES, + SETREALINPUTDERIVATIVES, + TERMINATE + } + + /** + * Error and Fatal should lead to freeInstance calls followed by subsequent termination. + */ + static class FmiStatusErrorHandlingBuilder { + static void generate(MablApiBuilder builder, String method, InstanceVariableFmi3Api instance, IMablScope scope, + MablApiBuilder.FmiStatus... statusesToFail) { + if (statusesToFail == null || statusesToFail.length == 0) { + return; + } + + Function checkStatusEq = + s -> newEqual(((IMablScope) scope).getFmiStatusVariable().getReferenceExp().clone(), + builder.getFmiStatusConstant(s).getReferenceExp().clone()); + + PExp exp = checkStatusEq.apply(statusesToFail[0]); + + for (int i = 1; i < statusesToFail.length; i++) { + exp = newOr(exp, checkStatusEq.apply(statusesToFail[i])); + } + + ScopeFmi2Api thenScope = scope.enterIf(new PredicateFmi2Api(exp)).enterThen(); + + // thenScope.add(newAAssignmentStm(builder.getGlobalExecutionContinue().getDesignator().clone(), newABoolLiteralExp(false))); + + for (MablApiBuilder.FmiStatus status : statusesToFail) { + ScopeFmi2Api s = thenScope.enterIf(new PredicateFmi2Api(checkStatusEq.apply(status))).enterThen(); + builder.getLogger() + .error(s, method.substring(0, 1).toUpperCase() + method.substring(1) + " failed on '%s' with status: " + status, instance); + } + + thenScope.add(new AErrorStm(newAStringLiteralExp("Failed to '" + method + "' on '" + instance.getName() + "'"))); + thenScope.leave(); + } + + static Set collectedPreviousLoadedModules(INode node/*, Set externalLoadedModuleIdentifiers*/) { + + if (node == null) { + return new HashSet<>(); + } + + Function getLoadedIdentifier = s -> { + AtomicReference id = new AtomicReference<>(); + try { + s.apply(new DepthFirstAnalysisAdaptor() { + @Override + public void caseALoadExp(ALoadExp node) { + AVariableDeclaration decl = node.getAncestor(AVariableDeclaration.class); + if (decl != null) { + id.set(decl.getName().getText()); + } + ALocalVariableStm ldecl = node.getAncestor(ALocalVariableStm.class); + if (decl != null) { + id.set(ldecl.getDeclaration().getName().getText()); + } + } + }); + } catch (AnalysisException e) { + e.addSuppressed(e); + } + return id.get(); + }; + + Set identifiers = new HashSet<>(); + if (node instanceof SBlockStm) { + + for (PStm n : ((SBlockStm) node).getBody()) { + String id = getLoadedIdentifier.apply(n); + if (id != null) { + identifiers.add(id); + } + } + } + + if (node.parent() != null) { + identifiers.addAll(collectedPreviousLoadedModules(node.parent()/*, externalLoadedModuleIdentifiers*/)); + } + /* + if (identifiers != null) { + identifiers.removeAll(externalLoadedModuleIdentifiers); + }*/ + + return identifiers; + + } + } + } diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/StateMablVariableFmi2Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/StateMablVariableFmi2Api.java index c2cfc3b11..1dea8288d 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/StateMablVariableFmi2Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/StateMablVariableFmi2Api.java @@ -22,11 +22,14 @@ public StateMablVariableFmi2Api(PStm declaration, PType type, IMablScope declare this.builder = builder; } + @Override public void set() throws IllegalStateException { set(builder.getDynamicScope()); } + + @Override public void set(Fmi2Builder.Scope scope) throws IllegalStateException { if (!valid) { diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/StateMablVariableFmi3Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/StateMablVariableFmi3Api.java new file mode 100644 index 000000000..826610ad2 --- /dev/null +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/StateMablVariableFmi3Api.java @@ -0,0 +1,75 @@ +package org.intocps.maestro.framework.fmi2.api.mabl.variables; + +import org.intocps.maestro.ast.node.*; +import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.mabl.MablApiBuilder; +import org.intocps.maestro.framework.fmi2.api.mabl.scoping.IMablScope; + +import java.util.Collections; + +import static org.intocps.maestro.ast.MableAstFactory.newAAssignmentStm; +import static org.intocps.maestro.ast.MableBuilder.call; + +public class StateMablVariableFmi3Api extends VariableFmi2Api implements Fmi2Builder.StateVariable { + private final InstanceVariableFmi3Api owner; + private final MablApiBuilder builder; + private boolean valid = true; + + public StateMablVariableFmi3Api(PStm declaration, PType type, IMablScope declaredScope, Fmi2Builder.DynamicActiveScope dynamicScope, + PStateDesignator designator, PExp referenceExp, MablApiBuilder builder, InstanceVariableFmi3Api owner) { + super(declaration, type, declaredScope, dynamicScope, designator, referenceExp); + this.owner = owner; + this.builder = builder; + } + + + @Override + public void set() throws IllegalStateException { + set(builder.getDynamicScope()); + } + + @Override + public void set(Fmi2Builder.Scope scope) throws IllegalStateException { + if (!valid) { + throw new IllegalStateException(); + } + AAssigmentStm stm = newAAssignmentStm(((IMablScope) scope).getFmiStatusVariable().getDesignator().clone(), + call(owner.getReferenceExp().clone(), "setState", Collections.singletonList(this.getReferenceExp().clone()))); + scope.add(stm); + if (builder.getSettings().fmiErrorHandlingEnabled) { + InstanceVariableFmi3Api.FmiStatusErrorHandlingBuilder + .generate(builder, "setState", this.owner, (IMablScope) scope, MablApiBuilder.FmiStatus.FMI_ERROR, + MablApiBuilder.FmiStatus.FMI_FATAL); + } + } + + @Override + public void destroy() throws IllegalStateException { + destroy(builder.getDynamicScope()); + } + + @Override + public void destroy(Fmi2Builder.Scope scope) throws IllegalStateException { + if (!valid) { + throw new IllegalStateException(); + } + + AAssigmentStm stm = newAAssignmentStm(((IMablScope) scope).getFmiStatusVariable().getDesignator().clone(), + call(owner.getReferenceExp().clone(), "freeState", Collections.singletonList(this.getReferenceExp().clone()))); + scope.add(stm); + if (builder.getSettings().fmiErrorHandlingEnabled) { + InstanceVariableFmi3Api.FmiStatusErrorHandlingBuilder + .generate(builder, "freeState", this.owner, (IMablScope) scope, MablApiBuilder.FmiStatus.FMI_ERROR, + MablApiBuilder.FmiStatus.FMI_FATAL); + } + + valid = false; + } + + @Override + public void setValue(Fmi2Builder.Scope scope, Object value) { + throw new IllegalStateException(); + } + + +} diff --git a/maestro/src/test/java/org/intocps/maestro/BuilderFmi3Test.java b/maestro/src/test/java/org/intocps/maestro/BuilderFmi3Test.java index 71814e928..e5b0fd372 100644 --- a/maestro/src/test/java/org/intocps/maestro/BuilderFmi3Test.java +++ b/maestro/src/test/java/org/intocps/maestro/BuilderFmi3Test.java @@ -18,10 +18,7 @@ import org.intocps.maestro.framework.fmi2.api.mabl.MablApiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.PortFmi2Api; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.DynamicActiveBuilderScope; -import org.intocps.maestro.framework.fmi2.api.mabl.variables.ComponentVariableFmi2Api; -import org.intocps.maestro.framework.fmi2.api.mabl.variables.FmuVariableFmi2Api; -import org.intocps.maestro.framework.fmi2.api.mabl.variables.FmuVariableFmi3Api; -import org.intocps.maestro.framework.fmi2.api.mabl.variables.VariableFmi2Api; +import org.intocps.maestro.framework.fmi2.api.mabl.variables.*; import org.intocps.maestro.interpreter.DefaultExternalValueFactory; import org.intocps.maestro.interpreter.MableInterpreter; import org.intocps.maestro.typechecker.TypeChecker; @@ -80,11 +77,14 @@ public void wt() throws Exception { URI ballUri = new File("target/Fmi3ModuleReferenceFmusTest/cache/BouncingBall.fmu").getAbsoluteFile().toURI(); Fmu3 ball = new Fmu3(new File(ballUri)); + ArrayVariableFmi2Api varArray = builder.getDynamicScope().store("varArray", new Long[] {1L}); Fmi3ModelDescription md3Ball = new Fmi3ModelDescription(ball.getModelDescription()); FmuVariableFmi3Api ballFmu = builder.getDynamicScope().createFMU("ball", md3Ball, ballUri); + InstanceVariableFmi3Api ballInstance = ballFmu.instantiate("ballInstance", varArray); + // Create the two FMUs FmuVariableFmi2Api controllerFMU = builder.getDynamicScope() From 2debd670cceacd843b380818e369c42758b82650 Mon Sep 17 00:00:00 2001 From: Kenneth Lausdahl Date: Thu, 7 Sep 2023 13:28:40 +0200 Subject: [PATCH 19/54] added fmi3 support to the template generator aka import --- .../maestro/framework/core}/FaultInject.java | 2 +- .../framework/core/FrameworkUnitInfo.java | 8 + .../framework/core/RelationVariable.java | 4 +- .../maestro/framework/fmi2/ComponentInfo.java | 8 +- .../fmi2/FaultInjectWithLexName.java | 2 + .../fmi2/Fmi2SimulationEnvironment.java | 305 +++++++++++------- .../maestro/framework/fmi2/InstanceInfo.java | 39 +++ .../fmi2/MaestroV1FmuValidation.java | 15 +- .../framework/fmi2/RelationVariable.java | 14 +- .../framework/fmi2/RelationVariable3.java | 54 ++++ .../Fmi2ModelDescriptionValidatorTest.java | 2 +- .../fmi2/api/mabl/FromMaBLToMaBLAPI.java | 64 ++-- .../variables/ComponentVariableFmi2Api.java | 5 +- .../org/intocps/maestro/BuilderHelper.java | 37 ++- .../template/MaBLTemplateGenerator.java | 41 ++- .../TemplateGeneratorFromScenario.java | 22 +- .../org/intocps/maestro/BuilderFmi3Test.java | 8 +- .../java/org/intocps/maestro/BuilderTest.java | 5 +- .../org/intocps/maestro/ImportCliTest.java | 19 ++ .../test/resources/cli-test/config-fmi3.json | 22 ++ .../maestro/plugin/DataExchangeHandler.java | 13 +- .../maestro/plugin/DataWriterHandler.java | 30 +- .../intocps/maestro/plugin/StateHandler.java | 11 +- .../src/main/kotlin/Initializer.kt | 8 +- .../maestro/plugin/JacobianStepBuilder.java | 26 +- .../src/main/kotlin/MasterModelMapper.kt | 11 +- 26 files changed, 542 insertions(+), 233 deletions(-) rename frameworks/{fmi2/src/main/java/org/intocps/maestro/framework/fmi2 => core/src/main/java/org/intocps/maestro/framework/core}/FaultInject.java (78%) create mode 100644 frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/InstanceInfo.java create mode 100644 frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/RelationVariable3.java create mode 100644 maestro/src/test/resources/cli-test/config-fmi3.json diff --git a/frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/FaultInject.java b/frameworks/core/src/main/java/org/intocps/maestro/framework/core/FaultInject.java similarity index 78% rename from frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/FaultInject.java rename to frameworks/core/src/main/java/org/intocps/maestro/framework/core/FaultInject.java index 1b14e6a4d..bf37d278d 100644 --- a/frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/FaultInject.java +++ b/frameworks/core/src/main/java/org/intocps/maestro/framework/core/FaultInject.java @@ -1,4 +1,4 @@ -package org.intocps.maestro.framework.fmi2; +package org.intocps.maestro.framework.core; public class FaultInject { public String constraintId; diff --git a/frameworks/core/src/main/java/org/intocps/maestro/framework/core/FrameworkUnitInfo.java b/frameworks/core/src/main/java/org/intocps/maestro/framework/core/FrameworkUnitInfo.java index c52324c15..d72578b82 100644 --- a/frameworks/core/src/main/java/org/intocps/maestro/framework/core/FrameworkUnitInfo.java +++ b/frameworks/core/src/main/java/org/intocps/maestro/framework/core/FrameworkUnitInfo.java @@ -1,4 +1,12 @@ package org.intocps.maestro.framework.core; +import java.util.Optional; + public interface FrameworkUnitInfo { + + String getOwnerIdentifier(); + Optional getFaultInject(); + void setFaultInject(String constraintId); + + } diff --git a/frameworks/core/src/main/java/org/intocps/maestro/framework/core/RelationVariable.java b/frameworks/core/src/main/java/org/intocps/maestro/framework/core/RelationVariable.java index c7dfdfc02..a1755c759 100644 --- a/frameworks/core/src/main/java/org/intocps/maestro/framework/core/RelationVariable.java +++ b/frameworks/core/src/main/java/org/intocps/maestro/framework/core/RelationVariable.java @@ -6,5 +6,7 @@ public interface RelationVariable { LexIdentifier getInstance(); - Fmi2ModelDescription.ScalarVariable getScalarVariable(); + String getName(); + + T getScalarVariable(Class clz); } diff --git a/frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/ComponentInfo.java b/frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/ComponentInfo.java index ea40f7a72..55fb9e299 100644 --- a/frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/ComponentInfo.java +++ b/frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/ComponentInfo.java @@ -1,10 +1,9 @@ package org.intocps.maestro.framework.fmi2; import org.intocps.maestro.fmi.Fmi2ModelDescription; +import org.intocps.maestro.framework.core.FaultInject; import org.intocps.maestro.framework.core.FrameworkUnitInfo; -import java.util.List; -import java.util.Map; import java.util.Optional; public class ComponentInfo implements FrameworkUnitInfo { @@ -32,4 +31,9 @@ public Fmi2ModelDescription getModelDescription() { public String getFmuIdentifier() { return fmuIdentifier; } + + @Override + public String getOwnerIdentifier() { + return getFmuIdentifier(); + } } diff --git a/frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/FaultInjectWithLexName.java b/frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/FaultInjectWithLexName.java index 196ab178e..ae662fc54 100644 --- a/frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/FaultInjectWithLexName.java +++ b/frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/FaultInjectWithLexName.java @@ -1,5 +1,7 @@ package org.intocps.maestro.framework.fmi2; +import org.intocps.maestro.framework.core.FaultInject; + public class FaultInjectWithLexName extends FaultInject { public String lexName; diff --git a/frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/Fmi2SimulationEnvironment.java b/frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/Fmi2SimulationEnvironment.java index 33f600d35..968987edb 100644 --- a/frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/Fmi2SimulationEnvironment.java +++ b/frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/Fmi2SimulationEnvironment.java @@ -2,6 +2,7 @@ import org.antlr.v4.runtime.CharStreams; +import org.apache.commons.io.IOUtils; import org.intocps.fmi.IFmu; import org.intocps.maestro.ast.LexIdentifier; import org.intocps.maestro.ast.MableAstFactory; @@ -9,15 +10,23 @@ import org.intocps.maestro.core.dto.MultiModel; import org.intocps.maestro.core.messages.IErrorReporter; import org.intocps.maestro.fmi.Fmi2ModelDescription; +import org.intocps.maestro.fmi.ModelDescription; +import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; import org.intocps.maestro.framework.core.*; import org.intocps.maestro.parser.template.MablSwapConditionParserUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - +import org.w3c.dom.Document; +import org.xml.sax.SAXException; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpressionException; -import java.io.File; -import java.io.FileInputStream; -import java.io.InputStream; +import javax.xml.xpath.XPathFactory; +import java.io.*; import java.lang.reflect.InvocationTargetException; import java.net.URI; import java.util.*; @@ -31,15 +40,16 @@ public class Fmi2SimulationEnvironment implements ISimulationEnvironment, ISimul private final Map instanceLexToInstanceName = new HashMap<>(); private final Map> instanceNameToLogLevels = new HashMap<>(); Map> variableToRelations = new HashMap<>(); - Map instanceNameToInstanceComponentInfo = new HashMap<>(); - HashMap fmuKeyToModelDescription = new HashMap<>(); + Map instanceNameToInstanceComponentInfo = new HashMap<>(); + HashMap fmuKeyToModelDescription = new HashMap<>(); Map fmuToUri = null; Map variables = new HashMap<>(); - Map> globalVariablesToLogForInstance = new HashMap<>(); + Map> globalVariablesToLogForInstance = new HashMap<>(); Map instanceToModelTransfer = new HashMap<>(); Map instanceToModelSwap = new HashMap<>(); private String faultInjectionConfigurationPath; + protected Fmi2SimulationEnvironment(Fmi2SimulationEnvironmentConfiguration msg, ModelDescriptionResolver resolver) throws Exception { initialize(msg, resolver); } @@ -126,7 +136,7 @@ public void setLexNameToInstanceNameMapping(String lexName, String instanceName) this.instanceLexToInstanceName.put(lexName, instanceName); } - public ComponentInfo getInstanceByLexName(String lexName) { + public FrameworkUnitInfo getInstanceByLexName(String lexName) { if (!this.instanceNameToInstanceComponentInfo.containsKey(lexName)) { throw new RuntimeException("Unable to locate instance named " + lexName + " in the simulation environment."); } @@ -140,8 +150,8 @@ public ComponentInfo getInstanceByLexName(String lexName) { * @return */ @Override - public List getVariablesToLog(String instanceName) { - List vars = this.globalVariablesToLogForInstance.get(instanceName); + public List getVariablesToLog(String instanceName) { + List vars = this.globalVariablesToLogForInstance.get(instanceName); if (vars == null) { return new ArrayList<>(); } else { @@ -149,12 +159,12 @@ public List getVariablesToL } } - public Set> getFmusWithModelDescriptions() { + public Set> getFmusWithModelDescriptions() { return this.fmuKeyToModelDescription.entrySet(); } @Override - public Set> getInstances() { + public Set> getInstances() { return this.instanceNameToInstanceComponentInfo.entrySet(); } @@ -175,6 +185,31 @@ ModelSwapInfo convert(MultiModel.ModelSwap swap) throws Exception { modelSwap.swapConnections = swap.swapConnections); } + + private void addInstance(ModelConnection.Variable var, Fmi2SimulationEnvironmentConfiguration msg) throws Exception { + + if (!instanceNameToInstanceComponentInfo.containsKey(var.instance.instanceName)) { + ModelDescription md = fmuKeyToModelDescription.get(var.instance.key); + if (md instanceof Fmi2ModelDescription) { + ComponentInfo instanceComponentInfo = new ComponentInfo((Fmi2ModelDescription) md, var.instance.key); + if (msg.faultInjectInstances != null && msg.faultInjectInstances.containsKey(var.instance.instanceName)) { + instanceComponentInfo.setFaultInject(msg.faultInjectInstances.get(var.instance.instanceName)); + } + if (msg.modelSwaps != null && msg.modelSwaps.containsKey(var.instance.instanceName)) { + instanceToModelSwap.put(var.instance.instanceName, convert(msg.modelSwaps.get(var.instance.instanceName))); + } + if (msg.modelTransfers != null && msg.modelTransfers.containsKey(var.instance.instanceName)) { + instanceToModelTransfer.put(var.instance.instanceName, msg.modelTransfers.get(var.instance.instanceName)); + } + instanceNameToInstanceComponentInfo.put(var.instance.instanceName, instanceComponentInfo); + } else if (md instanceof Fmi3ModelDescription) { + instanceNameToInstanceComponentInfo.put(var.instance.instanceName, new InstanceInfo((Fmi3ModelDescription) md, var.instance.key)); + } else { + logger.warn("Cannot add instance as model description type is unknown: {}", var.instance.key); + } + } + } + private void initialize(Fmi2SimulationEnvironmentConfiguration msg, ModelDescriptionResolver resolver) throws Exception { // Remove { } around fmu name. Map fmuToURI = msg.getFmuFiles(); @@ -184,7 +219,7 @@ private void initialize(Fmi2SimulationEnvironmentConfiguration msg, ModelDescrip List connections = buildConnections(msg.getConnections()); List swapConnections = buildConnections(msg.getModelSwapConnections()); - HashMap fmuKeyToModelDescription = buildFmuKeyToFmuMD(fmuToURI, resolver); + HashMap fmuKeyToModelDescription = buildFmuKeyToFmuMD(fmuToURI, resolver); this.fmuKeyToModelDescription = fmuKeyToModelDescription; if (msg.faultInjectConfigurationPath != null && msg.faultInjectConfigurationPath.length() > 0) { @@ -200,34 +235,10 @@ private void initialize(Fmi2SimulationEnvironmentConfiguration msg, ModelDescrip for (ModelConnection instance : Stream.concat(connections.stream(), swapConnections.stream()).collect(Collectors.toList())) { instancesFromConnections.add(instance.from.instance); instancesFromConnections.add(instance.to.instance); - if (!instanceNameToInstanceComponentInfo.containsKey(instance.from.instance.instanceName)) { - ComponentInfo instanceComponentInfo = - new ComponentInfo(fmuKeyToModelDescription.get(instance.from.instance.key), instance.from.instance.key); - if (msg.faultInjectInstances != null && msg.faultInjectInstances.containsKey(instance.from.instance.instanceName)) { - instanceComponentInfo.setFaultInject(msg.faultInjectInstances.get(instance.from.instance.instanceName)); - } - if (msg.modelSwaps != null && msg.modelSwaps.containsKey(instance.from.instance.instanceName)) { - instanceToModelSwap.put(instance.from.instance.instanceName, convert(msg.modelSwaps.get(instance.from.instance.instanceName))); - } - if (msg.modelTransfers != null && msg.modelTransfers.containsKey(instance.from.instance.instanceName)) { - instanceToModelTransfer.put(instance.from.instance.instanceName, msg.modelTransfers.get(instance.from.instance.instanceName)); - } - instanceNameToInstanceComponentInfo.put(instance.from.instance.instanceName, instanceComponentInfo); - } - if (!instanceNameToInstanceComponentInfo.containsKey(instance.to.instance.instanceName)) { - ComponentInfo instanceComponentInfo = - new ComponentInfo(fmuKeyToModelDescription.get(instance.to.instance.key), instance.to.instance.key); - if (msg.faultInjectInstances != null && msg.faultInjectInstances.containsKey(instance.to.instance.instanceName)) { - instanceComponentInfo.setFaultInject(msg.faultInjectInstances.get(instance.to.instance.instanceName)); - } - if (msg.modelSwaps != null && msg.modelSwaps.containsKey(instance.to.instance.instanceName)) { - instanceToModelSwap.put(instance.to.instance.instanceName, convert(msg.modelSwaps.get(instance.to.instance.instanceName))); - } - if (msg.modelTransfers != null && msg.modelTransfers.containsKey(instance.to.instance.instanceName)) { - instanceToModelTransfer.put(instance.to.instance.instanceName, msg.modelTransfers.get(instance.to.instance.instanceName)); - } - instanceNameToInstanceComponentInfo.put(instance.to.instance.instanceName, instanceComponentInfo); - } + + addInstance(instance.from, msg); + addInstance(instance.to, msg); + } // Build relations this.variableToRelations = buildRelations(msg, connections, instancesFromConnections); @@ -250,15 +261,10 @@ private Map> buildRelations(Fmi2SimulationEnvironme Map> idToRelations = new HashMap<>(); for (ModelConnection.ModelInstance instance : instancesFromConnections) { LexIdentifier instanceLexIdentifier = new LexIdentifier(instance.instanceName, null); - // Set instanceRelations = getOrCreateRelationsForLexIdentifier(instanceLexIdentifier); - Set instanceRelations = idToRelations.computeIfAbsent(instanceLexIdentifier, key -> new HashSet<>()); - List instanceOutputScalarVariablesPorts = - instanceNameToInstanceComponentInfo.get(instance.instanceName).modelDescription.getScalarVariables().stream() - .filter(x -> x.causality == Fmi2ModelDescription.Causality.Output).collect(Collectors.toList()); // Add the instance to the globalVariablesToLogForInstance map. - List globalVariablesToLogForGivenInstance; + List globalVariablesToLogForGivenInstance; if (this.globalVariablesToLogForInstance.containsKey(instance.instanceName)) { globalVariablesToLogForGivenInstance = this.globalVariablesToLogForInstance.get(instance.instanceName); } else { @@ -266,68 +272,13 @@ private Map> buildRelations(Fmi2SimulationEnvironme } this.globalVariablesToLogForInstance.putIfAbsent(instance.instanceName, globalVariablesToLogForGivenInstance); - for (Fmi2ModelDescription.ScalarVariable outputScalarVariable : instanceOutputScalarVariablesPorts) { - Variable outputVariable = getOrCreateVariable(outputScalarVariable, instanceLexIdentifier); - - // dependantInputs are the inputs on which the current output depends on internally - Map dependantInputs = new HashMap<>(); - for (Fmi2ModelDescription.ScalarVariable inputScalarVariable : outputScalarVariable.outputDependencies.keySet()) { - if (inputScalarVariable.causality == Fmi2ModelDescription.Causality.Input) { - Variable inputVariable = getOrCreateVariable(inputScalarVariable, instanceLexIdentifier); - dependantInputs.put(instanceLexIdentifier, inputVariable); - } - // TODO: Add relation from each input to the given output? - } - if (dependantInputs.size() != 0) { - Relation r = new Relation(); - r.source = outputVariable; - r.targets = dependantInputs; - r.direction = Relation.Direction.OutputToInput; - r.origin = Relation.InternalOrExternal.Internal; - instanceRelations.add(r); - } - - // externalInputTargets are the inputs that depend on the current output based on the provided connections. - List externalInputTargets = connections.stream() - .filter(conn -> conn.from.instance.equals(instance) && conn.from.variable.equals(outputScalarVariable.name)) - .map(conn -> conn.to).collect(Collectors.toList()); - if (externalInputTargets.size() != 0) { - // Log the current output as there is an input depending on it. - globalVariablesToLogForGivenInstance.add(outputVariable.scalarVariable); - // externalInputs are all the external Inputs that depends on the current output - Map externalInputs = new HashMap<>(); - for (ModelConnection.Variable modelConnToVar : externalInputTargets) { - Fmi2ModelDescription md = instanceNameToInstanceComponentInfo.get(modelConnToVar.instance.instanceName).modelDescription; - Optional toScalarVariable = - md.getScalarVariables().stream().filter(sv -> sv.name.equals(modelConnToVar.variable)).findFirst(); - if (toScalarVariable.isPresent()) { - LexIdentifier inputInstanceLexIdentifier = new LexIdentifier(modelConnToVar.instance.instanceName, null); - Variable inputVariable = getOrCreateVariable(toScalarVariable.get(), inputInstanceLexIdentifier); - externalInputs.put(inputInstanceLexIdentifier, inputVariable); - - //Add relation from the input to the given output - Set inputInstanceRelations = idToRelations.computeIfAbsent(inputInstanceLexIdentifier, key -> new HashSet<>()); - Relation r = new Relation(); - r.source = inputVariable; - r.targets = new HashMap<>() {{ - put(instanceLexIdentifier, outputVariable); - }}; - r.origin = Relation.InternalOrExternal.External; - r.direction = Relation.Direction.InputToOutput; - inputInstanceRelations.add(r); - } else { - throw new EnvironmentException( - "Failed to find the scalar variable " + modelConnToVar.variable + " at " + modelConnToVar.instance + - " when building the dependencies tree"); - } - } + { + ModelDescription md = this.fmuKeyToModelDescription.get(instance.key); + if (md instanceof Fmi2ModelDescription) { + buildFmi2Relation((Fmi2ModelDescription) md, instance, instanceLexIdentifier, idToRelations, connections, + globalVariablesToLogForGivenInstance); + } else if (md instanceof Fmi3ModelDescription) { - Relation r = new Relation(); - r.source = outputVariable; - r.targets = externalInputs; - r.direction = Relation.Direction.OutputToInput; - r.origin = Relation.InternalOrExternal.External; - instanceRelations.add(r); } } @@ -345,19 +296,33 @@ private Map> buildRelations(Fmi2SimulationEnvironme } - List variablesToLogForInstance = new ArrayList<>(); + List variablesToLogForInstance = new ArrayList<>(); String logVariablesKey = instance.key + "." + instance.instanceName; if (globalLogVariablesMaps.containsKey(logVariablesKey)) { for (String s : globalLogVariablesMaps.get(logVariablesKey)) { - variablesToLogForInstance.add(new RelationVariable( - this.fmuKeyToModelDescription.get(instance.key).getScalarVariables().stream().filter(x -> x.name.equals(s)).findFirst() - .get(), instanceLexIdentifier)); + + ModelDescription md = this.fmuKeyToModelDescription.get(instance.key); + + org.intocps.maestro.framework.core.RelationVariable rvar = null; + if (md instanceof Fmi2ModelDescription) { + rvar = new RelationVariable( + ((Fmi2ModelDescription) md).getScalarVariables().stream().filter(x -> x.name.equals(s)).findFirst().get(), + instanceLexIdentifier); + } else if (md instanceof Fmi3ModelDescription) { + rvar = new RelationVariable3( + ((Fmi3ModelDescription) md).getScalarVariables().stream().filter(x -> x.getVariable().getName().equals(s)).findFirst() + .get(), instanceLexIdentifier); + } + + + variablesToLogForInstance.add(rvar); } if (this.globalVariablesToLogForInstance.containsKey(instance.instanceName)) { - List existingRVs = this.globalVariablesToLogForInstance.get(instance.instanceName); - for (RelationVariable rv : variablesToLogForInstance) { + List existingRVs = + this.globalVariablesToLogForInstance.get(instance.instanceName); + for (org.intocps.maestro.framework.core.RelationVariable rv : variablesToLogForInstance) { if (!existingRVs.contains(rv)) { existingRVs.add(rv); } @@ -371,12 +336,94 @@ private Map> buildRelations(Fmi2SimulationEnvironme return idToRelations; } + private void buildFmi2Relation(Fmi2ModelDescription md2, ModelConnection.ModelInstance instance, LexIdentifier instanceLexIdentifier, + Map> idToRelations, List connections, + List globalVariablesToLogForGivenInstance) throws XPathExpressionException, InvocationTargetException, IllegalAccessException, EnvironmentException { + List instanceOutputScalarVariablesPorts = + md2.getScalarVariables().stream().filter(x -> x.causality == Fmi2ModelDescription.Causality.Output).collect(Collectors.toList()); + + Set instanceRelations = idToRelations.computeIfAbsent(instanceLexIdentifier, key -> new HashSet<>()); + + for (Fmi2ModelDescription.ScalarVariable outputScalarVariable : instanceOutputScalarVariablesPorts) { + Variable outputVariable = getOrCreateVariable(outputScalarVariable, instanceLexIdentifier); + + // dependantInputs are the inputs on which the current output depends on internally + Map dependantInputs = new HashMap<>(); + for (Fmi2ModelDescription.ScalarVariable inputScalarVariable : outputScalarVariable.outputDependencies.keySet()) { + if (inputScalarVariable.causality == Fmi2ModelDescription.Causality.Input) { + Variable inputVariable = getOrCreateVariable(inputScalarVariable, instanceLexIdentifier); + dependantInputs.put(instanceLexIdentifier, inputVariable); + } + // TODO: Add relation from each input to the given output? + } + if (dependantInputs.size() != 0) { + Relation r = new Relation(); + r.source = outputVariable; + r.targets = dependantInputs; + r.direction = Relation.Direction.OutputToInput; + r.origin = Relation.InternalOrExternal.Internal; + instanceRelations.add(r); + } + + // externalInputTargets are the inputs that depend on the current output based on the provided connections. + List externalInputTargets = + connections.stream().filter(conn -> conn.from.instance.equals(instance) && conn.from.variable.equals(outputScalarVariable.name)) + .map(conn -> conn.to).collect(Collectors.toList()); + if (externalInputTargets.size() != 0) { + // Log the current output as there is an input depending on it. + globalVariablesToLogForGivenInstance.add(outputVariable.scalarVariable); + // externalInputs are all the external Inputs that depends on the current output + Map externalInputs = new HashMap<>(); + for (ModelConnection.Variable modelConnToVar : externalInputTargets) { + FrameworkUnitInfo frameworkUnitInfo = instanceNameToInstanceComponentInfo.get(modelConnToVar.instance.instanceName); + + if (frameworkUnitInfo instanceof ComponentInfo) { + + + Optional toScalarVariable = + ((ComponentInfo) frameworkUnitInfo).getModelDescription().getScalarVariables().stream() + .filter(sv -> sv.name.equals(modelConnToVar.variable)).findFirst(); + if (toScalarVariable.isPresent()) { + LexIdentifier inputInstanceLexIdentifier = new LexIdentifier(modelConnToVar.instance.instanceName, null); + Variable inputVariable = getOrCreateVariable(toScalarVariable.get(), inputInstanceLexIdentifier); + externalInputs.put(inputInstanceLexIdentifier, inputVariable); + + //Add relation from the input to the given output + Set inputInstanceRelations = idToRelations.computeIfAbsent(inputInstanceLexIdentifier, key -> new HashSet<>()); + Relation r = new Relation(); + r.source = inputVariable; + r.targets = new HashMap<>() {{ + put(instanceLexIdentifier, outputVariable); + }}; + r.origin = Relation.InternalOrExternal.External; + r.direction = Relation.Direction.InputToOutput; + inputInstanceRelations.add(r); + } else { + throw new EnvironmentException( + "Failed to find the scalar variable " + modelConnToVar.variable + " at " + modelConnToVar.instance + + " when building the dependencies tree"); + } + } else { + logger.warn("Framework unit is not a component: {}", frameworkUnitInfo.getClass().getName()); + } + } + + Relation r = new Relation(); + r.source = outputVariable; + r.targets = externalInputs; + r.direction = Relation.Direction.OutputToInput; + r.origin = Relation.InternalOrExternal.External; + instanceRelations.add(r); + } + } + } + public Map> getLogLevels() { return Collections.unmodifiableMap(this.instanceNameToLogLevels); } - private HashMap buildFmuKeyToFmuMD(Map fmus, ModelDescriptionResolver resolver) throws Exception { - HashMap fmuKeyToFmuWithMD = new HashMap<>(); + private HashMap buildFmuKeyToFmuMD(Map fmus, ModelDescriptionResolver resolver) throws Exception { + HashMap fmuKeyToFmuWithMD = new HashMap<>(); for (Map.Entry entry : fmus.entrySet()) { String key = entry.getKey(); URI value = entry.getValue(); @@ -464,7 +511,7 @@ public void check(IErrorReporter reporter) throws Exception { } } - public Fmi2ModelDescription getModelDescription(String name) { + public ModelDescription getModelDescription(String name) { return this.fmuKeyToModelDescription.get(name); } @@ -472,7 +519,7 @@ public String getFaultInjectionConfigurationPath() { return this.faultInjectionConfigurationPath; } - public interface ModelDescriptionResolver extends BiFunction { + public interface ModelDescriptionResolver extends BiFunction { } public static class Relation implements FrameworkVariableInfo, IRelation { @@ -564,11 +611,29 @@ public String toString() { } public static class FileModelDescriptionResolver implements ModelDescriptionResolver { + static XPath xPath = XPathFactory.newInstance().newXPath(); + + double getFmiVersion(InputStream is) throws ParserConfigurationException, IOException, SAXException, XPathExpressionException { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + Document doc = builder.parse(is); + doc.getDocumentElement().normalize(); + return Double.parseDouble((String) xPath.compile("fmiModelDescription/@fmiVersion").evaluate(doc, XPathConstants.STRING)); + } + @Override - public Fmi2ModelDescription apply(String s, URI uri) { + public ModelDescription apply(String s, URI uri) { try { IFmu fmu = FmuFactory.create(null, uri); - return new ExplicitModelDescription(fmu.getModelDescription()); + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + IOUtils.copy(fmu.getModelDescription(), buffer); + + double fmiVersion = getFmiVersion(new ByteArrayInputStream(buffer.toByteArray())); + if (fmiVersion < 3) { + return new ExplicitModelDescription(new ByteArrayInputStream(buffer.toByteArray())); + } else { + return new Fmi3ModelDescription(new ByteArrayInputStream(buffer.toByteArray())); + } } catch (Exception e) { throw new RuntimeException(e); } diff --git a/frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/InstanceInfo.java b/frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/InstanceInfo.java new file mode 100644 index 000000000..e2527c4b9 --- /dev/null +++ b/frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/InstanceInfo.java @@ -0,0 +1,39 @@ +package org.intocps.maestro.framework.fmi2; + +import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; +import org.intocps.maestro.framework.core.FaultInject; +import org.intocps.maestro.framework.core.FrameworkUnitInfo; + +import java.util.Optional; + +public class InstanceInfo implements FrameworkUnitInfo { + public final Fmi3ModelDescription modelDescription; + public final String fmuIdentifier; + public Optional faultInject = Optional.empty(); + + public InstanceInfo(Fmi3ModelDescription modelDescription, String fmuIdentifier) { + this.modelDescription = modelDescription; + this.fmuIdentifier = fmuIdentifier; + } + + public Optional getFaultInject() { + return this.faultInject; + } + + public void setFaultInject(String constraintId) { + this.faultInject = Optional.of(new FaultInject(constraintId)); + } + + public Fmi3ModelDescription getModelDescription() { + return modelDescription; + } + + public String getFmuIdentifier() { + return fmuIdentifier; + } + + @Override + public String getOwnerIdentifier() { + return getFmuIdentifier(); + } +} diff --git a/frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/MaestroV1FmuValidation.java b/frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/MaestroV1FmuValidation.java index 73587edc5..5e0f15560 100644 --- a/frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/MaestroV1FmuValidation.java +++ b/frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/MaestroV1FmuValidation.java @@ -1,9 +1,9 @@ package org.intocps.maestro.framework.fmi2; -import org.intocps.fmi.IFmu; import org.intocps.maestro.core.messages.IErrorReporter; -import org.intocps.maestro.modeldefinitionchecker.VdmSvChecker; import org.intocps.maestro.fmi.Fmi2ModelDescription; +import org.intocps.maestro.fmi.ModelDescription; +import org.intocps.maestro.modeldefinitionchecker.VdmSvChecker; import javax.xml.xpath.XPathExpressionException; import java.lang.reflect.InvocationTargetException; @@ -16,11 +16,14 @@ public class MaestroV1FmuValidation implements IFmuValidator { @Override public boolean validate(String id, URI path, IErrorReporter reporter) { try { - IFmu fmu = FmuFactory.create(null, path); + Fmi2SimulationEnvironment.FileModelDescriptionResolver resolver = new Fmi2SimulationEnvironment.FileModelDescriptionResolver(); + ModelDescription md = resolver.apply(null, path); - Fmi2ModelDescription md = new Fmi2ModelDescription(fmu.getModelDescription()); - validateModelDescription(md); - VdmSvChecker.validateModelVariables(md.getScalarVariables()); + if (md instanceof Fmi2ModelDescription) { + validateModelDescription((Fmi2ModelDescription) md); + VdmSvChecker.validateModelVariables(((Fmi2ModelDescription) md).getScalarVariables()); + + } return true; } catch (Exception e) { reporter.report(0, e.getMessage(), null); diff --git a/frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/RelationVariable.java b/frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/RelationVariable.java index 0b5e84efb..d5724ca14 100644 --- a/frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/RelationVariable.java +++ b/frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/RelationVariable.java @@ -23,8 +23,20 @@ public LexIdentifier getInstance() { } @Override + public String getName() { + return scalarVariable.getName(); + } + + @Override + public T getScalarVariable(Class clz) { + if (clz.isAssignableFrom(scalarVariable.getClass())) { + return clz.cast(scalarVariable); + } + return null; + } + public Fmi2ModelDescription.ScalarVariable getScalarVariable() { - return scalarVariable; + return getScalarVariable(this.scalarVariable.getClass()); } @Override diff --git a/frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/RelationVariable3.java b/frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/RelationVariable3.java new file mode 100644 index 000000000..680cfd003 --- /dev/null +++ b/frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/RelationVariable3.java @@ -0,0 +1,54 @@ +package org.intocps.maestro.framework.fmi2; + +import org.intocps.maestro.ast.LexIdentifier; +import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; + +public class RelationVariable3 implements org.intocps.maestro.framework.core.RelationVariable { + public final Fmi3ModelDescription.Fmi3ScalarVariable scalarVariable; + public final LexIdentifier instance; + + public RelationVariable3(Fmi3ModelDescription.Fmi3ScalarVariable scalarVariable, LexIdentifier instance) { + this.scalarVariable = scalarVariable; + this.instance = instance; + } + + @Override + public LexIdentifier getInstance() { + return this.instance; + } + + @Override + public String getName() { + return scalarVariable.getVariable().getName(); + } + + @Override + public T getScalarVariable(Class clz) { + if (clz.isAssignableFrom(scalarVariable.getClass())) { + return clz.cast(scalarVariable); + } + return null; + } + + public Fmi3ModelDescription.Fmi3ScalarVariable getScalarVariable() { + return getScalarVariable(this.scalarVariable.getClass()); + } + + @Override + public String toString() { + return instance + "." + scalarVariable; + } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (!(o instanceof RelationVariable)) { + return false; + } + + RelationVariable rv = (RelationVariable) o; + return rv.toString().equals(this.toString()); + } +} \ No newline at end of file diff --git a/frameworks/fmi2/src/test/java/Fmi2ModelDescriptionValidatorTest.java b/frameworks/fmi2/src/test/java/Fmi2ModelDescriptionValidatorTest.java index e2db01465..2dc4b91e0 100644 --- a/frameworks/fmi2/src/test/java/Fmi2ModelDescriptionValidatorTest.java +++ b/frameworks/fmi2/src/test/java/Fmi2ModelDescriptionValidatorTest.java @@ -23,7 +23,7 @@ public void beforeEachTestMethod() throws Exception { modelDescriptionValidator = new ModelDescriptionValidator(); var iterator = env.getFmusWithModelDescriptions().iterator(); iterator.next(); - md = iterator.next().getValue(); + md = (Fmi2ModelDescription) iterator.next().getValue(); variables = md.getScalarVariables(); } diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/FromMaBLToMaBLAPI.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/FromMaBLToMaBLAPI.java index f72141727..99b8cfa4f 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/FromMaBLToMaBLAPI.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/FromMaBLToMaBLAPI.java @@ -3,12 +3,9 @@ import org.intocps.maestro.ast.AVariableDeclaration; import org.intocps.maestro.ast.LexIdentifier; import org.intocps.maestro.ast.node.*; -import org.intocps.maestro.framework.core.IRelation; -import org.intocps.maestro.framework.core.ISimulationEnvironment; -import org.intocps.maestro.framework.core.IVariable; +import org.intocps.maestro.framework.core.*; import org.intocps.maestro.framework.fmi2.ComponentInfo; import org.intocps.maestro.framework.fmi2.Fmi2SimulationEnvironment; -import org.intocps.maestro.framework.fmi2.RelationVariable; import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; import org.intocps.maestro.framework.fmi2.api.mabl.variables.ComponentVariableFmi2Api; import org.intocps.maestro.framework.fmi2.api.mabl.variables.FmuVariableFmi2Api; @@ -40,34 +37,43 @@ public static Map.Entry getComponentVariableFr if (exp instanceof AIdentifierExp) { String componentName = ((AIdentifierExp) exp).getName().getText(); - ComponentInfo instance = env.getInstanceByLexName(environmentComponentName); - ModelDescriptionContext modelDescriptionContext = new ModelDescriptionContext(instance.modelDescription); + FrameworkUnitInfo inst = env.getInstanceByLexName(environmentComponentName); + if (inst instanceof ComponentInfo) { - //This dummy statement is removed later. It ensures that the share variables are added to the root scope. - PStm dummyStm = newABlockStm(); - builder.getDynamicScope().add(dummyStm); - FmuVariableFmi2Api fmu = new FmuVariableFmi2Api(instance.fmuIdentifier, builder, modelDescriptionContext, dummyStm, newANameType("FMI2"), - builder.getDynamicScope().getActiveScope(), builder.getDynamicScope(), null, - new AIdentifierExp(new LexIdentifier(instance.fmuIdentifier.replace("{", "").replace("}", ""), null))); + ComponentInfo instance = (ComponentInfo) inst; + ModelDescriptionContext modelDescriptionContext = new ModelDescriptionContext(instance.modelDescription); - ComponentVariableFmi2Api a; - if (environmentComponentName == null) { - a = new ComponentVariableFmi2Api(dummyStm, fmu, componentName, modelDescriptionContext, builder, - builder.getDynamicScope().getActiveScope(), null, newAIdentifierExp(componentName)); - } else { - a = new ComponentVariableFmi2Api(dummyStm, fmu, componentName, modelDescriptionContext, builder, - builder.getDynamicScope().getActiveScope(), null, newAIdentifierExp(componentName), environmentComponentName); - } - List variablesToLog = null; - if (environmentComponentName == null) { - variablesToLog = env.getVariablesToLog(componentName); + //This dummy statement is removed later. It ensures that the share variables are added to the root scope. + PStm dummyStm = newABlockStm(); + builder.getDynamicScope().add(dummyStm); + + FmuVariableFmi2Api fmu = + new FmuVariableFmi2Api(instance.fmuIdentifier, builder, modelDescriptionContext, dummyStm, newANameType("FMI2"), + builder.getDynamicScope().getActiveScope(), builder.getDynamicScope(), null, + new AIdentifierExp(new LexIdentifier(instance.fmuIdentifier.replace("{", "").replace("}", ""), null))); + + ComponentVariableFmi2Api a; + if (environmentComponentName == null) { + a = new ComponentVariableFmi2Api(dummyStm, fmu, componentName, modelDescriptionContext, builder, + builder.getDynamicScope().getActiveScope(), null, newAIdentifierExp(componentName)); + } else { + a = new ComponentVariableFmi2Api(dummyStm, fmu, componentName, modelDescriptionContext, builder, + builder.getDynamicScope().getActiveScope(), null, newAIdentifierExp(componentName), environmentComponentName); + } + List variablesToLog = null; + if (environmentComponentName == null) { + variablesToLog = env.getVariablesToLog(componentName); + } else { + variablesToLog = env.getVariablesToLog(environmentComponentName); + } + a.setVariablesToLog(variablesToLog.stream().filter(org.intocps.maestro.framework.fmi2.RelationVariable.class::isInstance) + .map(org.intocps.maestro.framework.fmi2.RelationVariable.class::cast).collect(Collectors.toList())); + + return Map.entry(componentName, a); } else { - variablesToLog = env.getVariablesToLog(environmentComponentName); + throw new RuntimeException("instance is not an fmi2 component: " + componentName); } - a.setVariablesToLog(variablesToLog); - - return Map.entry(componentName, a); } else { throw new RuntimeException("exp is not of type AIdentifierExp, but of type: " + exp.getClass()); } @@ -93,9 +99,9 @@ public static void createBindings(Map instance } } - PortFmi2Api targetPort = instance.getPort(targetVar.getScalarVariable().getScalarVariable().getName()); + PortFmi2Api targetPort = instance.getPort(targetVar.getScalarVariable().getName()); - String sourcePortName = relation.getSource().getScalarVariable().getScalarVariable().getName(); + String sourcePortName = relation.getSource().getScalarVariable().getName(); if (targetPort != null) { entry.getValue().getPort(sourcePortName).linkTo(targetPort); } else { diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/ComponentVariableFmi2Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/ComponentVariableFmi2Api.java index 87acf0fef..05c6929d2 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/ComponentVariableFmi2Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/ComponentVariableFmi2Api.java @@ -7,7 +7,8 @@ import org.intocps.maestro.ast.analysis.DepthFirstAnalysisAdaptor; import org.intocps.maestro.ast.node.*; import org.intocps.maestro.fmi.Fmi2ModelDescription; -import org.intocps.maestro.framework.fmi2.RelationVariable; + +import org.intocps.maestro.framework.core.RelationVariable; import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; import org.intocps.maestro.framework.fmi2.api.mabl.*; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.IMablScope; @@ -99,7 +100,7 @@ public List getVariablesToLog() { } public void setVariablesToLog(List variablesToLog) { - this.variabesToLog = variablesToLog.stream().map(x -> x.scalarVariable.getName()).collect(Collectors.toList()); + this.variabesToLog = variablesToLog.stream().map(RelationVariable::getName).collect(Collectors.toList()); } @Override diff --git a/maestro/src/main/java/org/intocps/maestro/BuilderHelper.java b/maestro/src/main/java/org/intocps/maestro/BuilderHelper.java index 21d643b10..e712c64b1 100644 --- a/maestro/src/main/java/org/intocps/maestro/BuilderHelper.java +++ b/maestro/src/main/java/org/intocps/maestro/BuilderHelper.java @@ -5,6 +5,7 @@ import org.intocps.maestro.ast.analysis.AnalysisException; import org.intocps.maestro.ast.analysis.DepthFirstAnalysisAdaptorQuestion; import org.intocps.maestro.ast.node.*; +import org.intocps.maestro.framework.core.FrameworkUnitInfo; import org.intocps.maestro.framework.core.ISimulationEnvironment; import org.intocps.maestro.framework.fmi2.ComponentInfo; import org.intocps.maestro.framework.fmi2.Fmi2SimulationEnvironment; @@ -113,23 +114,27 @@ public void caseAInstanceMappingStm(AInstanceMappingStm node, if (exp instanceof AIdentifierExp) { String componentName = ((AIdentifierExp) exp).getName().getText(); - ComponentInfo instance = env.getInstanceByLexName(componentName); - ModelDescriptionContext modelDescriptionContext = null; - try { - modelDescriptionContext = new ModelDescriptionContext(instance.modelDescription); - } catch (IllegalAccessException | XPathExpressionException | InvocationTargetException e) { - throw new RuntimeException(e); - } - - //This dummy statement is removed later. It ensures that the share variables are added to the root scope. - PStm dummyStm = newABlockStm(); - builder.getDynamicScope().add(dummyStm); + FrameworkUnitInfo instance = env.getInstanceByLexName(componentName); + if (instance instanceof ComponentInfo) { + ModelDescriptionContext modelDescriptionContext = null; + try { + modelDescriptionContext = new ModelDescriptionContext(((ComponentInfo) instance).modelDescription); + } catch (IllegalAccessException | XPathExpressionException | InvocationTargetException e) { + throw new RuntimeException(e); + } + + //This dummy statement is removed later. It ensures that the share variables are added to the root scope. + PStm dummyStm = newABlockStm(); + builder.getDynamicScope().add(dummyStm); + + FmuVariableFmi2Api fmu = + new FmuVariableFmi2Api(instance.getOwnerIdentifier(), builder, modelDescriptionContext, dummyStm, newANameType("FMI2"), + builder.getDynamicScope().getActiveScope(), builder.getDynamicScope(), null, + new AIdentifierExp(new LexIdentifier(instance.getOwnerIdentifier().replace("{", "").replace("}", ""), null))); + return fmu; - FmuVariableFmi2Api fmu = - new FmuVariableFmi2Api(instance.fmuIdentifier, builder, modelDescriptionContext, dummyStm, newANameType("FMI2"), - builder.getDynamicScope().getActiveScope(), builder.getDynamicScope(), null, - new AIdentifierExp(new LexIdentifier(instance.fmuIdentifier.replace("{", "").replace("}", ""), null))); - return fmu; + } + throw new RuntimeException("exp is not identifying as a component: " + instance); } else { throw new RuntimeException("exp is not of type AIdentifierExp, but of type: " + exp.getClass()); } diff --git a/maestro/src/main/java/org/intocps/maestro/template/MaBLTemplateGenerator.java b/maestro/src/main/java/org/intocps/maestro/template/MaBLTemplateGenerator.java index 165cccd2e..4fe681674 100644 --- a/maestro/src/main/java/org/intocps/maestro/template/MaBLTemplateGenerator.java +++ b/maestro/src/main/java/org/intocps/maestro/template/MaBLTemplateGenerator.java @@ -10,8 +10,10 @@ import org.intocps.maestro.ast.node.*; import org.intocps.maestro.core.dto.IAlgorithmConfig; import org.intocps.maestro.fmi.Fmi2ModelDescription; +import org.intocps.maestro.fmi.ModelDescription; +import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; +import org.intocps.maestro.framework.core.FrameworkUnitInfo; import org.intocps.maestro.framework.core.IRelation; -import org.intocps.maestro.framework.fmi2.ComponentInfo; import org.intocps.maestro.framework.fmi2.FaultInjectWithLexName; import org.intocps.maestro.framework.fmi2.Fmi2SimulationEnvironment; import org.intocps.maestro.plugin.IMaestroPlugin; @@ -40,6 +42,7 @@ public class MaBLTemplateGenerator { public static final String LOGGER_MODULE_NAME = "Logger"; public static final String DATAWRITER_MODULE_NAME = "DataWriter"; public static final String FMI2_MODULE_NAME = "FMI2"; + public static final String FMI3_MODULE_NAME = "FMI3"; public static final String TYPECONVERTER_MODULE_NAME = "TypeConverter"; public static final String INITIALIZE_EXPANSION_FUNCTION_NAME = "initialize"; public static final String INITIALIZE_TRANSFER_EXPANSION_FUNCTION_NAME = "initialize_transfer"; @@ -102,12 +105,23 @@ public static List createFmuVariable(String fmuLexName, String fmuKey) { } - public static PStm createFMULoad(String fmuLexName, Map.Entry entry, + public static PStm createFMULoad(String fmuLexName, Map.Entry entry, URI uriFromFMUName) throws XPathExpressionException { - String path = uriFromFMUName.toString(); - return newAAssignmentStm(newAIdentifierStateDesignator(newAIdentifier(fmuLexName)), - call("load", newAStringLiteralExp("FMI2"), newAStringLiteralExp(entry.getValue().getGuid()), newAStringLiteralExp(path))); + ModelDescription md = entry.getValue(); + + if (md instanceof Fmi2ModelDescription) { + String path = uriFromFMUName.toString(); + return newAAssignmentStm(newAIdentifierStateDesignator(newAIdentifier(fmuLexName)), + call("load", newAStringLiteralExp("FMI2"), newAStringLiteralExp(((Fmi2ModelDescription) md).getGuid()), + newAStringLiteralExp(path))); + } else if (md instanceof Fmi3ModelDescription) { + String path = uriFromFMUName.toString(); + return newAAssignmentStm(newAIdentifierStateDesignator(newAIdentifier(fmuLexName)), + call("load", newAStringLiteralExp("FMI3"), newAStringLiteralExp(((Fmi3ModelDescription) md).getInstantiationToken()), + newAStringLiteralExp(path))); + } + return null; } @@ -224,7 +238,7 @@ public static ASimulationSpecificationCompilationUnit generateTemplate( // First create the FMU variables and assign to null HashMap fmuNameToLexIdentifier = new HashMap<>(); NameMapper.NameMapperState nameMapperState = new NameMapper.NameMapperState(); - for (Map.Entry entry : unitRelationShip.getFmusWithModelDescriptions()) { + for (Map.Entry entry : unitRelationShip.getFmusWithModelDescriptions()) { String fmuLexName = removeFmuKeyBraces(entry.getKey()); fmuLexName = NameMapper.makeSafeFMULexName(fmuLexName, nameMapperState); rootScopeBody.addAll(createFmuVariable(fmuLexName, entry.getKey())); @@ -256,8 +270,8 @@ public static ASimulationSpecificationCompilationUnit generateTemplate( Set instanceTransfers = new HashSet<>(); for (Map.Entry entry : unitRelationShip.getModelTransfers()) { - ComponentInfo inst = unitRelationShip.getInstanceByLexName(entry.getKey()); - String fmuLexName = removeFmuKeyBraces(inst.fmuIdentifier); + FrameworkUnitInfo inst = unitRelationShip.getInstanceByLexName(entry.getKey()); + String fmuLexName = removeFmuKeyBraces(inst.getOwnerIdentifier()); fmuTransfers.add(fmuLexName); String instanceLexName = instaceNameToInstanceLex.get(entry.getKey()); @@ -267,7 +281,7 @@ public static ASimulationSpecificationCompilationUnit generateTemplate( // Create FMU load statements for FMUs not transferred List unloadFmuStatements = new ArrayList<>(); - for (Map.Entry entry : unitRelationShip.getFmusWithModelDescriptions()) { + for (Map.Entry entry : unitRelationShip.getFmusWithModelDescriptions()) { String fmuLexName = fmuNameToLexIdentifier.get((entry.getKey())); // If FMU already transferred skip this iteration @@ -287,7 +301,7 @@ public static ASimulationSpecificationCompilationUnit generateTemplate( Map faultInjectedInstances = new HashMap<>(); unitRelationShip.getInstances().forEach(entry -> { // Find parent lex - String parentLex = fmuNameToLexIdentifier.get(entry.getValue().fmuIdentifier); + String parentLex = fmuNameToLexIdentifier.get(entry.getValue().getOwnerIdentifier()); // Get instanceName String instanceLexName = instaceNameToInstanceLex.get(entry.getKey()); @@ -401,8 +415,9 @@ public static ASimulationSpecificationCompilationUnit generateTemplate( List imports = new ArrayList<>( Arrays.asList(newAIdentifier(JACOBIANSTEP_EXPANSION_MODULE_NAME), newAIdentifier(INITIALIZE_EXPANSION_MODULE_NAME), newAIdentifier(DEBUG_LOGGING_MODULE_NAME), newAIdentifier(TYPECONVERTER_MODULE_NAME), newAIdentifier(DATAWRITER_MODULE_NAME), - newAIdentifier(FMI2_MODULE_NAME), newAIdentifier(MATH_MODULE_NAME), newAIdentifier(ARRAYUTIL_EXPANSION_MODULE_NAME), - newAIdentifier(LOGGER_MODULE_NAME), newAIdentifier(BOOLEANLOGIC_MODULE_NAME), newAIdentifier("MEnv"))); + newAIdentifier(FMI2_MODULE_NAME), newAIdentifier(FMI3_MODULE_NAME), newAIdentifier(MATH_MODULE_NAME), + newAIdentifier(ARRAYUTIL_EXPANSION_MODULE_NAME), newAIdentifier(LOGGER_MODULE_NAME), newAIdentifier(BOOLEANLOGIC_MODULE_NAME), + newAIdentifier("MEnv"))); if (faultInject) { imports.add(newAIdentifier(FAULT_INJECT_MODULE_NAME)); } @@ -423,7 +438,7 @@ public static ASimulationSpecificationCompilationUnit generateTemplate( private static void checkConnectionUnits(Fmi2SimulationEnvironment unitRelationShip) { StringBuilder sbUnitError = new StringBuilder(); //check scalar variable unit compatibility - for (Map.Entry instance : unitRelationShip.getInstances()) { + for (Map.Entry instance : unitRelationShip.getInstances()) { for (Fmi2SimulationEnvironment.Relation relation : unitRelationShip.getRelations(instance.getKey())) { if (relation.getOrigin() == IRelation.InternalOrExternal.External && relation.getDirection() == IRelation.Direction.OutputToInput) { for (Map.Entry target : relation.getTargets().entrySet()) { diff --git a/maestro/src/main/java/org/intocps/maestro/template/TemplateGeneratorFromScenario.java b/maestro/src/main/java/org/intocps/maestro/template/TemplateGeneratorFromScenario.java index a1c8903ba..dedf34590 100644 --- a/maestro/src/main/java/org/intocps/maestro/template/TemplateGeneratorFromScenario.java +++ b/maestro/src/main/java/org/intocps/maestro/template/TemplateGeneratorFromScenario.java @@ -7,7 +7,9 @@ import org.intocps.maestro.ast.MableAstFactory; import org.intocps.maestro.ast.display.PrettyPrinter; import org.intocps.maestro.ast.node.*; -import org.intocps.maestro.framework.fmi2.ComponentInfo; +import org.intocps.maestro.fmi.Fmi2ModelDescription; +import org.intocps.maestro.fmi.ModelDescription; +import org.intocps.maestro.framework.core.FrameworkUnitInfo; import org.intocps.maestro.framework.fmi2.Fmi2SimulationEnvironment; import org.intocps.maestro.framework.fmi2.api.mabl.FaultInject; import org.intocps.maestro.framework.fmi2.api.mabl.MablApiBuilder; @@ -20,6 +22,7 @@ import scala.jdk.javaapi.CollectionConverters; import synthesizer.ConfParser.ScenarioConfGenerator; +import java.net.URI; import java.util.*; import java.util.stream.Collectors; @@ -58,8 +61,13 @@ public static ASimulationSpecificationCompilationUnit generateTemplate(ScenarioC List fmus = simulationEnvironment.getFmusWithModelDescriptions().stream() .filter(entry -> simulationEnvironment.getUriFromFMUName(entry.getKey()) != null).map(entry -> { try { - return dynamicScope.createFMU(removeFmuKeyBraces(entry.getKey()), entry.getValue(), - simulationEnvironment.getUriFromFMUName(entry.getKey())); + String name = removeFmuKeyBraces(entry.getKey()); + ModelDescription md = entry.getValue(); + URI uri = simulationEnvironment.getUriFromFMUName(entry.getKey()); + if (md instanceof Fmi2ModelDescription) { + return dynamicScope.createFMU(name, (Fmi2ModelDescription) md, uri); + } + throw new RuntimeException("Only supporting FMI2 got: " + md.getFmiVersion()); } catch (Exception e) { throw new RuntimeException("Unable to create FMU variable: " + e); } @@ -87,7 +95,7 @@ public static ASimulationSpecificationCompilationUnit generateTemplate(ScenarioC // We need to use the fault inject fmu instead of the original. fmuInstances = originalFmuInstances.entrySet().stream().map(entry -> { String instanceNameInEnvironment = entry.getKey().split(Sigver.MASTER_MODEL_FMU_INSTANCE_DELIMITER)[1]; - Optional> simEnvInstance = + Optional> simEnvInstance = simulationEnvironment.getInstances().stream().filter(ins -> Objects.equals(ins.getKey(), instanceNameInEnvironment)) .findFirst(); if (simEnvInstance.isPresent() && simEnvInstance.get().getValue().getFaultInject().isPresent()) { @@ -145,7 +153,11 @@ public static ASimulationSpecificationCompilationUnit generateTemplate(ScenarioC if (doFaultInject) { originalFmuInstances.putAll(faultInjectInstances); } - originalFmuInstances.values().forEach(ComponentVariableFmi2Api::terminate); + originalFmuInstances.values().stream().filter(ComponentVariableFmi2Api.class::isInstance).map(ComponentVariableFmi2Api.class::cast) + .forEach(ComponentVariableFmi2Api::terminate); + //TODO: add terminal for fmi3 + // originalFmuInstances.values().stream().filter(InstanceVApi.class::isInstance).map(ComponentVariableFmi2Api.class::cast + // ).forEach(ComponentVariableFmi2Api::terminate); // Build unit ASimulationSpecificationCompilationUnit unit = builder.build(); diff --git a/maestro/src/test/java/org/intocps/maestro/BuilderFmi3Test.java b/maestro/src/test/java/org/intocps/maestro/BuilderFmi3Test.java index 562337156..5b5d9bc1a 100644 --- a/maestro/src/test/java/org/intocps/maestro/BuilderFmi3Test.java +++ b/maestro/src/test/java/org/intocps/maestro/BuilderFmi3Test.java @@ -9,6 +9,7 @@ import org.intocps.maestro.core.Framework; import org.intocps.maestro.core.messages.ErrorReporter; import org.intocps.maestro.core.messages.IErrorReporter; +import org.intocps.maestro.fmi.Fmi2ModelDescription; import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; import org.intocps.maestro.fmi3.Fmi3ModuleReferenceFmusTest; import org.intocps.maestro.framework.fmi2.Fmi2SimulationEnvironment; @@ -86,9 +87,10 @@ public void wt() throws Exception { // Create the two FMUs FmuVariableFmi2Api controllerFMU = builder.getDynamicScope() - .createFMU("controllerFMU", env.getModelDescription("{controllerFMU}"), env.getUriFromFMUName("{controllerFMU}")); - FmuVariableFmi2Api tankFMU = - builder.getDynamicScope().createFMU("tankFMU", env.getModelDescription("{tankFMU}"), env.getUriFromFMUName("{tankFMU}")); + .createFMU("controllerFMU", (Fmi2ModelDescription) env.getModelDescription("{controllerFMU}"), + env.getUriFromFMUName("{controllerFMU" + "}")); + FmuVariableFmi2Api tankFMU = builder.getDynamicScope() + .createFMU("tankFMU", (Fmi2ModelDescription) env.getModelDescription("{tankFMU}"), env.getUriFromFMUName("{tankFMU}")); // Create the controller and tank instanes ComponentVariableFmi2Api controller = controllerFMU.instantiate("controller"); diff --git a/maestro/src/test/java/org/intocps/maestro/BuilderTest.java b/maestro/src/test/java/org/intocps/maestro/BuilderTest.java index 1685e145a..f4861fdb3 100644 --- a/maestro/src/test/java/org/intocps/maestro/BuilderTest.java +++ b/maestro/src/test/java/org/intocps/maestro/BuilderTest.java @@ -8,6 +8,7 @@ import org.intocps.maestro.core.Framework; import org.intocps.maestro.core.messages.ErrorReporter; import org.intocps.maestro.core.messages.IErrorReporter; +import org.intocps.maestro.fmi.Fmi2ModelDescription; import org.intocps.maestro.framework.fmi2.Fmi2SimulationEnvironment; import org.intocps.maestro.framework.fmi2.Fmi2SimulationEnvironmentConfiguration; import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; @@ -66,9 +67,9 @@ public void wt() throws Exception { // Create the two FMUs FmuVariableFmi2Api controllerFMU = builder.getDynamicScope() - .createFMU("controllerFMU", env.getModelDescription("{controllerFMU}"), env.getUriFromFMUName("{controllerFMU}")); + .createFMU("controllerFMU",(Fmi2ModelDescription) env.getModelDescription("{controllerFMU}"), env.getUriFromFMUName("{controllerFMU}")); FmuVariableFmi2Api tankFMU = builder.getDynamicScope() - .createFMU("tankFMU", env.getModelDescription("{tankFMU}"), env.getUriFromFMUName("{tankFMU}")); + .createFMU("tankFMU", (Fmi2ModelDescription)env.getModelDescription("{tankFMU}"), env.getUriFromFMUName("{tankFMU}")); // Create the controller and tank instanes ComponentVariableFmi2Api controller = controllerFMU.instantiate("controller"); diff --git a/maestro/src/test/java/org/intocps/maestro/ImportCliTest.java b/maestro/src/test/java/org/intocps/maestro/ImportCliTest.java index 5e0add1f6..38d500b1e 100644 --- a/maestro/src/test/java/org/intocps/maestro/ImportCliTest.java +++ b/maestro/src/test/java/org/intocps/maestro/ImportCliTest.java @@ -1,8 +1,10 @@ package org.intocps.maestro; import org.apache.commons.io.FileUtils; +import org.intocps.maestro.fmi3.Fmi3ModuleReferenceFmusTest; import org.junit.Assert; import org.junit.Test; +import org.junit.jupiter.api.BeforeAll; import picocli.CommandLine; import java.io.File; @@ -13,6 +15,12 @@ public class ImportCliTest { + @BeforeAll + public static void downloadFmus() throws IOException { + Fmi3ModuleReferenceFmusTest.downloadReferenceFmus(); + + } + final static File resourcesConfigPrefix = Paths.get("src", "test", "resources", "cli-test").toFile(); File simulationConfigPath = new File(resourcesConfigPrefix, "simulation-config.json"); @@ -35,6 +43,17 @@ public void importTestRelativeExistingFmus() { } + @Test + public void importTestExistingFmu3Mix() { + + String arguments = String.format(Locale.US, "import sg1 --inline-framework-config -output %s %s %s", getOutputPath().toAbsolutePath(), + simulationConfigPath.getAbsolutePath(), new File(resourcesConfigPrefix, "config-fmi3.json").toPath()); + String[] s = arguments.split(" "); + + int exitCode = new CommandLine(new Main()).setCaseInsensitiveEnumValuesAllowed(true).execute(s); + Assert.assertEquals(0, exitCode); + + } // @Test // public void importTestRelativeFmus() { diff --git a/maestro/src/test/resources/cli-test/config-fmi3.json b/maestro/src/test/resources/cli-test/config-fmi3.json new file mode 100644 index 000000000..594755e72 --- /dev/null +++ b/maestro/src/test/resources/cli-test/config-fmi3.json @@ -0,0 +1,22 @@ +{ + "fmus": { + "{x1}": "target/Fmi3ModuleReferenceFmusTest/cache/BouncingBall.fmu", + "{x2}": "src/test/resources/singlewatertank-20sim.fmu" + }, + "connections": { + "{x1}.controller.valve": [ + "{x2}.tank.valvecontrol" + ], + "{x2}.tank.level": [ + "{x1}.controller.level" + ] + }, + "parameters": { + "{x1}.controller.maxLevel": 2, + "{x1}.controller.minLevel": 4 + }, + "algorithm": { + "type": "fixed-step", + "size": 0.1 + } +} \ No newline at end of file diff --git a/plugins/fixedstep/src/main/java/org/intocps/maestro/plugin/DataExchangeHandler.java b/plugins/fixedstep/src/main/java/org/intocps/maestro/plugin/DataExchangeHandler.java index f56253463..73141d9c7 100644 --- a/plugins/fixedstep/src/main/java/org/intocps/maestro/plugin/DataExchangeHandler.java +++ b/plugins/fixedstep/src/main/java/org/intocps/maestro/plugin/DataExchangeHandler.java @@ -2,9 +2,9 @@ import org.intocps.maestro.ast.LexIdentifier; import org.intocps.maestro.ast.node.*; +import org.intocps.maestro.fmi.Fmi2ModelDescription; import org.intocps.maestro.framework.fmi2.Fmi2SimulationEnvironment; import org.intocps.maestro.framework.fmi2.RelationVariable; -import org.intocps.maestro.fmi.Fmi2ModelDescription; import java.util.*; import java.util.function.BiConsumer; @@ -32,10 +32,12 @@ public DataExchangeHandler(Set relations, Fm .collect(Collectors.toSet()); // outputs contains both outputs based on relations and outputs based on additional variables to log - outputs = outputRelations.stream().map(r -> r.getSource().scalarVariable.instance).distinct().collect(Collectors - .toMap(Function.identity(), s -> outputRelations.stream().filter(r -> r.getSource().scalarVariable.instance.equals(s)).flatMap(r -> { + //FIXME fmi3 is excluded + outputs = outputRelations.stream().map(r -> r.getSource().scalarVariable.instance).distinct().collect(Collectors.toMap(Function.identity(), + s -> outputRelations.stream().filter(r -> r.getSource().scalarVariable.instance.equals(s)).flatMap(r -> { List outputs_ = - env.getVariablesToLog(s.getText()).stream().map(x -> x.scalarVariable).collect(Collectors.toList()); + env.getVariablesToLog(s.getText()).stream().map(x -> x.getScalarVariable(Fmi2ModelDescription.ScalarVariable.class)) + .filter(Objects::nonNull).collect(Collectors.toList()); //outputs_.add(r.getSource().scalarVariable.getScalarVariable()); return outputs_.stream(); }).distinct().collect(Collectors.groupingBy(sv -> sv.getType().type)))); @@ -200,7 +202,8 @@ public List exchangeData() { RelationVariable fromVar = r.getTargets().values().iterator().next().scalarVariable; PExp from = newAArrayIndexExp(newAIdentifierExp(getBufferName(fromVar.instance, fromVar.getScalarVariable().type.type, UsageType.Out)), Collections.singletonList(newAIntLiteralExp(outputs.get(fromVar.instance).get(fromVar.getScalarVariable().getType().type).stream() - .map(Fmi2ModelDescription.ScalarVariable::getName).collect(Collectors.toList()).indexOf(fromVar.scalarVariable.getName())))); + .map(Fmi2ModelDescription.ScalarVariable::getName).collect(Collectors.toList()) + .indexOf(fromVar.scalarVariable.getName())))); if (r.getSource().scalarVariable.getScalarVariable().getType().type != fromVar.getScalarVariable().getType().type) { //ok the types are not matching, lets use a converter diff --git a/plugins/fixedstep/src/main/java/org/intocps/maestro/plugin/DataWriterHandler.java b/plugins/fixedstep/src/main/java/org/intocps/maestro/plugin/DataWriterHandler.java index beae51633..796c7bebd 100644 --- a/plugins/fixedstep/src/main/java/org/intocps/maestro/plugin/DataWriterHandler.java +++ b/plugins/fixedstep/src/main/java/org/intocps/maestro/plugin/DataWriterHandler.java @@ -5,11 +5,11 @@ import org.intocps.maestro.ast.node.PExp; import org.intocps.maestro.ast.node.PStm; import org.intocps.maestro.core.Framework; +import org.intocps.maestro.fmi.Fmi2ModelDescription; import org.intocps.maestro.framework.core.FrameworkUnitInfo; import org.intocps.maestro.framework.fmi2.ComponentInfo; import org.intocps.maestro.framework.fmi2.Fmi2SimulationEnvironment; import org.intocps.maestro.framework.fmi2.RelationVariable; -import org.intocps.maestro.fmi.Fmi2ModelDescription; import java.util.*; import java.util.function.Consumer; @@ -27,18 +27,18 @@ public class DataWriterHandler implements GeneratorComponent { private final String dataWriter = "dataWriter"; private final String data_valuesIdentifier = "data_values"; private final String data_configuration = "dataWriter_configuration"; - Map csvFields; + Map csvFields; public List allocate(Set inputRelations, Map>> outputs, Fmi2SimulationEnvironment env) { List statements = new Vector<>(); List variableNames = new Vector<>(); - Function getLogName = k -> k.instance.getText() + "." + k.getScalarVariable().getName(); + Function getLogName = k -> k.getInstance().getText() + "." + k.getName(); csvFields = inputRelations.stream().map(r -> r.getTargets().values().stream().findFirst()).filter(Optional::isPresent).map(Optional::get) .flatMap(h -> { - List outputs_ = env.getVariablesToLog(h.scalarVariable.instance.getText()); + List outputs_ = env.getVariablesToLog(h.scalarVariable.instance.getText()); //outputs_.add(h.scalarVariable); return outputs_.stream(); //return h.scalarVariable; @@ -46,20 +46,26 @@ public List allocate(Set inputRelation //the relation should be a one to one relation so just take the first one - RelationVariable fromVar = r; - PExp from = arrayGet(getBufferName(fromVar.instance, fromVar.getScalarVariable().type.type, DataExchangeHandler.UsageType.Out), - outputs.get(fromVar.instance).get(fromVar.getScalarVariable().getType().type).stream() - .map(Fmi2ModelDescription.ScalarVariable::getName).collect(Collectors.toList()) - .indexOf(fromVar.scalarVariable.getName())); - return from; + org.intocps.maestro.framework.core.RelationVariable fromVar = r; + + if (fromVar instanceof RelationVariable) { + Fmi2ModelDescription.Types fromType = ((RelationVariable) fromVar).getScalarVariable().type.type; + PExp from = arrayGet(getBufferName(fromVar.getInstance(), fromType, DataExchangeHandler.UsageType.Out), + outputs.get(fromVar.getInstance()).get(fromType).stream().map(Fmi2ModelDescription.ScalarVariable::getName) + .collect(Collectors.toList()).indexOf(fromVar.getName())); + return from; + } else { + throw new RuntimeException("Not a fmi 2 variable"); + } + }, (oldValue, newValue) -> oldValue, LinkedHashMap::new)); variableNames.addAll(csvFields.keySet().stream().map(k -> { - FrameworkUnitInfo info = env.getUnitInfo(k.instance, Framework.FMI2); + FrameworkUnitInfo info = env.getUnitInfo(k.getInstance(), Framework.FMI2); - Stream nameComponents = Stream.of(k.instance.getText(), k.getScalarVariable().getName()); + Stream nameComponents = Stream.of(k.getInstance().getText(), k.getName()); if (info instanceof ComponentInfo) { nameComponents = Stream.concat(Stream.of(((ComponentInfo) info).fmuIdentifier), nameComponents); diff --git a/plugins/fixedstep/src/main/java/org/intocps/maestro/plugin/StateHandler.java b/plugins/fixedstep/src/main/java/org/intocps/maestro/plugin/StateHandler.java index 3f3e1044f..49ea7b2de 100644 --- a/plugins/fixedstep/src/main/java/org/intocps/maestro/plugin/StateHandler.java +++ b/plugins/fixedstep/src/main/java/org/intocps/maestro/plugin/StateHandler.java @@ -6,7 +6,9 @@ import org.intocps.maestro.ast.node.PExp; import org.intocps.maestro.ast.node.PStateDesignator; import org.intocps.maestro.ast.node.PStm; +import org.intocps.maestro.framework.fmi2.ComponentInfo; import org.intocps.maestro.framework.fmi2.Fmi2SimulationEnvironment; +import org.intocps.maestro.framework.fmi2.InstanceInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -40,7 +42,14 @@ public StateHandler(List componentNames, Fmi2SimulationEnvironmen supportsGetSetState = env.getInstances().stream().filter(f -> componentNames.stream().anyMatch(m -> m.getText().equals(f.getKey()))).allMatch(pair -> { try { - return pair.getValue().modelDescription.getCanGetAndSetFmustate(); + if (pair.getValue() instanceof ComponentInfo) { + return ((ComponentInfo) pair.getValue()).modelDescription.getCanGetAndSetFmustate(); + } else if (pair.getValue() instanceof InstanceInfo) { + return ((InstanceInfo) pair.getValue()).modelDescription.getCanGetAndSetFmustate(); + } + return false; + + } catch (XPathExpressionException e) { e.printStackTrace(); return false; diff --git a/plugins/initializer/src/main/kotlin/Initializer.kt b/plugins/initializer/src/main/kotlin/Initializer.kt index 06ed4f8c9..3a2e548f2 100644 --- a/plugins/initializer/src/main/kotlin/Initializer.kt +++ b/plugins/initializer/src/main/kotlin/Initializer.kt @@ -498,6 +498,7 @@ class Initializer : BasicMaestroExpansionPlugin { val b: Double = staticValue as Double comp.set(port, DoubleExpressionValue.of(b)) } + Fmi2ModelDescription.Types.Integer -> comp.set(port, IntExpressionValue.of(staticValue as Int)) Fmi2ModelDescription.Types.String -> comp.set(port, StringExpressionValue.of(staticValue as String)) Fmi2ModelDescription.Types.Enumeration -> throw ExpandException("Enumeration not supported") @@ -509,18 +510,22 @@ class Initializer : BasicMaestroExpansionPlugin { val v = builder.executionEnvironment.getBool(port.multiModelScalarVariableName) comp.set(port, v) } + Fmi2ModelDescription.Types.Real -> { val v = builder.executionEnvironment.getReal(port.multiModelScalarVariableName) comp.set(port, v) } + Fmi2ModelDescription.Types.Integer -> { val v = builder.executionEnvironment.getInt(port.multiModelScalarVariableName) comp.set(port, v) } + Fmi2ModelDescription.Types.String -> { val v = builder.executionEnvironment.getString(port.multiModelScalarVariableName) comp.set(port, v) } + Fmi2ModelDescription.Types.Enumeration -> throw ExpandException("Enumeration not supported") else -> throw ExpandException("Not known type") } @@ -580,6 +585,7 @@ class Initializer : BasicMaestroExpansionPlugin { addToPortsAlreadySet(fmu, port.scalarVariable) SetInstruction(fmu, port) } + else -> throw ExpandException("Internal error") } } else @@ -594,7 +600,7 @@ class Initializer : BasicMaestroExpansionPlugin { val fmuToPorts = ports.groupBy { i -> i.instance.text } .map { i -> i.key to i.value.map { p -> - fmuInstances.getValue(i.key).getPort(p.scalarVariable.getName()) + fmuInstances.getValue(i.key).getPort(p.name) } } .toMap() diff --git a/plugins/jacobianstepbuilder/src/main/java/org/intocps/maestro/plugin/JacobianStepBuilder.java b/plugins/jacobianstepbuilder/src/main/java/org/intocps/maestro/plugin/JacobianStepBuilder.java index 5236918be..4168084e4 100644 --- a/plugins/jacobianstepbuilder/src/main/java/org/intocps/maestro/plugin/JacobianStepBuilder.java +++ b/plugins/jacobianstepbuilder/src/main/java/org/intocps/maestro/plugin/JacobianStepBuilder.java @@ -14,7 +14,10 @@ import org.intocps.maestro.core.dto.StepAlgorithm; import org.intocps.maestro.core.messages.IErrorReporter; import org.intocps.maestro.fmi.Fmi2ModelDescription; +import org.intocps.maestro.framework.core.FrameworkUnitInfo; import org.intocps.maestro.framework.core.ISimulationEnvironment; +import org.intocps.maestro.framework.core.RelationVariable; +import org.intocps.maestro.framework.fmi2.ComponentInfo; import org.intocps.maestro.framework.fmi2.Fmi2SimulationEnvironment; import org.intocps.maestro.framework.fmi2.ModelSwapInfo; import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; @@ -201,8 +204,8 @@ public RuntimeConfigAddition expandWithRuntimeAddition(AFunctionDeclarati fmuInstances.forEach((identifier, instance) -> { Set scalarVariablesToGet = instance.getPorts().stream().filter(p -> jacobianStepConfig.getVariablesOfInterest().stream() .anyMatch(p1 -> p1.equals(p.getMultiModelScalarVariableName()))).map(PortFmi2Api::getName).collect(Collectors.toSet()); - scalarVariablesToGet.addAll(env.getVariablesToLog(instance.getEnvironmentName()).stream().map(var -> var.scalarVariable.getName()) - .collect(Collectors.toSet())); + scalarVariablesToGet.addAll( + env.getVariablesToLog(instance.getEnvironmentName()).stream().map(RelationVariable::getName).collect(Collectors.toSet())); componentsToPortsWithValues.put(instance, instance.get(scalarVariablesToGet.toArray(String[]::new))); }); @@ -218,14 +221,21 @@ public RuntimeConfigAddition expandWithRuntimeAddition(AFunctionDeclarati boolean everyFMUSupportsGetState = true; int indexer = 0; for (ComponentVariableFmi2Api instance : fmuInstances.values()) { - StringVariableFmi2Api fullyQualifiedFMUInstanceName = new StringVariableFmi2Api(null, null, null, null, - MableAstFactory.newAStringLiteralExp( - env.getInstanceByLexName(instance.getEnvironmentName()).getFmuIdentifier() + "." + instance.getName())); - fmuNamesToFmuInstances.put(fullyQualifiedFMUInstanceName, instance); - fmuInstanceToCommunicationPoint.put(instance, fmuCommunicationPoints.items().get(indexer)); + FrameworkUnitInfo v = env.getInstanceByLexName(instance.getEnvironmentName()); + if (v instanceof ComponentInfo) { + StringVariableFmi2Api fullyQualifiedFMUInstanceName = new StringVariableFmi2Api(null, null, null, null, + MableAstFactory.newAStringLiteralExp(((ComponentInfo) v).getFmuIdentifier() + "." + instance.getName())); + fmuNamesToFmuInstances.put(fullyQualifiedFMUInstanceName, instance); + + fmuInstanceToCommunicationPoint.put(instance, fmuCommunicationPoints.items().get(indexer)); + + everyFMUSupportsGetState = instance.getModelDescription().getCanGetAndSetFmustate() && everyFMUSupportsGetState; + + } else { + throw new RuntimeException("instance is not fmi2"); + } - everyFMUSupportsGetState = instance.getModelDescription().getCanGetAndSetFmustate() && everyFMUSupportsGetState; indexer++; } diff --git a/plugins/sigver/src/main/kotlin/MasterModelMapper.kt b/plugins/sigver/src/main/kotlin/MasterModelMapper.kt index 0e9b983ef..cb758750b 100644 --- a/plugins/sigver/src/main/kotlin/MasterModelMapper.kt +++ b/plugins/sigver/src/main/kotlin/MasterModelMapper.kt @@ -26,7 +26,8 @@ class MasterModelMapper { } private fun multiModelConnectionNameToPortName(name: String): String { - return name.split(Sigver.MULTI_MODEL_FMU_INSTANCE_DELIMITER).let { it.subList(2, it.size).joinToString(Sigver.MULTI_MODEL_FMU_INSTANCE_DELIMITER) } + return name.split(Sigver.MULTI_MODEL_FMU_INSTANCE_DELIMITER) + .let { it.subList(2, it.size).joinToString(Sigver.MULTI_MODEL_FMU_INSTANCE_DELIMITER) } } fun scenarioToMasterModel(scenario: String): MasterModel { @@ -80,7 +81,8 @@ class MasterModelMapper { }.flatten() // Instantiate a simulationConfiguration to be able to access fmu model descriptions - val simulationConfiguration = Fmi2SimulationEnvironmentConfiguration(extendedMultiModel.connections, extendedMultiModel.fmus) + val simulationConfiguration = + Fmi2SimulationEnvironmentConfiguration(extendedMultiModel.connections, extendedMultiModel.fmus) // Map fmus to fmu models val simulationEnvironment = Fmi2SimulationEnvironment.of(simulationConfiguration, null) @@ -93,8 +95,9 @@ class MasterModelMapper { }.flatten().distinct() val fmuNameToFmuModel = fmuInstanceNames.mapNotNull { fmuInstanceName -> fmusWithModelDescriptions.find { it.key.contains(getFmuNameFromFmuInstanceName(fmuInstanceName)) } - ?.let { fmuWithMD -> - val scalarVariables = fmuWithMD.value.scalarVariables + //FIXME we are filtering our fmi3 here + ?.takeIf { p -> p.value is Fmi2ModelDescription }?.let { fmuWithMD -> + val scalarVariables = (fmuWithMD.value as Fmi2ModelDescription).scalarVariables val inputs = scalarVariables.filter { port -> port.causality.equals(Fmi2ModelDescription.Causality.Input) } .associate { inputPort -> From 5a6e08f8565b72d879001cb72866b4fa5504485f Mon Sep 17 00:00:00 2001 From: Kenneth Lausdahl Date: Thu, 14 Sep 2023 12:25:16 +0200 Subject: [PATCH 20/54] Change type checker to not allow mixed none numeric types in array initializers --- .../maestro/typechecker/TypeCheckVisitor.java | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/typechecker/src/main/java/org/intocps/maestro/typechecker/TypeCheckVisitor.java b/typechecker/src/main/java/org/intocps/maestro/typechecker/TypeCheckVisitor.java index d86911014..5e8a84804 100644 --- a/typechecker/src/main/java/org/intocps/maestro/typechecker/TypeCheckVisitor.java +++ b/typechecker/src/main/java/org/intocps/maestro/typechecker/TypeCheckVisitor.java @@ -158,7 +158,7 @@ public PType caseAArrayIndexExp(AArrayIndexExp node, Context ctxt) throws Analys for (int i = 0; i < node.getIndices().size(); i++) { // If this happens, then we are finished already. if (!(iterationType instanceof AArrayType)) { - errorReporter.report(0, "Canont index none array expression", null); + errorReporter.report(0, "Cannot index none array expression", null); return store(node, MableAstFactory.newAUnknownType()); } else { iterationType = ((AArrayType) iterationType).getType(); @@ -270,14 +270,22 @@ PType narrow(List types) { } boolean isNumeric = types.stream().allMatch(t -> t instanceof SNumericPrimitiveType); - if (!isNumeric) { - return types.get(0); - } + + //FIXME we allow bool to act as a numeric type in array initializers + isNumeric |= types.stream().anyMatch(t -> t instanceof ABooleanPrimitiveType); + PType type = types.get(0); for (int i = 1; i < types.size(); i++) { PType from = types.get(i); if (!typeComparator.compatible(type, from)) { - type = from; + if (isNumeric) { + //for numeric types we expand the type if not fitting + type = from; + } else { + errorReporter.report(-5, + String.format("Array initializer contains mixed types. Expected '%s', got '%s' at position %d", type + "", from + "", i), + null); + } } } return type; From d105829f71d91380f1ed735c7c5cd6d9c8bcc2e2 Mon Sep 17 00:00:00 2001 From: Kenneth Lausdahl Date: Thu, 14 Sep 2023 12:25:52 +0200 Subject: [PATCH 21/54] added instantiation of fmi3 --- .../template/MaBLTemplateGenerator.java | 145 +++++++++++++----- 1 file changed, 108 insertions(+), 37 deletions(-) diff --git a/maestro/src/main/java/org/intocps/maestro/template/MaBLTemplateGenerator.java b/maestro/src/main/java/org/intocps/maestro/template/MaBLTemplateGenerator.java index 4fe681674..7e0f96bb8 100644 --- a/maestro/src/main/java/org/intocps/maestro/template/MaBLTemplateGenerator.java +++ b/maestro/src/main/java/org/intocps/maestro/template/MaBLTemplateGenerator.java @@ -14,8 +14,10 @@ import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; import org.intocps.maestro.framework.core.FrameworkUnitInfo; import org.intocps.maestro.framework.core.IRelation; +import org.intocps.maestro.framework.fmi2.ComponentInfo; import org.intocps.maestro.framework.fmi2.FaultInjectWithLexName; import org.intocps.maestro.framework.fmi2.Fmi2SimulationEnvironment; +import org.intocps.maestro.framework.fmi2.InstanceInfo; import org.intocps.maestro.plugin.IMaestroPlugin; import org.intocps.maestro.plugin.JacobianStepConfig; import org.slf4j.Logger; @@ -54,7 +56,10 @@ public class MaBLTemplateGenerator { public static final String DEBUG_LOGGING_EXPANSION_FUNCTION_NAME = "enableDebugLogging"; public static final String DEBUG_LOGGING_MODULE_NAME = "DebugLogging"; public static final String FMI2COMPONENT_TYPE = "FMI2Component"; + public static final String FMI3INSTANCE_TYPE = "FMI3Instance"; public static final String COMPONENTS_ARRAY_NAME = "components"; + + public static final String INSTANCES_ARRAY_NAME = "instances"; public static final String COMPONENTS_TRANSFER_ARRAY_NAME = "componentsTransfer"; public static final String GLOBAL_EXECUTION_CONTINUE = IMaestroPlugin.GLOBAL_EXECUTION_CONTINUE; public static final String STATUS = IMaestroPlugin.FMI_STATUS_VARIABLE_NAME; @@ -95,11 +100,11 @@ public static String findInstanceLexName(String preferredName, Collection createFmuVariable(String fmuLexName, String fmuKey) { + public static List createFmuVariable(String fmuLexName, String fmuKey, String type) { List statements = new ArrayList<>(); AFmuMappingStm mapping = newAFMUMappingStm(newAIdentifier(fmuLexName), fmuKey); statements.add(mapping); - PStm var = newVariable(fmuLexName, newANameType("FMI2"), newNullExp()); + PStm var = newVariable(fmuLexName, newANameType(type), newNullExp()); statements.add(var); return statements; } @@ -125,25 +130,38 @@ public static PStm createFMULoad(String fmuLexName, Map.Entry createFmuInstanceVariable(String instanceLexName, boolean external, String instanceEnvironmentKey) { + public static List createFmuInstanceVariable(String instanceLexName, boolean external, String instanceEnvironmentKey, String type) { List statements = new ArrayList<>(); AInstanceMappingStm mapping = newAInstanceMappingStm(newAIdentifier(instanceLexName), instanceEnvironmentKey); statements.add(mapping); - PStm var = newVariable(external, instanceLexName, newANameType("FMI2Component"), external ? null : newNullExp()); + PStm var = newVariable(external, instanceLexName, newANameType(type), external ? null : newNullExp()); statements.add(var); return statements; } - public static Map.Entry, List> createFMUInstantiateStatement(String instanceLexName, String instanceEnvironmentKey, - String fmuLexName, boolean visible, boolean loggingOn, FaultInjectWithLexName faultInject) { + public static Map.Entry, List> createFMUInstantiateStatement(TemplateInstanceList.TemplateInstance instance, String fmuLexName, + boolean visible, boolean loggingOn, FaultInjectWithLexName faultInject) { List rootStatements = new ArrayList<>(); List tryBlockStatements = new ArrayList<>(); - String instanceLexName_ = instanceLexName; + String instanceLexName = instance.getLexName(); + String instanceEnvironmentKey = instance.getName(); + + if (instance.source instanceof ComponentInfo) { + List instantiate = Arrays.asList(newAAssignmentStm(newAIdentifierStateDesignator(newAIdentifier(instanceLexName)), + call(fmuLexName, "instantiate", newAStringLiteralExp(instanceEnvironmentKey), newABoolLiteralExp(visible), + newABoolLiteralExp(loggingOn))), checkNullAndStop(instanceLexName)); + tryBlockStatements.addAll(instantiate); + } else if (instance.source instanceof InstanceInfo) { + String requiredIntermediateVariablesLex = instanceLexName + "_requiredIntermediateVariables"; + + List instantiate = Arrays.asList(newVariable(requiredIntermediateVariablesLex, new AUIntNumericPrimitiveType(), 0), + newAAssignmentStm(newAIdentifierStateDesignator(newAIdentifier(instanceLexName)), + call(fmuLexName, "instantiateCoSimulation", newAStringLiteralExp(instanceEnvironmentKey), newABoolLiteralExp(visible), + newABoolLiteralExp(loggingOn), newABoolLiteralExp(false), newABoolLiteralExp(false), + newAIdentifierExp(requiredIntermediateVariablesLex))), checkNullAndStop(instanceLexName)); + tryBlockStatements.addAll(instantiate); + } - List instantiate = Arrays.asList(newAAssignmentStm(newAIdentifierStateDesignator(newAIdentifier(instanceLexName_)), - call(fmuLexName, "instantiate", newAStringLiteralExp(instanceEnvironmentKey), newABoolLiteralExp(visible), - newABoolLiteralExp(loggingOn))), checkNullAndStop(instanceLexName_)); - tryBlockStatements.addAll(instantiate); if (faultInject != null) { AInstanceMappingStm fiToEnvMapping = newAInstanceMappingStm(newAIdentifier(faultInject.lexName), instanceEnvironmentKey); @@ -152,7 +170,7 @@ public static Map.Entry, List> createFMUInstantiateStatement(St rootStatements.addAll(Arrays.asList(fiToEnvMapping, transferAsStm, ficomp)); tryBlockStatements.addAll(Arrays.asList(newAAssignmentStm(newAIdentifierStateDesignator(newAIdentifier(faultInject.lexName)), newACallExp(newAIdentifierExp(FAULT_INJECT_MODULE_VARIABLE_NAME), newAIdentifier("faultInject"), - Arrays.asList(newAIdentifierExp(fmuLexName), newAIdentifierExp(instanceLexName_), + Arrays.asList(newAIdentifierExp(fmuLexName), newAIdentifierExp(instanceLexName), newAStringLiteralExp(faultInject.constraintId)))), checkNullAndStop(faultInject.lexName))); } @@ -189,6 +207,52 @@ public static ExpandStatements generateAlgorithmStms(IAlgorithmConfig algorithmC return new ExpandStatements(List.of(createRealVariable(STEP_SIZE_NAME, algorithmConfig.getStepSize())), List.of(algorithmStm)); } + /** + * Helper class to hold instances associating the base framework info with name, and lexname + */ + static class TemplateInstanceList extends Vector { + public String getLexNameFromName(String name) { + return this.stream().filter(i -> i.getName().equals(name)).findFirst().map(TemplateInstance::getLexName).get(); + + } + + public TemplateInstanceList getFmi2List() { + TemplateInstanceList list = new TemplateInstanceList(); + list.addAll(this.stream().filter(i -> i.source instanceof ComponentInfo).collect(Collectors.toList())); + return list; + } + + public TemplateInstanceList getFmi3List() { + TemplateInstanceList list = new TemplateInstanceList(); + list.addAll(this.stream().filter(i -> i.source instanceof InstanceInfo).collect(Collectors.toList())); + return list; + } + + public TemplateInstance getByName(String name) { + return this.stream().filter(i -> i.getName().equals(name)).findFirst().get(); + } + + static class TemplateInstance { + private final FrameworkUnitInfo source; + private final String lexName; + private final String name; + + public TemplateInstance(FrameworkUnitInfo source, String lexName, String name) { + this.source = source; + this.lexName = lexName; + this.name = name; + } + + public String getLexName() { + return lexName; + } + + public String getName() { + return name; + } + } + } + public static ASimulationSpecificationCompilationUnit generateTemplate( MaBLTemplateConfiguration templateConfiguration) throws XPathExpressionException, JsonProcessingException { @@ -241,26 +305,28 @@ public static ASimulationSpecificationCompilationUnit generateTemplate( for (Map.Entry entry : unitRelationShip.getFmusWithModelDescriptions()) { String fmuLexName = removeFmuKeyBraces(entry.getKey()); fmuLexName = NameMapper.makeSafeFMULexName(fmuLexName, nameMapperState); - rootScopeBody.addAll(createFmuVariable(fmuLexName, entry.getKey())); + rootScopeBody.addAll(createFmuVariable(fmuLexName, entry.getKey(), + entry.getValue() instanceof Fmi2ModelDescription ? FMI2_MODULE_NAME : FMI3_MODULE_NAME)); fmuNameToLexIdentifier.put(entry.getKey(), fmuLexName); } + + TemplateInstanceList instances = new TemplateInstanceList(); + // Create the FMU Instances and assign to null // invalidNames contains all the existing variable names. These cannot be resued Set invalidNames = new HashSet<>(fmuNameToLexIdentifier.values()); - HashMap instanceLexToInstanceName = new HashMap<>(); - Map instaceNameToInstanceLex = new HashMap<>(); unitRelationShip.getInstances().forEach(entry -> { // Get instanceName String instanceLexName = findInstanceLexName(entry.getKey(), invalidNames); invalidNames.add(instanceLexName); - instanceLexToInstanceName.put(instanceLexName, entry.getKey()); - instaceNameToInstanceLex.put(entry.getKey(), instanceLexName); + instances.add(new TemplateInstanceList.TemplateInstance(entry.getValue(), instanceLexName, entry.getKey())); //determine if fmu is external boolean external = unitRelationShip.getModelTransfers().stream().anyMatch(p -> p.getKey().equals(entry.getKey())); - rootScopeBody.addAll(createFmuInstanceVariable(instanceLexName, external, entry.getKey())); + rootScopeBody.addAll(createFmuInstanceVariable(instanceLexName, external, entry.getKey(), + entry.getValue() instanceof ComponentInfo ? FMI2COMPONENT_TYPE : FMI3INSTANCE_TYPE)); }); StatementMaintainer stmMaintainer = new StatementMaintainer(); @@ -274,7 +340,7 @@ public static ASimulationSpecificationCompilationUnit generateTemplate( String fmuLexName = removeFmuKeyBraces(inst.getOwnerIdentifier()); fmuTransfers.add(fmuLexName); - String instanceLexName = instaceNameToInstanceLex.get(entry.getKey()); + String instanceLexName = instances.getLexNameFromName(entry.getKey()); instanceTransfers.add(instanceLexName); } @@ -303,9 +369,10 @@ public static ASimulationSpecificationCompilationUnit generateTemplate( // Find parent lex String parentLex = fmuNameToLexIdentifier.get(entry.getValue().getOwnerIdentifier()); // Get instanceName - String instanceLexName = instaceNameToInstanceLex.get(entry.getKey()); + TemplateInstanceList.TemplateInstance instance = instances.getByName(entry.getKey()); // If instance already transferred skip this iteration + String instanceLexName = instance.getLexName(); if (instanceTransfers.contains(instanceLexName)) { return; } @@ -319,8 +386,8 @@ public static ASimulationSpecificationCompilationUnit generateTemplate( } Map.Entry, List> fmuInstantiateStatement = - createFMUInstantiateStatement(instanceLexName, entry.getKey(), parentLex, templateConfiguration.getVisible(), - templateConfiguration.getLoggingOn(), faultInjectedInstances.get(instanceLexName)); + createFMUInstantiateStatement(instance, parentLex, templateConfiguration.getVisible(), templateConfiguration.getLoggingOn(), + faultInjectedInstances.get(instanceLexName)); rootScopeBody.addAll(fmuInstantiateStatement.getKey()); stmMaintainer.addAll(fmuInstantiateStatement.getValue()); @@ -334,13 +401,14 @@ public static ASimulationSpecificationCompilationUnit generateTemplate( // Debug logging if (templateConfiguration.getLoggingOn()) { - stmMaintainer.addAll(createDebugLoggingStms(instaceNameToInstanceLex, templateConfiguration.getLogLevels())); + stmMaintainer.addAll(createDebugLoggingStms(instances, templateConfiguration.getLogLevels())); stmMaintainer.wrapInIfBlock(); } - var instanceLexToComponentsArray = new HashSet(); - for (String instanceLex : instanceLexToInstanceName.keySet()) { + var instanceLexToComponentsArray = new Vector(); + for (String instanceLex : instances.getFmi2List().stream().map(TemplateInstanceList.TemplateInstance::getLexName).distinct() + .collect(Collectors.toList())) { var fi = faultInjectedInstances.get(instanceLex); if (fi != null) { instanceLexToComponentsArray.add(fi.lexName); @@ -349,9 +417,13 @@ public static ASimulationSpecificationCompilationUnit generateTemplate( } } // Components Array - stmMaintainer.add(createComponentsArray(COMPONENTS_ARRAY_NAME, instanceLexToComponentsArray)); + stmMaintainer.add(createArray(COMPONENTS_ARRAY_NAME, FMI2COMPONENT_TYPE, instanceLexToComponentsArray)); + if (!instances.getFmi3List().isEmpty()) { + stmMaintainer.add(createArray(INSTANCES_ARRAY_NAME, FMI3INSTANCE_TYPE, + instances.getFmi3List().stream().map(TemplateInstanceList.TemplateInstance::getLexName).distinct().collect(Collectors.toList()))); + } if (modelSwapActive) { - stmMaintainer.add(createComponentsArray(COMPONENTS_TRANSFER_ARRAY_NAME, instanceTransfers)); + stmMaintainer.add(createArray(COMPONENTS_TRANSFER_ARRAY_NAME, FMI2COMPONENT_TYPE, new Vector<>(instanceTransfers))); } // Generate the jacobian step algorithm expand statement. i.e. fixedStep or variableStep and variable statement for step-size. @@ -484,9 +556,9 @@ private static PStm checkNullAndStop(String identifier) { null); } - private static Collection createDebugLoggingStmsHelper(Map instaceNameToInstanceLex, String instanceName, + private static Collection createDebugLoggingStmsHelper(TemplateInstanceList instances, String instanceName, List logLevels) { - String instanceLexName = instaceNameToInstanceLex.get(instanceName); + String instanceLexName = instances.getLexNameFromName(instanceName); if (instanceLexName != null) { return createExpandDebugLogging(instanceLexName, logLevels); } else { @@ -496,25 +568,24 @@ private static Collection createDebugLoggingStmsHelper(Map createDebugLoggingStms(Map instaceNameToInstanceLex, - Map> logLevels) { + private static Collection createDebugLoggingStms(TemplateInstanceList instances, Map> logLevels) { List stms = new ArrayList<>(); // If no logLevels have defined, then call setDebugLogging for all instances if (logLevels == null) { - for (Map.Entry entry : instaceNameToInstanceLex.entrySet()) { - stms.addAll(createDebugLoggingStmsHelper(instaceNameToInstanceLex, entry.getKey(), new ArrayList<>())); + for (TemplateInstanceList.TemplateInstance entry : instances) { + stms.addAll(createDebugLoggingStmsHelper(instances, entry.getName(), new ArrayList<>())); } } else { // If loglevels have been defined for some instances, then only call setDebugLogging for those instances. for (Map.Entry> entry : logLevels.entrySet()) { // If the instance is available as key in loglevels but has an empty value, then call setDebugLogging with empty loglevels. if (entry.getValue().isEmpty()) { - stms.addAll(createDebugLoggingStmsHelper(instaceNameToInstanceLex, entry.getKey(), new ArrayList<>())); + stms.addAll(createDebugLoggingStmsHelper(instances, entry.getKey(), new ArrayList<>())); continue; } // If the instance is available as key in loglevels and has nonempty value, then call setDebugLogging with the relevant values. - stms.addAll(createDebugLoggingStmsHelper(instaceNameToInstanceLex, entry.getKey(), entry.getValue())); + stms.addAll(createDebugLoggingStmsHelper(instances, entry.getKey(), entry.getValue())); } } @@ -567,9 +638,9 @@ private static Collection generateUnloadStms() { return null; } - private static PStm createComponentsArray(String lexName, Set keySet) { + private static PStm createArray(String lexName, String type, List keySet) { return MableAstFactory.newALocalVariableStm(MableAstFactory.newAVariableDeclaration(MableAstFactory.newAIdentifier(lexName), - MableAstFactory.newAArrayType(MableAstFactory.newANameType(FMI2COMPONENT_TYPE)), keySet.size(), + MableAstFactory.newAArrayType(MableAstFactory.newANameType(type)), keySet.size(), MableAstFactory.newAArrayInitializer(keySet.stream().map(x -> aIdentifierExpFromString(x)).collect(Collectors.toList())))); } From fe86ff0568b359cde44d578d5bebecd0e5e5e09e Mon Sep 17 00:00:00 2001 From: Nestor Date: Thu, 14 Sep 2023 12:43:01 +0200 Subject: [PATCH 22/54] terminate, enter/exit initializationMode Signed-off-by: Nestor --- .../framework/fmi2/api/Fmi2Builder.java | 229 ++++++++++++++++++ .../fmi2/api/mabl/MablApiBuilder.java | 102 ++++---- .../scoping/DynamicActiveBuilderScope.java | 2 +- .../fmi2/api/mabl/scoping/ScopeFmi2Api.java | 2 +- .../mabl/variables/FmuVariableFmi3Api.java | 4 - .../variables/InstanceVariableFmi3Api.java | 131 ++++++---- .../variables/StateMablVariableFmi3Api.java | 8 +- .../org/intocps/maestro/BuilderFmi3Test.java | 11 +- .../fmi3/reference/bounchingball/fmi3_bb.mabl | 2 - 9 files changed, 377 insertions(+), 114 deletions(-) diff --git a/frameworks/builder/src/main/java/org/intocps/maestro/framework/fmi2/api/Fmi2Builder.java b/frameworks/builder/src/main/java/org/intocps/maestro/framework/fmi2/api/Fmi2Builder.java index 3c15dcb2e..f6d78fcd1 100644 --- a/frameworks/builder/src/main/java/org/intocps/maestro/framework/fmi2/api/Fmi2Builder.java +++ b/frameworks/builder/src/main/java/org/intocps/maestro/framework/fmi2/api/Fmi2Builder.java @@ -755,6 +755,235 @@ interface PortExpressionValueMap extends Map { } } + /** + * Interface for an fmi instance. + *

+ * Note that all methods that do not take a scope uses the builders dynamic scope and adds the underlying instructions int he active scope. + */ + interface Fmi3InstanceVariable extends Variable> { + + void setDebugLogging(List categories, boolean enableLogging); + + void setupExperiment(DoubleVariable startTime, DoubleVariable endTime, BoolVariable endTimeDefined, Double tolerance); + + void setupExperiment(double startTime, Double endTime, Double tolerance); + + int enterInitializationMode(boolean toleranceDefined, double tolerance, double startTime, boolean stopTimeDefined, double stopTime); + + int exitInitializationMode(); + + void setupExperiment(Scope scope, DoubleVariable startTime, DoubleVariable endTime, BoolVariable endTimeDefined, + Double tolerance); + + void setupExperiment(Scope scope, double startTime, Double endTime, Double tolerance); + + int enterInitializationMode(Scope scope,boolean toleranceDefined, double tolerance, double startTime, boolean stopTimeDefined, + double stopTime); + + int exitInitializationMode(Scope scope); + + int terminate(Scope scope); + + int terminate(); + +// void freeInstance(); +// +// void freeInstance(Scope scope); + + /** + * @param scope + * @param currentCommunicationPoint + * @param communicationStepSize + * @param noSetFMUStatePriorToCurrentPoint a pair representing (full step completed, current time after step) + * @return + */ + Map.Entry, DoubleVariable> step(Scope scope, DoubleVariable currentCommunicationPoint, + DoubleVariable communicationStepSize, BoolVariable noSetFMUStatePriorToCurrentPoint); + + Map.Entry, DoubleVariable> step(Scope scope, DoubleVariable currentCommunicationPoint, + DoubleVariable communicationStepSize); + + Map.Entry, DoubleVariable> step(DoubleVariable currentCommunicationPoint, DoubleVariable communicationStepSize, + BoolVariable noSetFMUStatePriorToCurrentPoint); + + Map.Entry, DoubleVariable> step(DoubleVariable currentCommunicationPoint, DoubleVariable communicationStepSize); + + + List getPorts(); + + /** + * Get ports by name + * + * @param names + * @return + */ + List getPorts(String... names); + + /** + * Get ports by ref val + * + * @param valueReferences + * @return + */ + List getPorts(int... valueReferences); + + /** + * Get port by name + * + * @param name + * @return + */ + Port getPort(String name); + + /** + * Get port by ref val + * + * @param valueReference + * @return + */ + Port getPort(int valueReference); + + /** + * Get port values aka fmiGet + * + * @param ports + * @return + */ + Map> get(Port... ports); + + Map> get(Scope scope, Port... ports); + + /** + * Get all (linked) port values + * + * @return + */ + Map> get(); + + /** + * get filter by value reference + * + * @param valueReferences + * @return + */ + Map> get(int... valueReferences); + + /** + * Get filter by names + * + * @param names + * @return + */ + Map> get(String... names); + + Map> getAndShare(String... names); + + Map> getAndShare(Port... ports); + + Map> getAndShare(); + + Variable getShared(String name); + + Variable getShared(Port port); + + /** + * Get the value of a single port + * + * @param name + * @return + */ + Variable getSingle(String name); + + Variable getSingle(Port port); + + void set(Scope scope, PortValueMap value); + + + void set(Scope scope, PortVariableMap value); + + /** + * Set port values (if ports is not from this fmu then the links are used to remap) + * + * @param value + */ + void set(PortValueMap value); + + void set(Port port, Value value); + + void set(Port port, Variable value); + + void set(Scope scope, Port port, Variable value); + + void set(PortVariableMap value); + + /** + * Set this fmu port by name and link + */ + void setLinked(Scope scope, Port... filterPorts); + + void setLinked(); + + void setLinked(Port... filterPorts); + + void setLinked(String... filterNames); + + void setLinked(long... filterValueReferences); + + /** + * Set this fmu ports by val ref + * + * @param values + */ + void setInt(Map> values); + + /** + * Set this fmy ports by name + * + * @param value + */ + void setString(Map> value); + + /** + * Makes the values publicly available to all linked connections. On next set these ports will be resolved to the values given for + * other fmu + * + * @param values + */ + void share(Map> values); + + /** + * Makes the value publicly available to all linked connections. On next set these ports will be resolved to the values given for + * other fmu + * + * @param value + */ + void share(Port port, Variable value); + + /** + * Get the current state + * + * @return + */ + StateVariable getState() throws XPathExpressionException; + + /** + * Get the current state + * + * @return + */ + StateVariable getState(Scope scope) throws XPathExpressionException; + + + interface PortVariableMap extends Map> { + } + + interface PortValueMap extends Map> { + } + + interface PortExpressionValueMap extends Map { + } + } + interface Variable { String getName(); diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/MablApiBuilder.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/MablApiBuilder.java index d4c83d2eb..344091a92 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/MablApiBuilder.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/MablApiBuilder.java @@ -35,7 +35,7 @@ public class MablApiBuilder implements Fmi2Builder fmiStatusVariables; + private final Map fmiStatusVariables; private final Set externalLoadedModuleIdentifier = new HashSet<>(); int dynamicScopeInitialSize; List importedModules = new Vector<>(); @@ -140,76 +140,32 @@ public MablSettings getSettings() { return this.settings; } - public IntVariableFmi2Api getFmiStatusConstant(FmiStatus status) { - //if (!settings.fmiErrorHandlingEnabled) { - // throw new IllegalStateException("Fmi error handling feature not enabled"); - // } + interface FmiStatusInterface { + int getValue(); - if (!this.fmiStatusVariables.containsKey(status)) { - switch (status) { - case FMI_OK: { - IntVariableFmi2Api var = rootScope.store(status.name(), FmiStatus.FMI_OK.getValue()); - //relocate to top of scope - rootScope.addAfterOrTop(null, var.getDeclaringStm()); - fmiStatusVariables.put(FmiStatus.FMI_OK, var); - } - break; - case FMI_WARNING: { - IntVariableFmi2Api var = rootScope.store(status.name(), FmiStatus.FMI_WARNING.getValue()); - //relocate to top of scope - rootScope.addAfterOrTop(null, var.getDeclaringStm()); - fmiStatusVariables.put(FmiStatus.FMI_WARNING, var); - break; - } - case FMI_DISCARD: { - IntVariableFmi2Api var = rootScope.store(status.name(), FmiStatus.FMI_DISCARD.getValue()); - //relocate to top of scope - rootScope.addAfterOrTop(null, var.getDeclaringStm()); - fmiStatusVariables.put(FmiStatus.FMI_DISCARD, var); - } - break; - case FMI_ERROR: { - IntVariableFmi2Api var = storeStatusVariable(rootScope, status.name(), FmiStatus.FMI_ERROR.getValue()); - //IntVariableFmi2Api var = rootScope.store(status.name(), FmiStatus.FMI_ERROR.getValue()); - //relocate to top of scope - rootScope.addAfterOrTop(null, var.getDeclaringStm()); - fmiStatusVariables.put(FmiStatus.FMI_ERROR, var); - break; - } - case FMI_FATAL: { - IntVariableFmi2Api var = storeStatusVariable(rootScope, status.name(), FmiStatus.FMI_FATAL.getValue()); - //relocate to top of scope - rootScope.addAfterOrTop(null, var.getDeclaringStm()); - fmiStatusVariables.put(FmiStatus.FMI_FATAL, var); - break; - } - case FMI_PENDING: { - IntVariableFmi2Api var = rootScope.store(status.name(), FmiStatus.FMI_PENDING.getValue()); - //relocate to top of scope - rootScope.addAfterOrTop(null, var.getDeclaringStm()); - fmiStatusVariables.put(FmiStatus.FMI_PENDING, var); - break; - } - } + String getName(); + } + private IntVariableFmi2Api getFmiStatusConstant_aux(FmiStatusInterface status) { + if(!this.fmiStatusVariables.containsKey(status)) { + IntVariableFmi2Api var = rootScope.store(status.getName(), status.getValue()); + rootScope.addAfterOrTop(null, var.getDeclaringStm()); + fmiStatusVariables.put(status, var); } - return this.fmiStatusVariables.get(status); } + public IntVariableFmi2Api getFmiStatusConstant(FmiStatus status) {return getFmiStatusConstant_aux(status);} + public IntVariableFmi2Api getFmiStatusConstant(Fmi3Status status) {return getFmiStatusConstant_aux(status);} + public MablToMablAPI getMablToMablAPI() { return this.mablToMablAPI; } - public IntVariableFmi2Api getGlobalFmiStatus() { return globalFmiStatus; } - private IntVariableFmi2Api storeStatusVariable(ScopeFmi2Api rootScope, String name, int errorCode) { - return rootScope.store(() -> this.getNameGenerator().getNameIgnoreCase(name), errorCode); - } - @SuppressWarnings("rawtypes") private Variable createVariable(IMablScope scope, PType type, PExp initialValue, String... prefixes) { String name = nameGenerator.getName(prefixes); @@ -632,7 +588,7 @@ T load(String moduleType, Function, T> creat return m; } - public enum FmiStatus { + public enum FmiStatus implements FmiStatusInterface { FMI_OK(0), FMI_WARNING(1), FMI_DISCARD(2), @@ -645,11 +601,41 @@ public enum FmiStatus { private FmiStatus(final int value) { this.value = value; } + public int getValue() { return this.value; } + // Interface method, not sure how to best preserve enum name() method. + public String getName() { + for (FmiStatus status : FmiStatus.values()) { + if (status.value == this.value) { + return status.name(); + } + } + return null; + } + } + + public enum Fmi3Status implements FmiStatusInterface { + FMI_OK(0), + FMI_WARNING(1), + FMI_DISCARD(2), + FMI_ERROR(3), + FMI_FATAL(4); + private final int value; + private Fmi3Status(final int value) { + this.value = value; + } public int getValue() { return this.value; } + public String getName() { + for (FmiStatus status : FmiStatus.values()) { + if (status.value == this.value) { + return status.name(); + } + } + return null; + } } public static class MablSettings { diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/DynamicActiveBuilderScope.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/DynamicActiveBuilderScope.java index c0821a3e7..342ffedfe 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/DynamicActiveBuilderScope.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/DynamicActiveBuilderScope.java @@ -255,7 +255,7 @@ public void registerComponentVariableFmi2Api(ComponentVariableFmi2Api componentV @Override public void registerInstanceVariableFmi3Api(InstanceVariableFmi3Api instanceVariableFmi3Api) { - // TODO stuff goes here. + activeScope.registerInstanceVariableFmi3Api((instanceVariableFmi3Api)); } @Override diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/ScopeFmi2Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/ScopeFmi2Api.java index 721c4847c..4ddf63a81 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/ScopeFmi2Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/ScopeFmi2Api.java @@ -222,12 +222,12 @@ public IntVariableFmi2Api store(String name, int value) { return store(() -> builder.getNameGenerator().getName(name), value); } - @Override public ArrayVariableFmi2Api store(String name, V[] value) { return store(() -> builder.getNameGenerator().getName(name), value); } + public DoubleVariableFmi2Api store(Supplier nameProvider, double value) { String name = nameProvider.get(); ARealLiteralExp initial = newARealLiteralExp(value); diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/FmuVariableFmi3Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/FmuVariableFmi3Api.java index 0b18e53f2..ddb6d3c42 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/FmuVariableFmi3Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/FmuVariableFmi3Api.java @@ -72,10 +72,6 @@ public InstanceVariableFmi3Api instantiate(String namePrefix, Fmi2Builder.TrySco //TODO: Extract bool visible and bool loggingOn from configuration var var = newVariable(name, newANameType("FMI3Instance"), newNullExp()); - - - - PStm instantiateAssign = newAAssignmentStm(newAIdentifierStateDesignator(name), call(getReferenceExp().clone(), "instantiateCoSimulation", newAStringLiteralExp(name), newABoolLiteralExp(true), newABoolLiteralExp(loggingOn), newABoolLiteralExp(true), newABoolLiteralExp(true), diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/InstanceVariableFmi3Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/InstanceVariableFmi3Api.java index ea1a2e208..8fe16bc1c 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/InstanceVariableFmi3Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/InstanceVariableFmi3Api.java @@ -1,5 +1,6 @@ package org.intocps.maestro.framework.fmi2.api.mabl.variables; +import org.intocps.fmi.jnifmuapi.fmi3.Fmi3Status; import org.intocps.maestro.ast.AVariableDeclaration; import org.intocps.maestro.ast.LexIdentifier; import org.intocps.maestro.ast.MableAstFactory; @@ -36,7 +37,7 @@ @SuppressWarnings("rawtypes") -public class InstanceVariableFmi3Api extends VariableFmi2Api> implements Fmi2Builder.Fmi2ComponentVariable { +public class InstanceVariableFmi3Api extends VariableFmi2Api> implements Fmi2Builder.Fmi3InstanceVariable { final static Logger logger = LoggerFactory.getLogger(InstanceVariableFmi3Api.class); private final static int FMI_OK = 0; private final static int FMI_WARNING = 1; @@ -255,8 +256,8 @@ public void setDebugLogging(List categories, boolean enableLogging) { scope.add(arrayContent, callStm); if (builder.getSettings().fmiErrorHandlingEnabled) { - FmiStatusErrorHandlingBuilder.generate(builder, "setDebugLogging", this, (IMablScope) scope, MablApiBuilder.FmiStatus.FMI_ERROR, - MablApiBuilder.FmiStatus.FMI_FATAL); + FmiStatusErrorHandlingBuilder.generate(builder, "setDebugLogging", this, (IMablScope) scope, MablApiBuilder.Fmi3Status.FMI_ERROR, + MablApiBuilder.Fmi3Status.FMI_FATAL); } } @@ -285,20 +286,19 @@ private void setupExperiment(Fmi2Builder.Scope scope, PExp startTime, PExp startTime.clone(), endTimeDefined, endTime != null ? endTime.clone() : newARealLiteralExp(0d))))); scope.add(stm); if (builder.getSettings().fmiErrorHandlingEnabled) { - FmiStatusErrorHandlingBuilder.generate(builder, "setupExperiment", this, (IMablScope) scope, MablApiBuilder.FmiStatus.FMI_ERROR, - MablApiBuilder.FmiStatus.FMI_FATAL); + FmiStatusErrorHandlingBuilder.generate(builder, "setupExperiment", this, (IMablScope) scope, MablApiBuilder.Fmi3Status.FMI_ERROR, + MablApiBuilder.Fmi3Status.FMI_FATAL); } } @Override - public void enterInitializationMode() { - this.enterInitializationMode(builder.getDynamicScope()); - + public int enterInitializationMode(boolean toleranceDefined, double tolerance, double startTime, boolean stopTimeDefined, double stopTime) { + return this.enterInitializationMode(builder.getDynamicScope(), toleranceDefined, tolerance, startTime, stopTimeDefined, stopTime); } @Override - public void exitInitializationMode() { - this.exitInitializationMode(builder.getDynamicScope()); + public int exitInitializationMode() { + return this.exitInitializationMode(builder.getDynamicScope()); } @Override @@ -313,24 +313,31 @@ public void setupExperiment(Fmi2Builder.Scope scope, double startTime, Dou this.setupExperiment(scope, newARealLiteralExp(startTime), newARealLiteralExp(endTime), newABoolLiteralExp(true), tolerance); } + // TODO: probably should return other things than ok also @Override - public void enterInitializationMode(Fmi2Builder.Scope scope) { - PStm stm = stateTransitionFunction(FmiFunctionType.ENTERINITIALIZATIONMODE); + public int enterInitializationMode(Fmi2Builder.Scope scope, boolean toleranceDefined, double tolerance, double startTime, + boolean stopTimeDefined, double stopTime) { + PStm stm = stateTransitionFunction(FmiFunctionType.ENTERINITIALIZATIONMODE, toleranceDefined, tolerance, startTime, stopTimeDefined, stopTime ); + + scope.add(stm); if (builder.getSettings().fmiErrorHandlingEnabled) { - FmiStatusErrorHandlingBuilder.generate(builder, "enterInitializationMode", this, (IMablScope) scope, MablApiBuilder.FmiStatus.FMI_ERROR, - MablApiBuilder.FmiStatus.FMI_FATAL); + FmiStatusErrorHandlingBuilder.generate(builder, "enterInitializationMode", this, (IMablScope) scope, MablApiBuilder.Fmi3Status.FMI_ERROR, + MablApiBuilder.Fmi3Status.FMI_FATAL); } + return Fmi3Status.OK.value; } + // TODO: Probably return other things than just ok. @Override - public void exitInitializationMode(Fmi2Builder.Scope scope) { + public int exitInitializationMode(Fmi2Builder.Scope scope) { PStm stm = stateTransitionFunction(FmiFunctionType.EXITINITIALIZATIONMODE); scope.add(stm); if (builder.getSettings().fmiErrorHandlingEnabled) { - FmiStatusErrorHandlingBuilder.generate(builder, "exitInitializationMode", this, (IMablScope) scope, MablApiBuilder.FmiStatus.FMI_ERROR, - MablApiBuilder.FmiStatus.FMI_FATAL); + FmiStatusErrorHandlingBuilder.generate(builder, "exitInitializationMode", this, (IMablScope) scope, MablApiBuilder.Fmi3Status.FMI_ERROR, + MablApiBuilder.Fmi3Status.FMI_FATAL); } + return Fmi3Status.OK.value; } @Override @@ -369,8 +376,8 @@ private Map.Entry, Fmi2Builder.DoubleVariable, Fmi2Builder.DoubleVariable Map> get(Fmi2Builder.Scope scop if (builder.getSettings().fmiErrorHandlingEnabled) { FmiStatusErrorHandlingBuilder.generate(builder, createFunctionName(FmiFunctionType.GET, e.getValue().get(0)), this, - (IMablScope) scope, MablApiBuilder.FmiStatus.FMI_ERROR, MablApiBuilder.FmiStatus.FMI_FATAL); + (IMablScope) scope, MablApiBuilder.Fmi3Status.FMI_ERROR, MablApiBuilder.Fmi3Status.FMI_FATAL); } if (builder.getSettings().setGetDerivatives && type.equals(new ARealNumericPrimitiveType())) { @@ -628,7 +655,7 @@ public Map>> getDerivatives(List scope, Fmi2Builder.Port p, Fmi2Builder.ExpressionValue v) { - this.set(scope, new PortValueMapImpl(Map.of(p, v))); + ; + // this.set(scope, new PortValueMapImpl(Map.of(p, v))); } public void set(PortExpressionValueMap value) { @@ -862,7 +890,7 @@ public void set(Fmi2Builder.Scope scope, List selectedPorts, if (builder.getSettings().fmiErrorHandlingEnabled) { FmiStatusErrorHandlingBuilder.generate(builder, createFunctionName(FmiFunctionType.SET, sortedPorts.get(0)), this, (IMablScope) scope, - MablApiBuilder.FmiStatus.FMI_ERROR, MablApiBuilder.FmiStatus.FMI_FATAL); + MablApiBuilder.Fmi3Status.FMI_ERROR, MablApiBuilder.Fmi3Status.FMI_FATAL); } // TODO: IntermediateUpdateMode instead of CanInterpolateInputs? @@ -968,7 +996,7 @@ public void setDerivatives(ArrayVariableFmi2Api derValInBuf, ArrayVariableFmi2Ap // If enabled handle potential errors from calling setRealInputDerivatives if (builder.getSettings().fmiErrorHandlingEnabled) { FmiStatusErrorHandlingBuilder.generate(builder, createFunctionName(FmiFunctionType.SETREALINPUTDERIVATIVES), this, (IMablScope) scope, - MablApiBuilder.FmiStatus.FMI_ERROR, MablApiBuilder.FmiStatus.FMI_FATAL); + MablApiBuilder.Fmi3Status.FMI_ERROR, MablApiBuilder.Fmi3Status.FMI_FATAL); } } @@ -979,20 +1007,22 @@ public void set(PortValueMap value) { @Override public void set(Fmi2Builder.Port port, Fmi2Builder.Variable value) { - this.set(new PortVariableMapImpl(Map.of(port, value))); + ; + // this.set(new PortVariableMapImpl(Map.of(port, value))); } @Override public void set(Fmi2Builder.Scope scope, Fmi2Builder.Port port, Fmi2Builder.Variable value) { - this.set(scope, new PortVariableMapImpl(Map.of(port, value))); + ; +// this.set(scope, new PortVariableMapImpl(Map.of(port, value))); } @Override public void set(Fmi2Builder.Port port, Fmi2Builder.Value value) { - PortValueMap map = new PortValueMapImpl(); - map.put(port, value); - set(map); - + ; + // PortValueMap map = new PortValueMapImpl(); + // map.put(port, value); + // set(map); } @@ -1077,20 +1107,35 @@ public void setString(Map> } @Override - public void terminate() { - this.terminate(builder.getDynamicScope()); + public int terminate() { + return this.terminate(builder.getDynamicScope()); } + // TODO: Return other values but ok? @Override - public void terminate(Fmi2Builder.Scope scope) { + public int terminate(Fmi2Builder.Scope scope) { PStm stm = stateTransitionFunction(FmiFunctionType.TERMINATE); scope.add(stm); if (builder.getSettings().fmiErrorHandlingEnabled) { - FmiStatusErrorHandlingBuilder.generate(builder, "terminate", this, (IMablScope) scope, MablApiBuilder.FmiStatus.FMI_ERROR, - MablApiBuilder.FmiStatus.FMI_FATAL); + FmiStatusErrorHandlingBuilder.generate(builder, "terminate", this, (IMablScope) scope, MablApiBuilder.Fmi3Status.FMI_ERROR, + MablApiBuilder.Fmi3Status.FMI_FATAL); } + return Fmi3Status.OK.value; } +// public void freeInstance() { +// this.terminate(builder.getDynamicScope()); +// } +// +// public void freeInstance(Fmi2Builder.Scope scope) { +// scope.add(newABlockStm(MableAstFactory.newExpressionStm(call(getReferenceExp().clone(), "fmi3FreeInstance")))) +// scope.add(newIf(newNotEqual(((InstanceVariableFmi3Api) inst).getReferenceExp().clone(), newNullExp()), newABlockStm( +// MableAstFactory.newExpressionStm( +// call(getReferenceExp().clone(), "freeInstance", ((InstanceVariableFmi3Api) inst).getReferenceExp().clone())), +// newAAssignmentStm(((InstanceVariableFmi3Api) inst).getDesignatorClone(), newNullExp())), null)); +// } + + // TODO: implement this from the other share function below. This for now to build. @Override public void share(Map> values) { @@ -1280,8 +1325,8 @@ public Fmi2Builder.StateVariable getState(Fmi2Builder.Scope scope) t call(this.getReferenceExp().clone(), "getState", Collections.singletonList(newARefExp(state.getReferenceExp().clone())))); scope.add(stm); if (builder.getSettings().fmiErrorHandlingEnabled) { - FmiStatusErrorHandlingBuilder.generate(builder, "getState", this, (IMablScope) scope, MablApiBuilder.FmiStatus.FMI_ERROR, - MablApiBuilder.FmiStatus.FMI_FATAL); + FmiStatusErrorHandlingBuilder.generate(builder, "getState", this, (IMablScope) scope, MablApiBuilder.Fmi3Status.FMI_ERROR, + MablApiBuilder.Fmi3Status.FMI_FATAL); } return state; @@ -1322,12 +1367,12 @@ public enum FmiFunctionType { */ static class FmiStatusErrorHandlingBuilder { static void generate(MablApiBuilder builder, String method, InstanceVariableFmi3Api instance, IMablScope scope, - MablApiBuilder.FmiStatus... statusesToFail) { + MablApiBuilder.Fmi3Status... statusesToFail) { if (statusesToFail == null || statusesToFail.length == 0) { return; } - Function checkStatusEq = + Function checkStatusEq = s -> newEqual(((IMablScope) scope).getFmiStatusVariable().getReferenceExp().clone(), builder.getFmiStatusConstant(s).getReferenceExp().clone()); @@ -1341,7 +1386,7 @@ static void generate(MablApiBuilder builder, String method, InstanceVariableFmi3 // thenScope.add(newAAssignmentStm(builder.getGlobalExecutionContinue().getDesignator().clone(), newABoolLiteralExp(false))); - for (MablApiBuilder.FmiStatus status : statusesToFail) { + for (MablApiBuilder.Fmi3Status status : statusesToFail) { ScopeFmi2Api s = thenScope.enterIf(new PredicateFmi2Api(checkStatusEq.apply(status))).enterThen(); builder.getLogger() .error(s, method.substring(0, 1).toUpperCase() + method.substring(1) + " failed on '%s' with status: " + status, instance); diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/StateMablVariableFmi3Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/StateMablVariableFmi3Api.java index 826610ad2..f7c2188af 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/StateMablVariableFmi3Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/StateMablVariableFmi3Api.java @@ -38,8 +38,8 @@ public void set(Fmi2Builder.Scope scope) throws IllegalStateException { scope.add(stm); if (builder.getSettings().fmiErrorHandlingEnabled) { InstanceVariableFmi3Api.FmiStatusErrorHandlingBuilder - .generate(builder, "setState", this.owner, (IMablScope) scope, MablApiBuilder.FmiStatus.FMI_ERROR, - MablApiBuilder.FmiStatus.FMI_FATAL); + .generate(builder, "setState", this.owner, (IMablScope) scope, MablApiBuilder.Fmi3Status.FMI_ERROR, + MablApiBuilder.Fmi3Status.FMI_FATAL); } } @@ -59,8 +59,8 @@ public void destroy(Fmi2Builder.Scope scope) throws IllegalStateException scope.add(stm); if (builder.getSettings().fmiErrorHandlingEnabled) { InstanceVariableFmi3Api.FmiStatusErrorHandlingBuilder - .generate(builder, "freeState", this.owner, (IMablScope) scope, MablApiBuilder.FmiStatus.FMI_ERROR, - MablApiBuilder.FmiStatus.FMI_FATAL); + .generate(builder, "freeState", this.owner, (IMablScope) scope, MablApiBuilder.Fmi3Status.FMI_ERROR, + MablApiBuilder.Fmi3Status.FMI_FATAL); } valid = false; diff --git a/maestro/src/test/java/org/intocps/maestro/BuilderFmi3Test.java b/maestro/src/test/java/org/intocps/maestro/BuilderFmi3Test.java index ff099d9cd..66ea38c5e 100644 --- a/maestro/src/test/java/org/intocps/maestro/BuilderFmi3Test.java +++ b/maestro/src/test/java/org/intocps/maestro/BuilderFmi3Test.java @@ -86,6 +86,14 @@ public void wt() throws Exception { InstanceVariableFmi3Api ballInstance = ballFmu.instantiate("ballInstance", varArray); + int res = ballInstance.enterInitializationMode(false, 0.0, 0.0, true,10.0); + res = ballInstance.exitInitializationMode(); + + res = ballInstance.terminate(); + + + + // Create the two FMUs FmuVariableFmi2Api controllerFMU = builder.getDynamicScope() @@ -94,7 +102,8 @@ public void wt() throws Exception { FmuVariableFmi2Api tankFMU = builder.getDynamicScope() .createFMU("tankFMU", (Fmi2ModelDescription) env.getModelDescription("{tankFMU}"), env.getUriFromFMUName("{tankFMU}")); - // Create the controller and tank instanes + + // Create the controller and tank instances ComponentVariableFmi2Api controller = controllerFMU.instantiate("controller"); ComponentVariableFmi2Api tank = tankFMU.instantiate("tank"); DynamicActiveBuilderScope dynamicScope = builder.getDynamicScope(); diff --git a/maestro/src/test/resources/fmi3/reference/bounchingball/fmi3_bb.mabl b/maestro/src/test/resources/fmi3/reference/bounchingball/fmi3_bb.mabl index 77ccf9407..0a97e1163 100644 --- a/maestro/src/test/resources/fmi3/reference/bounchingball/fmi3_bb.mabl +++ b/maestro/src/test/resources/fmi3/reference/bounchingball/fmi3_bb.mabl @@ -32,8 +32,6 @@ import Logger; uint sv_par_e=6; int res=0; - - uint svs[2]={sv_par_g, sv_par_e}; float values_r[2]={-9.81,0.7}; res=instance.setFloat32(svs,values_r); From e070a2eb841e0a048e99f7c240c756b45b63d48a Mon Sep 17 00:00:00 2001 From: Nestor Date: Thu, 14 Sep 2023 14:08:21 +0200 Subject: [PATCH 23/54] Can now pass booleans to instantiateCoSimulation properly, small tweaks Signed-off-by: Nestor --- .../framework/fmi2/api/Fmi2Builder.java | 6 +- .../mabl/variables/FmuVariableFmi3Api.java | 59 ++++++++++--------- .../variables/InstanceVariableFmi3Api.java | 20 +++---- .../org/intocps/maestro/BuilderFmi3Test.java | 13 +++- .../fmi3/reference/bounchingball/fmi3_bb.mabl | 2 +- 5 files changed, 56 insertions(+), 44 deletions(-) diff --git a/frameworks/builder/src/main/java/org/intocps/maestro/framework/fmi2/api/Fmi2Builder.java b/frameworks/builder/src/main/java/org/intocps/maestro/framework/fmi2/api/Fmi2Builder.java index f6d78fcd1..fb3270d91 100644 --- a/frameworks/builder/src/main/java/org/intocps/maestro/framework/fmi2/api/Fmi2Builder.java +++ b/frameworks/builder/src/main/java/org/intocps/maestro/framework/fmi2/api/Fmi2Builder.java @@ -786,9 +786,9 @@ int enterInitializationMode(Scope scope,boolean toleranceDefined, double tole int terminate(); -// void freeInstance(); -// -// void freeInstance(Scope scope); + void freeInstance(); + + void freeInstance(Scope scope); /** * @param scope diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/FmuVariableFmi3Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/FmuVariableFmi3Api.java index ddb6d3c42..26743d3c2 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/FmuVariableFmi3Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/FmuVariableFmi3Api.java @@ -30,7 +30,6 @@ public class FmuVariableFmi3Api extends VariableFmi2Api dynamicScope, PStateDesignator designator, PExp referenceExp) { this(builder, modelDescriptionContext, declaration, type, declaredScope, dynamicScope, designator, referenceExp); @@ -49,33 +48,40 @@ public ModelDescriptionContext3 getModelDescriptionContext() { return modelDescriptionContext; } -// @Override - public InstanceVariableFmi3Api instantiate(String name, String environmentName, ArrayVariableFmi2Api variables) { + public InstanceVariableFmi3Api instantiate(String name, boolean visible, boolean loggingOn, boolean eventModeUsed, + boolean earlyReturnAllowed, ArrayVariableFmi2Api requiredIntermediateVariables) { IMablScope scope = builder.getDynamicScope().getActiveScope(); - return instantiate(name, scope.findParentScope(TryMaBlScope.class), scope, environmentName, variables); + return instantiate(name, scope.findParentScope(TryMaBlScope.class), scope, visible, loggingOn, + eventModeUsed, earlyReturnAllowed, requiredIntermediateVariables); } - public InstanceVariableFmi3Api instantiate(String name, ArrayVariableFmi2Api variables) { + public InstanceVariableFmi3Api instantiate(String name, Fmi2Builder.TryScope enclosingTryScope, Fmi2Builder.Scope scope, + boolean visible, boolean loggingOn, boolean eventModeUsed, boolean earlyReturnAllowed, + ArrayVariableFmi2Api requiredIntermediateVariables) { + return instantiate(name, enclosingTryScope, scope, null, visible, loggingOn, eventModeUsed, + earlyReturnAllowed, requiredIntermediateVariables); + + } + + public InstanceVariableFmi3Api instantiate(String name, String environmentName, boolean visible, boolean loggingOn, boolean eventModeUsed, + boolean earlyReturnAllowed, ArrayVariableFmi2Api requiredIntermediateVariables) { IMablScope scope = builder.getDynamicScope().getActiveScope(); - return instantiate(name, scope.findParentScope(TryMaBlScope.class), scope, variables); + return instantiate(name, scope.findParentScope(TryMaBlScope.class), builder.getDynamicScope(), environmentName, + visible, loggingOn, eventModeUsed, earlyReturnAllowed, requiredIntermediateVariables); } public InstanceVariableFmi3Api instantiate(String namePrefix, Fmi2Builder.TryScope enclosingTryScope, Fmi2Builder.Scope scope, - String environmentName, ArrayVariableFmi2Api variables) { - return instantiate(namePrefix, enclosingTryScope, scope, environmentName, true, variables ); - } - public InstanceVariableFmi3Api instantiate(String namePrefix, Fmi2Builder.TryScope enclosingTryScope, Fmi2Builder.Scope scope, - String environmentName, boolean loggingOn, ArrayVariableFmi2Api variables) { + String environmentName, boolean visible, boolean loggingOn, boolean eventModeUsed, boolean earlyReturnAllowed, + ArrayVariableFmi2Api requiredIntermediateVariables) { String name = builder.getNameGenerator().getName(namePrefix); - //TODO: Extract bool visible and bool loggingOn from configuration var var = newVariable(name, newANameType("FMI3Instance"), newNullExp()); PStm instantiateAssign = newAAssignmentStm(newAIdentifierStateDesignator(name), - call(getReferenceExp().clone(), "instantiateCoSimulation", newAStringLiteralExp(name), newABoolLiteralExp(true), - newABoolLiteralExp(loggingOn), newABoolLiteralExp(true), newABoolLiteralExp(true), - variables.getReferenceExp().clone())); + call(getReferenceExp().clone(), "instantiateCoSimulation", newAStringLiteralExp(name), newABoolLiteralExp(visible), + newABoolLiteralExp(loggingOn), newABoolLiteralExp(eventModeUsed), newABoolLiteralExp(earlyReturnAllowed), + requiredIntermediateVariables.getReferenceExp().clone())); if (enclosingTryScope == null) { throw new IllegalArgumentException("Call to instantiate is not allowed with a null enclosing try scope"); @@ -85,29 +91,29 @@ public InstanceVariableFmi3Api instantiate(String namePrefix, Fmi2Builder.TrySco TryMaBlScope mTryScope = (TryMaBlScope) enclosingTryScope; mTryScope.parent().addBefore(mTryScope.getDeclaration(), var); - InstanceVariableFmi3Api compVar; + InstanceVariableFmi3Api instanceVar; if (environmentName == null) { - compVar = new InstanceVariableFmi3Api(var, this, name, this.modelDescriptionContext, builder, mTryScope.parent(), + instanceVar = new InstanceVariableFmi3Api(var, this, name, this.modelDescriptionContext, builder, mTryScope.parent(), newAIdentifierStateDesignator(newAIdentifier(name)), newAIdentifierExp(name)); } else { AInstanceMappingStm mapping = newAInstanceMappingStm(newAIdentifier(name), environmentName); - compVar = new InstanceVariableFmi3Api(var, this, name, this.modelDescriptionContext, builder, mTryScope.parent(), + instanceVar = new InstanceVariableFmi3Api(var, this, name, this.modelDescriptionContext, builder, mTryScope.parent(), newAIdentifierStateDesignator(newAIdentifier(name)), newAIdentifierExp(name), environmentName); scope.add(mapping); } scope.add(instantiateAssign); - mTryScope.getFinallyBody().addAfterOrTop(null, newIf(newNotEqual(compVar.getReferenceExp().clone(), newNullExp()), - newABlockStm(MableAstFactory.newExpressionStm(call(getReferenceExp().clone(), "freeInstance", compVar.getReferenceExp().clone())), - newAAssignmentStm(compVar.getDesignatorClone(), newNullExp())), null)); + mTryScope.getFinallyBody().addAfterOrTop(null, newIf(newNotEqual(instanceVar.getReferenceExp().clone(), newNullExp()), + newABlockStm(MableAstFactory.newExpressionStm(call(getReferenceExp().clone(), "freeInstance", instanceVar.getReferenceExp().clone())), + newAAssignmentStm(instanceVar.getDesignatorClone(), newNullExp())), null)); scope.activate(); if (builder.getSettings().fmiErrorHandlingEnabled) { ScopeFmi2Api thenScope = - (ScopeFmi2Api) scope.enterIf(new PredicateFmi2Api(newEqual(compVar.getReferenceExp().clone(), newNullExp()))).enterThen(); + (ScopeFmi2Api) scope.enterIf(new PredicateFmi2Api(newEqual(instanceVar.getReferenceExp().clone(), newNullExp()))).enterThen(); builder.getLogger().error(thenScope, "Instantiate failed on fmu: '%s' for instance: '%s'", this.getFmuIdentifier(), namePrefix); thenScope.add(new AErrorStm( @@ -115,14 +121,13 @@ public InstanceVariableFmi3Api instantiate(String namePrefix, Fmi2Builder.TrySco thenScope.leave(); } - ((IMablScope) scope).registerInstanceVariableFmi3Api(compVar); + ((IMablScope) scope).registerInstanceVariableFmi3Api(instanceVar); - return compVar; - } - public InstanceVariableFmi3Api instantiate(String namePrefix, Fmi2Builder.TryScope enclosingTryScope, Fmi2Builder.Scope scope, ArrayVariableFmi2Api variables) { - return instantiate(namePrefix, enclosingTryScope, scope, null, variables); + return instanceVar; } + + public String getFmuIdentifier() { return fmuIdentifier; } diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/InstanceVariableFmi3Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/InstanceVariableFmi3Api.java index 8fe16bc1c..b0e16ee32 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/InstanceVariableFmi3Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/InstanceVariableFmi3Api.java @@ -1123,17 +1123,15 @@ public int terminate(Fmi2Builder.Scope scope) { return Fmi3Status.OK.value; } -// public void freeInstance() { -// this.terminate(builder.getDynamicScope()); -// } -// -// public void freeInstance(Fmi2Builder.Scope scope) { -// scope.add(newABlockStm(MableAstFactory.newExpressionStm(call(getReferenceExp().clone(), "fmi3FreeInstance")))) -// scope.add(newIf(newNotEqual(((InstanceVariableFmi3Api) inst).getReferenceExp().clone(), newNullExp()), newABlockStm( -// MableAstFactory.newExpressionStm( -// call(getReferenceExp().clone(), "freeInstance", ((InstanceVariableFmi3Api) inst).getReferenceExp().clone())), -// newAAssignmentStm(((InstanceVariableFmi3Api) inst).getDesignatorClone(), newNullExp())), null)); -// } + public void freeInstance() { + this.freeInstance(builder.getDynamicScope()); + } + + public void freeInstance(Fmi2Builder.Scope scope) { + // TODO: add fault checks??? + scope.add(MableAstFactory.newExpressionStm(call(getReferenceExp().clone(), "freeInstance"))); + } + // TODO: implement this from the other share function below. This for now to build. diff --git a/maestro/src/test/java/org/intocps/maestro/BuilderFmi3Test.java b/maestro/src/test/java/org/intocps/maestro/BuilderFmi3Test.java index 66ea38c5e..0204077dc 100644 --- a/maestro/src/test/java/org/intocps/maestro/BuilderFmi3Test.java +++ b/maestro/src/test/java/org/intocps/maestro/BuilderFmi3Test.java @@ -84,12 +84,21 @@ public void wt() throws Exception { FmuVariableFmi3Api ballFmu = builder.getDynamicScope().createFMU("ball", md3Ball, ballUri); - InstanceVariableFmi3Api ballInstance = ballFmu.instantiate("ballInstance", varArray); + boolean visible = true; + boolean loggingOn = true; + boolean eventModeUsed = true; + boolean earlyReturnAllowed = true; + InstanceVariableFmi3Api ballInstance = ballFmu.instantiate("ballInstance", visible, loggingOn, eventModeUsed, earlyReturnAllowed, + varArray); int res = ballInstance.enterInitializationMode(false, 0.0, 0.0, true,10.0); res = ballInstance.exitInitializationMode(); - res = ballInstance.terminate(); + ballInstance.freeInstance(); + + + + diff --git a/maestro/src/test/resources/fmi3/reference/bounchingball/fmi3_bb.mabl b/maestro/src/test/resources/fmi3/reference/bounchingball/fmi3_bb.mabl index 0a97e1163..466015039 100644 --- a/maestro/src/test/resources/fmi3/reference/bounchingball/fmi3_bb.mabl +++ b/maestro/src/test/resources/fmi3/reference/bounchingball/fmi3_bb.mabl @@ -106,4 +106,4 @@ import Logger; { unload(x1); } -} \ No newline at end of file +} From 4bbe9b510befb998cc351174248541d478ccf87d Mon Sep 17 00:00:00 2001 From: Kenneth Lausdahl Date: Thu, 5 Oct 2023 10:53:48 +0200 Subject: [PATCH 24/54] changed Fmi2Builder to batter represent fmi2 and 3 --- .../framework/fmi2/api/Fmi2Builder.java | 197 ++++--- .../fmi2/api/mabl/FromMaBLToMaBLAPI.java | 100 ++++ .../framework/fmi2/api/mabl/PortFmi2Api.java | 20 +- .../framework/fmi2/api/mabl/PortFmi3Api.java | 15 +- .../values/PortValueExpresssionMapImpl.java | 4 +- .../api/mabl/values/PortValueMapImpl.java | 4 +- .../variables/ComponentVariableFmi2Api.java | 38 +- .../mabl/variables/FmuVariableFmi2Api.java | 3 +- .../variables/InstanceVariableFmi3Api.java | 510 +++++++++--------- .../mabl/variables/PortVariableMapImpl.java | 5 +- .../framework/fmi2/api/mabl/SetPortsTest.java | 6 +- .../org/intocps/maestro/BuilderHelper.java | 96 ++-- .../template/MaBLTemplateGenerator.java | 19 +- .../src/main/kotlin/Initializer.kt | 453 ++++++++++------ 14 files changed, 925 insertions(+), 545 deletions(-) diff --git a/frameworks/builder/src/main/java/org/intocps/maestro/framework/fmi2/api/Fmi2Builder.java b/frameworks/builder/src/main/java/org/intocps/maestro/framework/fmi2/api/Fmi2Builder.java index 3c15dcb2e..a71b8bc4e 100644 --- a/frameworks/builder/src/main/java/org/intocps/maestro/framework/fmi2/api/Fmi2Builder.java +++ b/frameworks/builder/src/main/java/org/intocps/maestro/framework/fmi2/api/Fmi2Builder.java @@ -265,9 +265,9 @@ interface Scope extends Scoping { @Deprecated Variable store(Value tag); - Fmu2Variable createFMU(String name, String loaderName, String... args) throws Exception; + Fmu2Variable createFMU(String name, String loaderName, String... args) throws Exception; - Fmu3Variable createFMU3(String name, String loaderName, String... args) throws Exception; + Fmu3Variable createFMU3(String name, String loaderName, String... args) throws Exception; void markTransferPoint(String... names); @@ -356,7 +356,21 @@ interface Numeric extends Value, Type { } - interface Port { + interface Port { + + /** + * Gets the fully qualified port name including its source reference. Often on the form source.name + * + * @return + */ + String getQualifiedName(); + + /** + * Gets the underlying objects from which the port is created + * + * @return + */ + T getSourceObject(); /** * Get the port name @@ -377,7 +391,7 @@ interface Port { * * @param receiver */ - void linkTo(Port... receiver) throws PortLinkException; + void linkTo(Port... receiver) throws PortLinkException; /** * Break the source link @@ -485,10 +499,10 @@ interface StateVariable extends Variable { /** * Handle for an fmu for the creation of component */ - interface Fmu2Variable extends Variable> { - Fmi2ComponentVariable instantiate(String name, String environmentname); + interface Fmu2Variable extends Variable> { + Fmi2ComponentVariable instantiate(String name, String environmentname); - Fmi2ComponentVariable instantiate(String name); + Fmi2ComponentVariable instantiate(String name); // /** // * Performs null check and frees the instance @@ -506,12 +520,12 @@ interface Fmu2Variable extends Variable> { // throw new RuntimeException("Argument is not an FMU instance - it is not an instance of ComponentVariableFmi2API"); // } // } - Fmi2ComponentVariable instantiate(String namePrefix, TryScope enclosingTryScope, Scope scope, String environmentName); + Fmi2ComponentVariable instantiate(String namePrefix, TryScope enclosingTryScope, Scope scope, String environmentName); - Fmi2ComponentVariable instantiate(String namePrefix, Fmi2Builder.TryScope enclosingTryScope, Fmi2Builder.Scope scope, + Fmi2ComponentVariable instantiate(String namePrefix, Fmi2Builder.TryScope enclosingTryScope, Fmi2Builder.Scope scope, String environmentName, boolean loggingOn); - Fmi2ComponentVariable instantiate(String name, TryScope enclosingTryScope, Scope scope); + Fmi2ComponentVariable instantiate(String name, TryScope enclosingTryScope, Scope scope); //void freeInstance(Fmi2ComponentVariable comp); @@ -528,38 +542,26 @@ Fmi2ComponentVariable instantiate(String namePrefix, Fmi2Builder.TryScope extends Variable> { + } + /** + * Generic type for all simulation instances + * + * @param + */ + interface SimulationInstance extends Variable> { } /** - * Interface for an fmi compoennt. - *

- * Note that all methods that do not take a scope uses the builders dynamic scope and adds the underlying instructions int he active scope. + * Type that represents common FMI functions accross versions for now 2 and 3 + * + * @param the construction type. Often a kind of AST statement + * @param the port internal reference type. Often a kind of scalar variable from FMI */ - interface Fmi2ComponentVariable extends Variable> { + interface FmiSimulationInstance extends SimulationInstance { void setDebugLogging(List categories, boolean enableLogging); - void setupExperiment(DoubleVariable startTime, DoubleVariable endTime, BoolVariable endTimeDefined, Double tolerance); - - void setupExperiment(double startTime, Double endTime, Double tolerance); - - void enterInitializationMode(); - - void exitInitializationMode(); - - void setupExperiment(Scope scope, DoubleVariable startTime, DoubleVariable endTime, BoolVariable endTimeDefined, - Double tolerance); - - void setupExperiment(Scope scope, double startTime, Double endTime, Double tolerance); - - void enterInitializationMode(Scope scope); - - void exitInitializationMode(Scope scope); - - void terminate(Scope scope); - - void terminate(); /** * @param scope @@ -580,7 +582,7 @@ Map.Entry, DoubleVariable> step(DoubleVariable currentComm Map.Entry, DoubleVariable> step(DoubleVariable currentCommunicationPoint, DoubleVariable communicationStepSize); - List getPorts(); + List> getPorts(); /** * Get ports by name @@ -588,7 +590,7 @@ Map.Entry, DoubleVariable> step(DoubleVariable currentComm * @param names * @return */ - List getPorts(String... names); + List> getPorts(String... names); /** * Get ports by ref val @@ -596,7 +598,7 @@ Map.Entry, DoubleVariable> step(DoubleVariable currentComm * @param valueReferences * @return */ - List getPorts(int... valueReferences); + List> getPorts(int... valueReferences); /** * Get port by name @@ -604,7 +606,7 @@ Map.Entry, DoubleVariable> step(DoubleVariable currentComm * @param name * @return */ - Port getPort(String name); + Port getPort(String name); /** * Get port by ref val @@ -612,7 +614,7 @@ Map.Entry, DoubleVariable> step(DoubleVariable currentComm * @param valueReference * @return */ - Port getPort(int valueReference); + Port getPort(int valueReference); /** * Get port values aka fmiGet @@ -620,16 +622,16 @@ Map.Entry, DoubleVariable> step(DoubleVariable currentComm * @param ports * @return */ - Map> get(Port... ports); + Map, ? extends Variable> get(Port... ports); - Map> get(Scope scope, Port... ports); + Map, ? extends Variable> get(Scope scope, Port... ports); /** * Get all (linked) port values * * @return */ - Map> get(); + Map, ? extends Variable> get(); /** * get filter by value reference @@ -637,7 +639,7 @@ Map.Entry, DoubleVariable> step(DoubleVariable currentComm * @param valueReferences * @return */ - Map> get(int... valueReferences); + Map, ? extends Variable> get(int... valueReferences); /** * Get filter by names @@ -645,17 +647,17 @@ Map.Entry, DoubleVariable> step(DoubleVariable currentComm * @param names * @return */ - Map> get(String... names); + Map, ? extends Variable> get(String... names); - Map> getAndShare(String... names); + Map, ? extends Variable> getAndShare(String... names); - Map> getAndShare(Port... ports); + Map, ? extends Variable> getAndShare(Port... ports); - Map> getAndShare(); + Map, ? extends Variable> getAndShare(); Variable getShared(String name); - Variable getShared(Port port); + Variable getShared(Port port); /** * Get the value of a single port @@ -665,36 +667,36 @@ Map.Entry, DoubleVariable> step(DoubleVariable currentComm */ Variable getSingle(String name); - Variable getSingle(Port port); + Variable getSingle(Port port); - void set(Scope scope, PortValueMap value); + void set(Scope scope, PortValueMap value); - void set(Scope scope, PortVariableMap value); + void set(Scope scope, PortVariableMap value); /** * Set port values (if ports is not from this fmu then the links are used to remap) * * @param value */ - void set(PortValueMap value); + void set(PortValueMap value); - void set(Port port, Value value); + void set(Port port, Value value); - void set(Port port, Variable value); + void set(Port port, Variable value); - void set(Scope scope, Port port, Variable value); + void set(Scope scope, Port port, Variable value); - void set(PortVariableMap value); + void set(PortVariableMap value); /** * Set this fmu port by name and link */ - void setLinked(Scope scope, Port... filterPorts); + void setLinked(Scope scope, Port... filterPorts); void setLinked(); - void setLinked(Port... filterPorts); + void setLinked(Port... filterPorts); void setLinked(String... filterNames); @@ -720,7 +722,7 @@ Map.Entry, DoubleVariable> step(DoubleVariable currentComm * * @param values */ - void share(Map> values); + void share(Map, ? extends Variable> values); /** * Makes the value publicly available to all linked connections. On next set these ports will be resolved to the values given for @@ -728,7 +730,7 @@ Map.Entry, DoubleVariable> step(DoubleVariable currentComm * * @param value */ - void share(Port port, Variable value); + void share(Port port, Variable value); /** * Get the current state @@ -744,17 +746,84 @@ Map.Entry, DoubleVariable> step(DoubleVariable currentComm */ StateVariable getState(Scope scope) throws XPathExpressionException; - - interface PortVariableMap extends Map> { + interface PortVariableMap extends Map, Variable> { } - interface PortValueMap extends Map> { + interface PortValueMap extends Map, Value> { } - interface PortExpressionValueMap extends Map { + interface PortExpressionValueMap extends Map, ExpressionValue> { } } + /** + * Simulation instance for FMI3 + * + * @param building block + * @param fmi3 scalar variable type + */ + interface Fmi3InstanceVariable extends FmiSimulationInstance { + + + void setupExperiment(DoubleVariable startTime, DoubleVariable endTime, BoolVariable endTimeDefined, Double tolerance); + + void setupExperiment(double startTime, Double endTime, Double tolerance); + + void enterInitializationMode(boolean toleranceDefined, double tolerance, double startTime, boolean stopTimeDefined, double stopTime); + + void exitInitializationMode(); + + void setupExperiment(Scope scope, DoubleVariable startTime, DoubleVariable endTime, BoolVariable endTimeDefined, + Double tolerance); + + void setupExperiment(Scope scope, double startTime, Double endTime, Double tolerance); + + void enterInitializationMode(Scope scope, boolean toleranceDefined, double tolerance, double startTime, boolean stopTimeDefined, + double stopTime); + + void exitInitializationMode(Scope scope); + + void terminate(Scope scope); + + void terminate(); + + + } + + /** + * Interface for an fmi compoennt. + *

+ * Note that all methods that do not take a scope uses the builders dynamic scope and adds the underlying instructions int he active scope. + * + * @param building block + * @param fmi2 scalar variable type + */ + interface Fmi2ComponentVariable extends FmiSimulationInstance { + + void setDebugLogging(List categories, boolean enableLogging); + + void setupExperiment(DoubleVariable startTime, DoubleVariable endTime, BoolVariable endTimeDefined, Double tolerance); + + void setupExperiment(double startTime, Double endTime, Double tolerance); + + void enterInitializationMode(); + + void exitInitializationMode(); + + void setupExperiment(Scope scope, DoubleVariable startTime, DoubleVariable endTime, BoolVariable endTimeDefined, + Double tolerance); + + void setupExperiment(Scope scope, double startTime, Double endTime, Double tolerance); + + void enterInitializationMode(Scope scope); + + void exitInitializationMode(Scope scope); + + void terminate(Scope scope); + + void terminate(); + } + interface Variable { String getName(); diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/FromMaBLToMaBLAPI.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/FromMaBLToMaBLAPI.java index 99b8cfa4f..0678093c6 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/FromMaBLToMaBLAPI.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/FromMaBLToMaBLAPI.java @@ -6,9 +6,12 @@ import org.intocps.maestro.framework.core.*; import org.intocps.maestro.framework.fmi2.ComponentInfo; import org.intocps.maestro.framework.fmi2.Fmi2SimulationEnvironment; +import org.intocps.maestro.framework.fmi2.InstanceInfo; import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; import org.intocps.maestro.framework.fmi2.api.mabl.variables.ComponentVariableFmi2Api; import org.intocps.maestro.framework.fmi2.api.mabl.variables.FmuVariableFmi2Api; +import org.intocps.maestro.framework.fmi2.api.mabl.variables.FmuVariableFmi3Api; +import org.intocps.maestro.framework.fmi2.api.mabl.variables.InstanceVariableFmi3Api; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -79,6 +82,54 @@ public static Map.Entry getComponentVariableFr } } + public static Map.Entry getInstanceVariableFrom(MablApiBuilder builder, PExp exp, + Fmi2SimulationEnvironment env, + String environmentComponentName) throws IllegalAccessException, XPathExpressionException, InvocationTargetException { + if (exp instanceof AIdentifierExp) { + String componentName = ((AIdentifierExp) exp).getName().getText(); + + FrameworkUnitInfo inst = env.getInstanceByLexName(environmentComponentName); + if (inst instanceof InstanceInfo) { + + + InstanceInfo instance = (InstanceInfo) inst; + ModelDescriptionContext3 modelDescriptionContext = new ModelDescriptionContext3(instance.getModelDescription()); + + //This dummy statement is removed later. It ensures that the share variables are added to the root scope. + PStm dummyStm = newABlockStm(); + builder.getDynamicScope().add(dummyStm); + + FmuVariableFmi3Api fmu = + new FmuVariableFmi3Api(instance.fmuIdentifier, builder, modelDescriptionContext, dummyStm, newANameType("FMI3"), + builder.getDynamicScope().getActiveScope(), builder.getDynamicScope(), null, + new AIdentifierExp(new LexIdentifier(instance.fmuIdentifier.replace("{", "").replace("}", ""), null))); + + InstanceVariableFmi3Api a; + if (environmentComponentName == null) { + a = new InstanceVariableFmi3Api(dummyStm, fmu, componentName, modelDescriptionContext, builder, + builder.getDynamicScope().getActiveScope(), null, newAIdentifierExp(componentName)); + } else { + a = new InstanceVariableFmi3Api(dummyStm, fmu, componentName, modelDescriptionContext, builder, + builder.getDynamicScope().getActiveScope(), null, newAIdentifierExp(componentName), environmentComponentName); + } + List variablesToLog = null; + if (environmentComponentName == null) { + variablesToLog = env.getVariablesToLog(componentName); + } else { + variablesToLog = env.getVariablesToLog(environmentComponentName); + } + a.setVariablesToLog(variablesToLog.stream().filter(org.intocps.maestro.framework.fmi2.RelationVariable.class::isInstance) + .map(org.intocps.maestro.framework.fmi2.RelationVariable.class::cast).collect(Collectors.toList())); + + return Map.entry(componentName, a); + } else { + throw new RuntimeException("instance is not an fmi2 component: " + componentName); + } + } else { + throw new RuntimeException("exp is not of type AIdentifierExp, but of type: " + exp.getClass()); + } + } + public static void createBindings(Map instances, ISimulationEnvironment env) throws Fmi2Builder.Port.PortLinkException { for (Map.Entry entry : instances.entrySet()) { @@ -120,6 +171,47 @@ public static void createBindings(Map instance } + public static void createBindings3(Map instances, + ISimulationEnvironment env) throws Fmi2Builder.Port.PortLinkException { + for (Map.Entry entry : instances.entrySet()) { + java.util.Set relations = getRelations3(entry, env); + for (IRelation relation : relations.stream().filter(x -> x.getDirection() == Fmi2SimulationEnvironment.Relation.Direction.OutputToInput && + x.getOrigin() == Fmi2SimulationEnvironment.Relation.InternalOrExternal.External).collect(Collectors.toList())) { + + for (IVariable targetVar : relation.getTargets().values()) { + String targetName = targetVar.getScalarVariable().getInstance().getText(); + if (instances.containsKey(targetName) || + instances.values().stream().anyMatch(x -> x.getEnvironmentName().equalsIgnoreCase(targetName))) { + InstanceVariableFmi3Api instance = instances.get(targetName); + if (instance == null) { + Optional instanceOpt = + instances.values().stream().filter(x -> x.getEnvironmentName().equalsIgnoreCase(targetName)).findFirst(); + if (instanceOpt.isPresent()) { + instance = instanceOpt.get(); + } + } + + PortFmi3Api targetPort = instance.getPort(targetVar.getScalarVariable().getName()); + + String sourcePortName = relation.getSource().getScalarVariable().getName(); + if (targetPort != null) { + entry.getValue().getPort(sourcePortName).linkTo(targetPort); + } else { + //error port not found in target var + logger.warn("Failed to find port '{}' on instance '{}' required by relational '{}' ", sourcePortName, targetName, + relation); + } + } else { + logger.warn( + "Failed to find instance required by relational information from simulation env. Missing '{}' in relation " + "{}", + targetName, relation); + } + } + } + } + + } + private static Set getRelations(Map.Entry entry, ISimulationEnvironment env) { if (entry.getValue().getEnvironmentName() != entry.getKey()) { return env.getRelations(entry.getValue().getEnvironmentName()); @@ -128,6 +220,14 @@ private static Set getRelations(Map.Entry getRelations3(Map.Entry entry, ISimulationEnvironment env) { + if (entry.getValue().getEnvironmentName() != entry.getKey()) { + return env.getRelations(entry.getValue().getEnvironmentName()); + } else { + return env.getRelations(entry.getKey()); + } + } + public static Map getComponentVariablesFrom(MablApiBuilder builder, PExp exp, Fmi2SimulationEnvironment env) throws IllegalAccessException, XPathExpressionException, InvocationTargetException { diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/PortFmi2Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/PortFmi2Api.java index 208f2fe0c..bc2cd0fd6 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/PortFmi2Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/PortFmi2Api.java @@ -11,7 +11,7 @@ import static org.intocps.maestro.ast.MableAstFactory.*; -public class PortFmi2Api implements Fmi2Builder.Port { +public class PortFmi2Api implements Fmi2Builder.Port { public final ComponentVariableFmi2Api aMablFmi2ComponentAPI; public final Fmi2ModelDescription.ScalarVariable scalarVariable; @@ -55,6 +55,17 @@ public PType getType() { } } + @Override + public String getQualifiedName() { + return this.aMablFmi2ComponentAPI.getOwner().getFmuIdentifier() + "." + this.aMablFmi2ComponentAPI.getEnvironmentName() + "." + + this.getName(); + } + + @Override + public Fmi2ModelDescription.ScalarVariable getSourceObject() { + return this.scalarVariable; + } + @Override public String getName() { return this.scalarVariable.getName(); @@ -67,7 +78,7 @@ public Long getPortReferenceValue() { @Override - public void linkTo(Fmi2Builder.Port... receivers) throws PortLinkException { + public void linkTo(Fmi2Builder.Port... receivers) throws PortLinkException { if (receivers == null || receivers.length == 0) { return; @@ -77,7 +88,7 @@ public void linkTo(Fmi2Builder.Port... receivers) throws PortLinkException { throw new PortLinkException("Can only link output ports. This port is: " + this.scalarVariable.causality, this); } - for (Fmi2Builder.Port receiver : receivers) { + for (Fmi2Builder.Port receiver : receivers) { PortFmi2Api receiverPort = (PortFmi2Api) receiver; if (receiverPort.scalarVariable.causality != Fmi2ModelDescription.Causality.Input) { @@ -129,8 +140,7 @@ public String toLexName() { } public String getMultiModelScalarVariableName() { - return this.aMablFmi2ComponentAPI.getOwner().getFmuIdentifier() + "." + this.aMablFmi2ComponentAPI.getEnvironmentName() + "." + - this.getName(); + return getQualifiedName(); } public String getMultiModelScalarVariableNameWithoutFmu() { diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/PortFmi3Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/PortFmi3Api.java index b92a01244..69863a1da 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/PortFmi3Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/PortFmi3Api.java @@ -14,7 +14,7 @@ import static org.intocps.maestro.ast.MableAstFactory.*; -public class PortFmi3Api implements Fmi2Builder.Port { +public class PortFmi3Api implements Fmi2Builder.Port { public final InstanceVariableFmi3Api aMablFmi3InstanceAPI; public final Fmi3ModelDescription.Fmi3ScalarVariable scalarVariable; @@ -59,6 +59,17 @@ public PType getType() { } } + @Override + public String getQualifiedName() { + return this.aMablFmi3InstanceAPI.getOwner().getFmuIdentifier() + "." + this.aMablFmi3InstanceAPI.getEnvironmentName() + "." + + this.getName(); + } + + @Override + public Fmi3ModelDescription.Fmi3ScalarVariable getSourceObject() { + return this.scalarVariable; + } + @Override public String getName() { return this.scalarVariable.getVariable().getName(); @@ -71,7 +82,7 @@ public Long getPortReferenceValue() { @Override - public void linkTo(Fmi2Builder.Port... receivers) throws PortLinkException { + public void linkTo(Fmi2Builder.Port... receivers) throws PortLinkException { if (receivers == null || receivers.length == 0) { return; diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/PortValueExpresssionMapImpl.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/PortValueExpresssionMapImpl.java index 24738ec65..21eb559fa 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/PortValueExpresssionMapImpl.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/PortValueExpresssionMapImpl.java @@ -5,7 +5,7 @@ import java.util.HashMap; import java.util.Map; -public class PortValueExpresssionMapImpl extends HashMap implements Fmi2Builder.Fmi2ComponentVariable.PortExpressionValueMap { +public class PortValueExpresssionMapImpl extends HashMap, Fmi2Builder.ExpressionValue> implements Fmi2Builder.Fmi2ComponentVariable.PortExpressionValueMap { public PortValueExpresssionMapImpl(int initialCapacity, float loadFactor) { super(initialCapacity, loadFactor); } @@ -17,7 +17,7 @@ public PortValueExpresssionMapImpl(int initialCapacity) { public PortValueExpresssionMapImpl() { } - public PortValueExpresssionMapImpl(Map m) { + public PortValueExpresssionMapImpl(Map, ? extends Fmi2Builder.ExpressionValue> m) { super(m); } } diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/PortValueMapImpl.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/PortValueMapImpl.java index 03852dbda..2a05839eb 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/PortValueMapImpl.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/PortValueMapImpl.java @@ -5,7 +5,7 @@ import java.util.HashMap; import java.util.Map; -public class PortValueMapImpl extends HashMap> implements Fmi2Builder.Fmi2ComponentVariable.PortValueMap { +public class PortValueMapImpl extends HashMap, Fmi2Builder.Value> implements Fmi2Builder.Fmi2ComponentVariable.PortValueMap { public PortValueMapImpl(int initialCapacity, float loadFactor) { super(initialCapacity, loadFactor); } @@ -17,7 +17,7 @@ public PortValueMapImpl(int initialCapacity) { public PortValueMapImpl() { } - public PortValueMapImpl(Map> m) { + public PortValueMapImpl(Map, ? extends Fmi2Builder.Value> m) { super(m); } } diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/ComponentVariableFmi2Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/ComponentVariableFmi2Api.java index ead626750..fd212775d 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/ComponentVariableFmi2Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/ComponentVariableFmi2Api.java @@ -7,7 +7,6 @@ import org.intocps.maestro.ast.analysis.DepthFirstAnalysisAdaptor; import org.intocps.maestro.ast.node.*; import org.intocps.maestro.fmi.Fmi2ModelDescription; - import org.intocps.maestro.framework.core.RelationVariable; import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; import org.intocps.maestro.framework.fmi2.api.mabl.*; @@ -34,7 +33,7 @@ @SuppressWarnings("rawtypes") -public class ComponentVariableFmi2Api extends VariableFmi2Api> implements Fmi2Builder.Fmi2ComponentVariable { +public class ComponentVariableFmi2Api extends VariableFmi2Api> implements Fmi2Builder.Fmi2ComponentVariable { final static Logger logger = LoggerFactory.getLogger(ComponentVariableFmi2Api.class); private final static int FMI_OK = 0; private final static int FMI_WARNING = 1; @@ -104,8 +103,8 @@ public void setVariablesToLog(List variablesToLog) { } @Override - public void share(Fmi2Builder.Port port, Fmi2Builder.Variable value) { - Map> map = new HashMap<>(); + public void share(Fmi2Builder.Port port, Fmi2Builder.Variable value) { + Map, Fmi2Builder.Variable> map = new HashMap<>(); map.put(port, value); share(map); } @@ -476,12 +475,13 @@ public Map> getTentative(IMablScope scope, S } @Override - public Map> get(Fmi2Builder.Port... ports) { + public Map> get(Fmi2Builder.Port... ports) { return get(builder.getDynamicScope().getActiveScope(), ports); } @Override - public Map> get(Fmi2Builder.Scope scope, Fmi2Builder.Port... ports) { + public Map> get(Fmi2Builder.Scope scope, + Fmi2Builder.Port... ports) { List selectedPorts; if (ports == null || ports.length == 0) { @@ -666,14 +666,15 @@ public Map> getAndShare(String... names) { } @Override - public Map> getAndShare(Fmi2Builder.Port... ports) { + public Map, ? extends Fmi2Builder.Variable> getAndShare( + Fmi2Builder.Port... ports) { Map> values = get(ports); share(values); return values; } @Override - public Map> getAndShare() { + public Map, ? extends Fmi2Builder.Variable> getAndShare() { Map> values = get(); share(values); return values; @@ -690,7 +691,7 @@ public VariableFmi2Api getShared(Fmi2Builder.Port port) { } @Override - public VariableFmi2Api getSingle(Fmi2Builder.Port port) { + public VariableFmi2Api getSingle(Fmi2Builder.Port port) { return (VariableFmi2Api) this.get(port).entrySet().iterator().next().getValue(); } @@ -752,7 +753,7 @@ public void set(PortExpressionValueMap value) { this.set(builder.getDynamicScope().getActiveScope(), value); } - public void set(Fmi2Builder.Scope scope, PortExpressionValueMap value) { + public void set(Fmi2Builder.Scope scope, PortExpressionValueMap value) { if (value == null || value.isEmpty()) { return; } @@ -766,7 +767,7 @@ public void set(Fmi2Builder.Scope scope, PortExpressionValueMap value) { } @Override - public void set(Fmi2Builder.Scope scope, PortValueMap value) { + public void set(Fmi2Builder.Scope scope, PortValueMap value) { if (value == null || value.isEmpty()) { @@ -798,7 +799,7 @@ public void set(Fmi2Builder.Scope scope, PortValueMap value) { } @Override - public void set(Fmi2Builder.Scope scope, PortVariableMap value) { + public void set(Fmi2Builder.Scope scope, PortVariableMap value) { List selectedPorts; if (value == null || value.isEmpty()) { @@ -963,17 +964,18 @@ public void setDerivatives(ArrayVariableFmi2Api derValInBuf, ArrayVariableFmi2Ap } @Override - public void set(PortValueMap value) { + public void set(PortValueMap value) { set(builder.getDynamicScope(), value); } @Override - public void set(Fmi2Builder.Port port, Fmi2Builder.Variable value) { + public void set(Fmi2Builder.Port port, Fmi2Builder.Variable value) { this.set(new PortVariableMapImpl(Map.of(port, value))); } @Override - public void set(Fmi2Builder.Scope scope, Fmi2Builder.Port port, Fmi2Builder.Variable value) { + public void set(Fmi2Builder.Scope scope, Fmi2Builder.Port port, + Fmi2Builder.Variable value) { this.set(scope, new PortVariableMapImpl(Map.of(port, value))); } @@ -987,12 +989,12 @@ public void set(Fmi2Builder.Port port, Fmi2Builder.Value value) { @Override - public void set(PortVariableMap value) { + public void set(PortVariableMap value) { set(builder.getDynamicScope(), value); } @Override - public void setLinked(Fmi2Builder.Scope scope, Fmi2Builder.Port... filterPorts) { + public void setLinked(Fmi2Builder.Scope scope, Fmi2Builder.Port... filterPorts) { List selectedPorts = ports.stream().filter(isLinked).collect(Collectors.toList()); if (filterPorts != null && filterPorts.length != 0) { @@ -1082,7 +1084,7 @@ public void terminate(Fmi2Builder.Scope scope) { } @Override - public void share(Map> values) { + public void share(Map, ? extends Fmi2Builder.Variable> values) { // Group by the string value of the port type as grouping by the port type itself doesnt utilise equals values.entrySet().stream().collect(Collectors.groupingBy(map -> ((PortFmi2Api) map.getKey()).getType().toString())).entrySet().stream() .forEach(map -> { diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/FmuVariableFmi2Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/FmuVariableFmi2Api.java index 2d1cbee2f..91edabb6b 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/FmuVariableFmi2Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/FmuVariableFmi2Api.java @@ -2,6 +2,7 @@ import org.intocps.maestro.ast.MableAstFactory; import org.intocps.maestro.ast.node.*; +import org.intocps.maestro.fmi.Fmi2ModelDescription; import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; import org.intocps.maestro.framework.fmi2.api.mabl.MablApiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.ModelDescriptionContext; @@ -14,7 +15,7 @@ import static org.intocps.maestro.ast.MableBuilder.call; import static org.intocps.maestro.ast.MableBuilder.newVariable; -public class FmuVariableFmi2Api extends VariableFmi2Api> implements Fmi2Builder.Fmu2Variable { +public class FmuVariableFmi2Api extends VariableFmi2Api> implements Fmi2Builder.Fmu2Variable { private final ModelDescriptionContext modelDescriptionContext; private final MablApiBuilder builder; diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/InstanceVariableFmi3Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/InstanceVariableFmi3Api.java index ea1a2e208..4004d65e7 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/InstanceVariableFmi3Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/InstanceVariableFmi3Api.java @@ -6,7 +6,6 @@ import org.intocps.maestro.ast.analysis.AnalysisException; import org.intocps.maestro.ast.analysis.DepthFirstAnalysisAdaptor; import org.intocps.maestro.ast.node.*; -import org.intocps.maestro.fmi.Fmi2ModelDescription; import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3Causality; import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3TypeEnum; @@ -21,7 +20,6 @@ import org.slf4j.LoggerFactory; import javax.xml.xpath.XPathExpressionException; -import java.lang.reflect.InvocationTargetException; import java.util.*; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Function; @@ -36,7 +34,7 @@ @SuppressWarnings("rawtypes") -public class InstanceVariableFmi3Api extends VariableFmi2Api> implements Fmi2Builder.Fmi2ComponentVariable { +public class InstanceVariableFmi3Api extends VariableFmi2Api> implements Fmi2Builder.Fmi3InstanceVariable { final static Logger logger = LoggerFactory.getLogger(InstanceVariableFmi3Api.class); private final static int FMI_OK = 0; private final static int FMI_WARNING = 1; @@ -87,8 +85,7 @@ public InstanceVariableFmi3Api(PStm declaration, FmuVariableFmi3Api parent, Stri outputPorts = ports.stream().filter(p -> p.scalarVariable.getVariable().getCausality() == Fmi3Causality.Output) .sorted(Comparator.comparing(PortFmi3Api::getPortReferenceValue)).collect(Collectors.toUnmodifiableList()); - inputPorts = - ports.stream().filter(p -> p.scalarVariable.getVariable().getCausality() == Fmi3Causality.Input) + inputPorts = ports.stream().filter(p -> p.scalarVariable.getVariable().getCausality() == Fmi3Causality.Input) .sorted(Comparator.comparing(PortFmi3Api::getPortReferenceValue)).collect(Collectors.toUnmodifiableList()); this.environmentName = environmentName; @@ -108,8 +105,8 @@ public void setVariablesToLog(List variablesToLog) { } @Override - public void share(Fmi2Builder.Port port, Fmi2Builder.Variable value) { - Map> map = new HashMap<>(); + public void share(Fmi2Builder.Port port, Fmi2Builder.Variable value) { + Map, Fmi2Builder.Variable> map = new HashMap<>(); map.put(port, value); share(map); } @@ -291,8 +288,8 @@ private void setupExperiment(Fmi2Builder.Scope scope, PExp startTime, PExp } @Override - public void enterInitializationMode() { - this.enterInitializationMode(builder.getDynamicScope()); + public void enterInitializationMode(boolean toleranceDefined, double tolerance, double startTime, boolean stopTimeDefined, double stopTime) { + this.enterInitializationMode(builder.getDynamicScope(), toleranceDefined, tolerance, startTime, stopTimeDefined, stopTime); } @@ -314,7 +311,8 @@ public void setupExperiment(Fmi2Builder.Scope scope, double startTime, Dou } @Override - public void enterInitializationMode(Fmi2Builder.Scope scope) { + public void enterInitializationMode(Fmi2Builder.Scope scope, boolean toleranceDefined, double tolerance, double startTime, + boolean stopTimeDefined, double stopTime) { PStm stm = stateTransitionFunction(FmiFunctionType.ENTERINITIALIZATIONMODE); scope.add(stm); if (builder.getSettings().fmiErrorHandlingEnabled) { @@ -480,12 +478,13 @@ public Map> getTentative(IMablScope scope, S } @Override - public Map> get(Fmi2Builder.Port... ports) { + public Map> get(Fmi2Builder.Port... ports) { return get(builder.getDynamicScope().getActiveScope(), ports); } @Override - public Map> get(Fmi2Builder.Scope scope, Fmi2Builder.Port... ports) { + public Map> get(Fmi2Builder.Scope scope, + Fmi2Builder.Port... ports) { List selectedPorts; if (ports == null || ports.length == 0) { @@ -514,22 +513,22 @@ public Map> get(Fmi2Builder.Scope scop PType type; switch (e.getKey()) { -// case Boolean: -// type = new ABooleanPrimitiveType(); -// break; -// case Real: -// type = new ARealNumericPrimitiveType(); -// break; -// case Integer: -// type = new AIntNumericPrimitiveType(); -// break; -// case String: -// type = new AStringPrimitiveType(); -// break; -// case Enumeration: -// throw new RuntimeException("Cannot assign enumeration port type."); -// default: -// throw new RuntimeException("Cannot match port types."); + // case Boolean: + // type = new ABooleanPrimitiveType(); + // break; + // case Real: + // type = new ARealNumericPrimitiveType(); + // break; + // case Integer: + // type = new AIntNumericPrimitiveType(); + // break; + // case String: + // type = new AStringPrimitiveType(); + // break; + // case Enumeration: + // throw new RuntimeException("Cannot assign enumeration port type."); + // default: + // throw new RuntimeException("Cannot match port types."); default: type = new AIntNumericPrimitiveType(); // TODO For now for testing } @@ -565,77 +564,77 @@ public Map> get(Fmi2Builder.Scope scop public Map>> getDerivatives(List ports, Fmi2Builder.Scope scope) { Map>> derivativePortsToReturn = new HashMap<>(); -// // If any target ports exists that can interpolate the port is also linked and derivatives should be retrieved. -// // TODO: interpolation for FMI3? -// List portsLinkedToTargetsThatInterpolates = ports.stream().filter(p1 -> p1.getTargetPorts().stream().anyMatch(p2 -> { -// try { -// return p2.aMablFmi3InstanceAPI.getModelDescription().getCanInterpolateInputs(); -// } catch (XPathExpressionException e) { -// throw new RuntimeException("Exception occurred when accessing modeldescription: ", e); -// } -// })).collect(Collectors.toList()); -// -// try { -// int maxOutputDerOrder = modelDescriptionContext.getModelDescription().getMaxOutputDerivativeOrder(); -// if (portsLinkedToTargetsThatInterpolates.size() > 0 && maxOutputDerOrder > 0) { -// -// // Find derivative ports -// List derivativePorts = new ArrayList<>(); -// modelDescriptionContext.getModelDescription().getDerivativeToDerivativeSourceMap().entrySet().stream() -// .filter(entry -> portsLinkedToTargetsThatInterpolates.stream() -// .anyMatch(p -> p.getPortReferenceValue().equals(entry.getKey().getVariable().getValueReference()))).forEach(e -> -// // Find the PortFmi3Api representation of the scalarvariable derivative port. -// getPorts().stream().filter(p -> p.getPortReferenceValue().equals(e.getValue().getVariable().getValueReference())).findAny() -// .ifPresent(derivativePorts::add)); -// -// if (derivativePorts.size() > 0) { -// // Array size: number of ports for which to get derivatives multiplied the max derivative order. -// int arraySize = derivativePorts.size() * maxOutputDerOrder; -// -// ArrayVariableFmi2Api derValOutBuf = createBuffer(newRealType(), "DVal_OUT", arraySize, getDeclaredScope()); -// ArrayVariableFmi2Api derOrderOutBuf = createBuffer(newIntType(), "DOrder_OUT", arraySize, getDeclaredScope()); -// ArrayVariableFmi2Api derRefOutBuf = createBuffer(newUIntType(), "DRef_OUT", arraySize, getDeclaredScope()); -// -// // Loop arrays and assign derivative value reference and derivative order. -// // E.g for two ports with and a max derivative order of two: derRefOutBuf = [derPortRef1, derPortRef1, derPortRef2,derPortRef2], -// // derOrderOutBuf = [1,2,1,2] -// PortFmi3Api derivativePort = null; -// for (int arrayIndex = 0, portIndex = 0, order = 1; arrayIndex < arraySize; arrayIndex++) { -// // Switch to the next port when we have traversed a length of 'maxOutputDerOrder' in the arrays and reset order. -// if (arrayIndex % maxOutputDerOrder == 0) { -// order = 1; -// derivativePort = derivativePorts.get(portIndex); -// derivativePortsToReturn.put(derivativePort, derValOutBuf.items().subList(arrayIndex, arrayIndex + maxOutputDerOrder)); -// portIndex++; -// } -// -// PStateDesignator dRefDesignator = derRefOutBuf.items().get(arrayIndex).getDesignator().clone(); -// scope.add(newAAssignmentStm(dRefDesignator, newAIntLiteralExp(derivativePort.getPortReferenceValue().intValue()))); -// -// PStateDesignator derOrderDesignator = derOrderOutBuf.items().get(arrayIndex).getDesignator().clone(); -// scope.add(newAAssignmentStm(derOrderDesignator, newAIntLiteralExp(order))); -// order++; -// } -// -// // Create assignment statement which assigns derivatives to derValOutBuf by calling getRealOutputDerivatives with -// // derRefOutBuf, arraySize and derOrderOutBuf. -// PStm AStm = newAAssignmentStm(builder.getGlobalFmiStatus().getDesignator().clone(), -// call(this.getReferenceExp().clone(), createFunctionName(FmiFunctionType.GETREALOUTPUTDERIVATIVES), -// derRefOutBuf.getReferenceExp().clone(), newAUIntLiteralExp((long) arraySize), -// derOrderOutBuf.getReferenceExp().clone(), derValOutBuf.getReferenceExp().clone())); -// scope.add(AStm); -// -// // If enabled handle potential errors from calling getRealOutputDerivatives -// if (builder.getSettings().fmiErrorHandlingEnabled) { -// FmiStatusErrorHandlingBuilder.generate(builder, createFunctionName(FmiFunctionType.GETREALOUTPUTDERIVATIVES), this, -// (IMablScope) scope, MablApiBuilder.FmiStatus.FMI_ERROR, MablApiBuilder.FmiStatus.FMI_FATAL); -// } -// } -// } -// // TODO InvocationTargetException | IllegalAccessException ? -// } catch (XPathExpressionException e) { -// throw new RuntimeException("Exception occurred when retrieving derivatives: ", e); -// } + // // If any target ports exists that can interpolate the port is also linked and derivatives should be retrieved. + // // TODO: interpolation for FMI3? + // List portsLinkedToTargetsThatInterpolates = ports.stream().filter(p1 -> p1.getTargetPorts().stream().anyMatch(p2 -> { + // try { + // return p2.aMablFmi3InstanceAPI.getModelDescription().getCanInterpolateInputs(); + // } catch (XPathExpressionException e) { + // throw new RuntimeException("Exception occurred when accessing modeldescription: ", e); + // } + // })).collect(Collectors.toList()); + // + // try { + // int maxOutputDerOrder = modelDescriptionContext.getModelDescription().getMaxOutputDerivativeOrder(); + // if (portsLinkedToTargetsThatInterpolates.size() > 0 && maxOutputDerOrder > 0) { + // + // // Find derivative ports + // List derivativePorts = new ArrayList<>(); + // modelDescriptionContext.getModelDescription().getDerivativeToDerivativeSourceMap().entrySet().stream() + // .filter(entry -> portsLinkedToTargetsThatInterpolates.stream() + // .anyMatch(p -> p.getPortReferenceValue().equals(entry.getKey().getVariable().getValueReference()))).forEach(e -> + // // Find the PortFmi3Api representation of the scalarvariable derivative port. + // getPorts().stream().filter(p -> p.getPortReferenceValue().equals(e.getValue().getVariable().getValueReference())).findAny() + // .ifPresent(derivativePorts::add)); + // + // if (derivativePorts.size() > 0) { + // // Array size: number of ports for which to get derivatives multiplied the max derivative order. + // int arraySize = derivativePorts.size() * maxOutputDerOrder; + // + // ArrayVariableFmi2Api derValOutBuf = createBuffer(newRealType(), "DVal_OUT", arraySize, getDeclaredScope()); + // ArrayVariableFmi2Api derOrderOutBuf = createBuffer(newIntType(), "DOrder_OUT", arraySize, getDeclaredScope()); + // ArrayVariableFmi2Api derRefOutBuf = createBuffer(newUIntType(), "DRef_OUT", arraySize, getDeclaredScope()); + // + // // Loop arrays and assign derivative value reference and derivative order. + // // E.g for two ports with and a max derivative order of two: derRefOutBuf = [derPortRef1, derPortRef1, derPortRef2,derPortRef2], + // // derOrderOutBuf = [1,2,1,2] + // PortFmi3Api derivativePort = null; + // for (int arrayIndex = 0, portIndex = 0, order = 1; arrayIndex < arraySize; arrayIndex++) { + // // Switch to the next port when we have traversed a length of 'maxOutputDerOrder' in the arrays and reset order. + // if (arrayIndex % maxOutputDerOrder == 0) { + // order = 1; + // derivativePort = derivativePorts.get(portIndex); + // derivativePortsToReturn.put(derivativePort, derValOutBuf.items().subList(arrayIndex, arrayIndex + maxOutputDerOrder)); + // portIndex++; + // } + // + // PStateDesignator dRefDesignator = derRefOutBuf.items().get(arrayIndex).getDesignator().clone(); + // scope.add(newAAssignmentStm(dRefDesignator, newAIntLiteralExp(derivativePort.getPortReferenceValue().intValue()))); + // + // PStateDesignator derOrderDesignator = derOrderOutBuf.items().get(arrayIndex).getDesignator().clone(); + // scope.add(newAAssignmentStm(derOrderDesignator, newAIntLiteralExp(order))); + // order++; + // } + // + // // Create assignment statement which assigns derivatives to derValOutBuf by calling getRealOutputDerivatives with + // // derRefOutBuf, arraySize and derOrderOutBuf. + // PStm AStm = newAAssignmentStm(builder.getGlobalFmiStatus().getDesignator().clone(), + // call(this.getReferenceExp().clone(), createFunctionName(FmiFunctionType.GETREALOUTPUTDERIVATIVES), + // derRefOutBuf.getReferenceExp().clone(), newAUIntLiteralExp((long) arraySize), + // derOrderOutBuf.getReferenceExp().clone(), derValOutBuf.getReferenceExp().clone())); + // scope.add(AStm); + // + // // If enabled handle potential errors from calling getRealOutputDerivatives + // if (builder.getSettings().fmiErrorHandlingEnabled) { + // FmiStatusErrorHandlingBuilder.generate(builder, createFunctionName(FmiFunctionType.GETREALOUTPUTDERIVATIVES), this, + // (IMablScope) scope, MablApiBuilder.FmiStatus.FMI_ERROR, MablApiBuilder.FmiStatus.FMI_FATAL); + // } + // } + // } + // // TODO InvocationTargetException | IllegalAccessException ? + // } catch (XPathExpressionException e) { + // throw new RuntimeException("Exception occurred when retrieving derivatives: ", e); + // } return derivativePortsToReturn; } @@ -672,14 +671,15 @@ public Map> getAndShare(String... names) { } @Override - public Map> getAndShare(Fmi2Builder.Port... ports) { + public Map, ? extends Fmi2Builder.Variable> getAndShare( + Fmi2Builder.Port... ports) { Map> values = get(ports); share(values); return values; } @Override - public Map> getAndShare() { + public Map, ? extends Fmi2Builder.Variable> getAndShare() { Map> values = get(); share(values); return values; @@ -696,7 +696,7 @@ public VariableFmi2Api getShared(Fmi2Builder.Port port) { } @Override - public VariableFmi2Api getSingle(Fmi2Builder.Port port) { + public VariableFmi2Api getSingle(Fmi2Builder.Port port) { return (VariableFmi2Api) this.get(port).entrySet().iterator().next().getValue(); } @@ -746,13 +746,12 @@ public VariableFmi2Api getSingle(String name) { } - public void set(Fmi2Builder.Port p, Fmi2Builder.ExpressionValue v) { this.set(new PortValueExpresssionMapImpl(Map.of(p, v))); ; } - public void set(Fmi2Builder.Scope scope, Fmi2Builder.Port p, Fmi2Builder.ExpressionValue v) { + public void set(Fmi2Builder.Scope scope, Fmi2Builder.Port p, Fmi2Builder.ExpressionValue v) { this.set(scope, new PortValueMapImpl(Map.of(p, v))); } @@ -760,7 +759,7 @@ public void set(PortExpressionValueMap value) { this.set(builder.getDynamicScope().getActiveScope(), value); } - public void set(Fmi2Builder.Scope scope, PortExpressionValueMap value) { + public void set(Fmi2Builder.Scope scope, PortExpressionValueMap value) { if (value == null || value.isEmpty()) { return; } @@ -774,7 +773,7 @@ public void set(Fmi2Builder.Scope scope, PortExpressionValueMap value) { } @Override - public void set(Fmi2Builder.Scope scope, PortValueMap value) { + public void set(Fmi2Builder.Scope scope, PortValueMap value) { if (value == null || value.isEmpty()) { @@ -806,7 +805,7 @@ public void set(Fmi2Builder.Scope scope, PortValueMap value) { } @Override - public void set(Fmi2Builder.Scope scope, PortVariableMap value) { + public void set(Fmi2Builder.Scope scope, PortVariableMap value) { List selectedPorts; if (value == null || value.isEmpty()) { @@ -823,8 +822,7 @@ public void set(Fmi2Builder.Scope scope, PortVariableMap valu public void set(Fmi2Builder.Scope scope, List selectedPorts, Function> portToValue) { Set selectedPortsAsStrings = selectedPorts.stream() - .map(p -> p.getName() + "-" + p.aMablFmi3InstanceAPI.getName() + "-" + p.aMablFmi3InstanceAPI.getOwner().getName()) - .collect(toSet()); + .map(p -> p.getName() + "-" + p.aMablFmi3InstanceAPI.getName() + "-" + p.aMablFmi3InstanceAPI.getOwner().getName()).collect(toSet()); selectedPortsAsStrings.removeAll( ports.stream().map(p -> p.getName() + "-" + p.aMablFmi3InstanceAPI.getName() + "-" + p.aMablFmi3InstanceAPI.getOwner().getName()) .collect(toSet())); @@ -867,82 +865,82 @@ public void set(Fmi2Builder.Scope scope, List selectedPorts, // TODO: IntermediateUpdateMode instead of CanInterpolateInputs? // TODO: commented out for no so it compiles -// try { -// if (builder.getSettings().setGetDerivatives && modelDescriptionContext.getModelDescription().getCanInterpolateInputs() && -// type.equals(new ARealNumericPrimitiveType())) { -// setDerivativesForSharedPorts(value, scope); -// } -// } catch (XPathExpressionException e) { -// throw new RuntimeException("Exception occurred when when setting derivatives.", e); -// } + // try { + // if (builder.getSettings().setGetDerivatives && modelDescriptionContext.getModelDescription().getCanInterpolateInputs() && + // type.equals(new ARealNumericPrimitiveType())) { + // setDerivativesForSharedPorts(value, scope); + // } + // } catch (XPathExpressionException e) { + // throw new RuntimeException("Exception occurred when when setting derivatives.", e); + // } }); } -// -// /** -// * @param ports The ports for which derivative should be set from SHARED derivative ports -// * @param scope The builder scope -// */ -// private void setDerivativesForSharedPorts(List ports, Fmi2Builder.Scope scope) { -// // Find all ports for which derivatives should be passed together with the derivatives and their order. -// LinkedHashMap> mapPortsToDerPortsWithOrder = -// ports.stream().filter(port -> port.getSourcePort() != null).map(port -> { -// try { -// Map.Entry innerEntry; -// // Find if port is in map of derivatives -// Optional> derivativePortEntry = -// port.getSourcePort().aMablFmi3InstanceAPI.getModelDescription().getDerivativeToDerivativeSourceMap().entrySet().stream() -// .filter(e -> e.getKey().getVariable().getValueReferenceAsLong().equals(port.getSourcePort().getPortReferenceValue())).findAny(); -// -// -// if (derivativePortEntry.isPresent()) { -// // Find PortFmi3Api value of the scalarvariable derivative port and the components max output derivative. -// innerEntry = Map.entry(port.getSourcePort().aMablFmi3InstanceAPI.getPort((int) -// derivativePortEntry.get().getValue().getVariable().getValueReferenceAsLong()), -// port.getSourcePort().aMablFmi3InstanceAPI.getModelDescription().getMaxOutputDerivativeOrder()); -// return Map.entry(port, innerEntry); -// } -// -// return null; -// } catch (XPathExpressionException | IllegalAccessException | InvocationTargetException e) { -// throw new RuntimeException("Exception occurred when accessing modeldescription: ", e); -// } -// }).filter(Objects::nonNull).collect(LinkedHashMap::new, (map, item) -> map.put(item.getKey(), item.getValue()), // Accumulator -// Map::putAll); -// -// if (mapPortsToDerPortsWithOrder.size() > 0) { -// // Get the total array size as the sum of derivative orders. -// int arraySize = mapPortsToDerPortsWithOrder.values().stream().mapToInt(Map.Entry::getValue).sum(); -// -// // Create input arrays -// ArrayVariableFmi2Api derValInBuf = createBuffer(newRealType(), "DVal_IN", arraySize, getDeclaredScope()); -// ArrayVariableFmi2Api derOrderInBuf = createBuffer(newIntType(), "DOrder_IN", arraySize, getDeclaredScope()); -// ArrayVariableFmi2Api derRefInBuf = createBuffer(newUIntType(), "DRef_IN", arraySize, getDeclaredScope()); -// -// // Loop through arrays and assign the port reference, derivative order and derivative value. -// // E.g: for two derivative ports Out1 (linked to In1) and Out2 (linked to In2) with a max derivative order of 2 and 1: derValInBuf = [der -// // (Out1), der(der(Out1)),der(Out2))], derOrderInBuf = [1,2,1], derRefInBuf = [In1, In1, In2] -// int arrayIndex = 0; -// for (Map.Entry> entry : mapPortsToDerPortsWithOrder.entrySet()) { -// PortFmi3Api port = entry.getKey(); -// int maxOrder = entry.getValue().getValue(); -// for (int order = 1; order <= maxOrder; order++, arrayIndex++) { -// // Assign to array variables -// PStateDesignator derRefDesignator = derRefInBuf.items().get(arrayIndex).getDesignator().clone(); -// scope.add(newAAssignmentStm(derRefDesignator, newAIntLiteralExp(port.getPortReferenceValue().intValue()))); -// -// PStateDesignator derOrderDesignator = derOrderInBuf.items().get(arrayIndex).getDesignator().clone(); -// scope.add(newAAssignmentStm(derOrderDesignator, newAIntLiteralExp(order))); -// -// PStateDesignator derValInDesignator = derValInBuf.items().get(arrayIndex).getDesignator().clone(); -// scope.add(newAAssignmentStm(derValInDesignator, -// ((VariableFmi2Api) ((ArrayVariableFmi2Api) entry.getValue().getKey().getSharedAsVariable()).items() -// .get(order - 1)).getReferenceExp().clone())); -// } -// } -// -// setDerivatives(derValInBuf, derOrderInBuf, derRefInBuf, scope); -// } -// } + // + // /** + // * @param ports The ports for which derivative should be set from SHARED derivative ports + // * @param scope The builder scope + // */ + // private void setDerivativesForSharedPorts(List ports, Fmi2Builder.Scope scope) { + // // Find all ports for which derivatives should be passed together with the derivatives and their order. + // LinkedHashMap> mapPortsToDerPortsWithOrder = + // ports.stream().filter(port -> port.getSourcePort() != null).map(port -> { + // try { + // Map.Entry innerEntry; + // // Find if port is in map of derivatives + // Optional> derivativePortEntry = + // port.getSourcePort().aMablFmi3InstanceAPI.getModelDescription().getDerivativeToDerivativeSourceMap().entrySet().stream() + // .filter(e -> e.getKey().getVariable().getValueReferenceAsLong().equals(port.getSourcePort().getPortReferenceValue())).findAny(); + // + // + // if (derivativePortEntry.isPresent()) { + // // Find PortFmi3Api value of the scalarvariable derivative port and the components max output derivative. + // innerEntry = Map.entry(port.getSourcePort().aMablFmi3InstanceAPI.getPort((int) + // derivativePortEntry.get().getValue().getVariable().getValueReferenceAsLong()), + // port.getSourcePort().aMablFmi3InstanceAPI.getModelDescription().getMaxOutputDerivativeOrder()); + // return Map.entry(port, innerEntry); + // } + // + // return null; + // } catch (XPathExpressionException | IllegalAccessException | InvocationTargetException e) { + // throw new RuntimeException("Exception occurred when accessing modeldescription: ", e); + // } + // }).filter(Objects::nonNull).collect(LinkedHashMap::new, (map, item) -> map.put(item.getKey(), item.getValue()), // Accumulator + // Map::putAll); + // + // if (mapPortsToDerPortsWithOrder.size() > 0) { + // // Get the total array size as the sum of derivative orders. + // int arraySize = mapPortsToDerPortsWithOrder.values().stream().mapToInt(Map.Entry::getValue).sum(); + // + // // Create input arrays + // ArrayVariableFmi2Api derValInBuf = createBuffer(newRealType(), "DVal_IN", arraySize, getDeclaredScope()); + // ArrayVariableFmi2Api derOrderInBuf = createBuffer(newIntType(), "DOrder_IN", arraySize, getDeclaredScope()); + // ArrayVariableFmi2Api derRefInBuf = createBuffer(newUIntType(), "DRef_IN", arraySize, getDeclaredScope()); + // + // // Loop through arrays and assign the port reference, derivative order and derivative value. + // // E.g: for two derivative ports Out1 (linked to In1) and Out2 (linked to In2) with a max derivative order of 2 and 1: derValInBuf = [der + // // (Out1), der(der(Out1)),der(Out2))], derOrderInBuf = [1,2,1], derRefInBuf = [In1, In1, In2] + // int arrayIndex = 0; + // for (Map.Entry> entry : mapPortsToDerPortsWithOrder.entrySet()) { + // PortFmi3Api port = entry.getKey(); + // int maxOrder = entry.getValue().getValue(); + // for (int order = 1; order <= maxOrder; order++, arrayIndex++) { + // // Assign to array variables + // PStateDesignator derRefDesignator = derRefInBuf.items().get(arrayIndex).getDesignator().clone(); + // scope.add(newAAssignmentStm(derRefDesignator, newAIntLiteralExp(port.getPortReferenceValue().intValue()))); + // + // PStateDesignator derOrderDesignator = derOrderInBuf.items().get(arrayIndex).getDesignator().clone(); + // scope.add(newAAssignmentStm(derOrderDesignator, newAIntLiteralExp(order))); + // + // PStateDesignator derValInDesignator = derValInBuf.items().get(arrayIndex).getDesignator().clone(); + // scope.add(newAAssignmentStm(derValInDesignator, + // ((VariableFmi2Api) ((ArrayVariableFmi2Api) entry.getValue().getKey().getSharedAsVariable()).items() + // .get(order - 1)).getReferenceExp().clone())); + // } + // } + // + // setDerivatives(derValInBuf, derOrderInBuf, derRefInBuf, scope); + // } + // } /** * If two derivative ports 'Out1' (linked to 'In1') and 'Out2' (linked to 'In2') with a max derivative order of 2 and 1 then derValInBuf = @@ -973,36 +971,36 @@ public void setDerivatives(ArrayVariableFmi2Api derValInBuf, ArrayVariableFmi2Ap } @Override - public void set(PortValueMap value) { + public void set(PortValueMap value) { set(builder.getDynamicScope(), value); } + @Override - public void set(Fmi2Builder.Port port, Fmi2Builder.Variable value) { + public void set(Fmi2Builder.Port port, Fmi2Builder.Variable value) { this.set(new PortVariableMapImpl(Map.of(port, value))); } @Override - public void set(Fmi2Builder.Scope scope, Fmi2Builder.Port port, Fmi2Builder.Variable value) { + public void set(Fmi2Builder.Scope scope, Fmi2Builder.Port port, + Fmi2Builder.Variable value) { this.set(scope, new PortVariableMapImpl(Map.of(port, value))); } @Override - public void set(Fmi2Builder.Port port, Fmi2Builder.Value value) { + public void set(Fmi2Builder.Port port, Fmi2Builder.Value value) { PortValueMap map = new PortValueMapImpl(); map.put(port, value); set(map); - } - @Override - public void set(PortVariableMap value) { + public void set(PortVariableMap value) { set(builder.getDynamicScope(), value); } @Override - public void setLinked(Fmi2Builder.Scope scope, Fmi2Builder.Port... filterPorts) { + public void setLinked(Fmi2Builder.Scope scope, Fmi2Builder.Port... filterPorts) { List selectedPorts = ports.stream().filter(isLinked).collect(Collectors.toList()); if (filterPorts != null && filterPorts.length != 0) { @@ -1043,7 +1041,7 @@ public void setLinked(Fmi2Builder.Scope scope, Fmi2Builder.Port... filterP @Override public void setLinked() { - this.setLinked(dynamicScope, (Fmi2Builder.Port[]) null); + this.setLinked(dynamicScope, (Fmi2Builder.Port[]) null); } @Override @@ -1093,73 +1091,73 @@ public void terminate(Fmi2Builder.Scope scope) { // TODO: implement this from the other share function below. This for now to build. @Override - public void share(Map> values) { + public void share(Map, ? extends Fmi2Builder.Variable> values) { ; } -// @Override -// public void share(Map> values) { -// // Group by the string value of the port type as grouping by the port type itself doesnt utilise equals -// values.entrySet().stream().collect(Collectors.groupingBy(map -> ((PortFmi3Api) map.getKey()).getType().toString())).entrySet().stream() -// .forEach(map -> { -// PType type = ((PortFmi3Api) map.getValue().get(0).getKey()).getType(); -// -// Map data = -// map.getValue().stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); -// -// data.keySet().stream().map(PortFmi3Api.class::cast).sorted(Comparator.comparing(PortFmi3Api::getPortReferenceValue)) -// .forEach(port -> { -// //this is the sorted set of assignments, these can be replaced by a memcopy later -// ArrayVariableFmi2Api buffer = getSharedBuffer(type); -// if (port.getSharedAsVariable() == null) { -// ArrayVariableFmi2Api newBuf = growBuffer(buffer, 1); -// this.setSharedBuffer(newBuf, type); -// -// VariableFmi2Api newShared = newBuf.items().get(newBuf.items().size() - 1); -// port.setSharedAsVariable(newShared); -// } -// -// PStateDesignator designator = port.getSharedAsVariable().getDesignator(); -// builder.getDynamicScope().addAll(BuilderUtil.createTypeConvertingAssignment(builder, dynamicScope, designator.clone(), -// ((VariableFmi2Api) data.get(port)).getReferenceExp().clone(), port.getType(), -// ((VariableFmi2Api) ((VariableFmi2Api) data.get(port))).type)); -// -// -// if (type.equals(new ARealNumericPrimitiveType()) && derivativePortsToShare != null) { -// // Find match a derivativePortsToShare where both port reference and derivative port reference matches. -// derivativePortsToShare.keySet().stream().filter(derivativePort -> { -// try { -// return modelDescriptionContext.getModelDescription().getDerivativesMap().entrySet().stream().anyMatch( -// e -> e.getKey().getValueReference().equals(port.getPortReferenceValue()) && -// e.getValue().getValueReference().equals(derivativePort.getPortReferenceValue())); -// } catch (XPathExpressionException | InvocationTargetException | IllegalAccessException e) { -// throw new RuntimeException( -// "Attempting to obtain shared values from a port that is linked but has no value shared. Share a value " + -// "first. " + port); -// } -// }).findFirst().ifPresent((derivativePort) -> { -// // If the derivative port is not yet shared then get shared derivative buffer, grow it by one and set the port as shared -// // with the new array. -// if (derivativePort.getSharedAsVariable() == null) { -// ArrayVariableFmi2Api sharedDerBuf = growSharedDerBuf(1); -// -// ArrayVariableFmi2Api newSharedArray = -// (ArrayVariableFmi2Api) sharedDerBuf.items().get(sharedDerBuf.items().size() - 1); -// derivativePort.setSharedAsVariable(newSharedArray); -// } -// -// // DerivativePorts.get(derivativePort).size should equal derivativePort.getSharedAsVariable().items().size() as they are -// // both determined by the max derivative order. -// List derivatives = ((ArrayVariableFmi2Api) derivativePort.getSharedAsVariable()).items(); -// for (int i = 0; i < derivatives.size(); i++) { -// PExp val = derivativePortsToShare.get(derivativePort).get(i).getReferenceExp().clone(); -// builder.getDynamicScope().add(newAAssignmentStm(derivatives.get(i).getDesignator().clone(), val)); -// } -// }); -// } -// }); -// }); -// } + // @Override + // public void share(Map> values) { + // // Group by the string value of the port type as grouping by the port type itself doesnt utilise equals + // values.entrySet().stream().collect(Collectors.groupingBy(map -> ((PortFmi3Api) map.getKey()).getType().toString())).entrySet().stream() + // .forEach(map -> { + // PType type = ((PortFmi3Api) map.getValue().get(0).getKey()).getType(); + // + // Map data = + // map.getValue().stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + // + // data.keySet().stream().map(PortFmi3Api.class::cast).sorted(Comparator.comparing(PortFmi3Api::getPortReferenceValue)) + // .forEach(port -> { + // //this is the sorted set of assignments, these can be replaced by a memcopy later + // ArrayVariableFmi2Api buffer = getSharedBuffer(type); + // if (port.getSharedAsVariable() == null) { + // ArrayVariableFmi2Api newBuf = growBuffer(buffer, 1); + // this.setSharedBuffer(newBuf, type); + // + // VariableFmi2Api newShared = newBuf.items().get(newBuf.items().size() - 1); + // port.setSharedAsVariable(newShared); + // } + // + // PStateDesignator designator = port.getSharedAsVariable().getDesignator(); + // builder.getDynamicScope().addAll(BuilderUtil.createTypeConvertingAssignment(builder, dynamicScope, designator.clone(), + // ((VariableFmi2Api) data.get(port)).getReferenceExp().clone(), port.getType(), + // ((VariableFmi2Api) ((VariableFmi2Api) data.get(port))).type)); + // + // + // if (type.equals(new ARealNumericPrimitiveType()) && derivativePortsToShare != null) { + // // Find match a derivativePortsToShare where both port reference and derivative port reference matches. + // derivativePortsToShare.keySet().stream().filter(derivativePort -> { + // try { + // return modelDescriptionContext.getModelDescription().getDerivativesMap().entrySet().stream().anyMatch( + // e -> e.getKey().getValueReference().equals(port.getPortReferenceValue()) && + // e.getValue().getValueReference().equals(derivativePort.getPortReferenceValue())); + // } catch (XPathExpressionException | InvocationTargetException | IllegalAccessException e) { + // throw new RuntimeException( + // "Attempting to obtain shared values from a port that is linked but has no value shared. Share a value " + + // "first. " + port); + // } + // }).findFirst().ifPresent((derivativePort) -> { + // // If the derivative port is not yet shared then get shared derivative buffer, grow it by one and set the port as shared + // // with the new array. + // if (derivativePort.getSharedAsVariable() == null) { + // ArrayVariableFmi2Api sharedDerBuf = growSharedDerBuf(1); + // + // ArrayVariableFmi2Api newSharedArray = + // (ArrayVariableFmi2Api) sharedDerBuf.items().get(sharedDerBuf.items().size() - 1); + // derivativePort.setSharedAsVariable(newSharedArray); + // } + // + // // DerivativePorts.get(derivativePort).size should equal derivativePort.getSharedAsVariable().items().size() as they are + // // both determined by the max derivative order. + // List derivatives = ((ArrayVariableFmi2Api) derivativePort.getSharedAsVariable()).items(); + // for (int i = 0; i < derivatives.size(); i++) { + // PExp val = derivativePortsToShare.get(derivativePort).get(i).getReferenceExp().clone(); + // builder.getDynamicScope().add(newAAssignmentStm(derivatives.get(i).getDesignator().clone(), val)); + // } + // }); + // } + // }); + // }); + // } /** * @param increaseByCount the length of which the outer array should grow diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/PortVariableMapImpl.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/PortVariableMapImpl.java index 27c0cca9a..a84690828 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/PortVariableMapImpl.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/PortVariableMapImpl.java @@ -6,7 +6,8 @@ import java.util.HashMap; import java.util.Map; -public class PortVariableMapImpl extends HashMap> implements Fmi2Builder.Fmi2ComponentVariable.PortVariableMap { +public class PortVariableMapImpl extends HashMap, Fmi2Builder.Variable> implements Fmi2Builder.FmiSimulationInstance.PortVariableMap { public PortVariableMapImpl(int initialCapacity, float loadFactor) { super(initialCapacity, loadFactor); } @@ -18,7 +19,7 @@ public PortVariableMapImpl(int initialCapacity) { public PortVariableMapImpl() { } - public PortVariableMapImpl(Map> m) { + public PortVariableMapImpl(Map, ? extends Fmi2Builder.Variable> m) { super(m); } } diff --git a/frameworks/fmi2api/src/test/java/org/intocps/maestro/framework/fmi2/api/mabl/SetPortsTest.java b/frameworks/fmi2api/src/test/java/org/intocps/maestro/framework/fmi2/api/mabl/SetPortsTest.java index a57a76be2..5c0b6bcaa 100644 --- a/frameworks/fmi2api/src/test/java/org/intocps/maestro/framework/fmi2/api/mabl/SetPortsTest.java +++ b/frameworks/fmi2api/src/test/java/org/intocps/maestro/framework/fmi2/api/mabl/SetPortsTest.java @@ -1,5 +1,6 @@ package org.intocps.maestro.framework.fmi2.api.mabl; +import org.intocps.maestro.fmi.Fmi2ModelDescription; import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.DynamicActiveBuilderScope; import org.intocps.maestro.framework.fmi2.api.mabl.values.PortValueMapImpl; @@ -36,9 +37,10 @@ public void undeclaredPortsTest() throws Exception { controllerInstance.get(controllerInstance.getPorts().stream().map(PortFmi2Api::getName).toArray(String[]::new)); controllerInstance.share(controllerPortMap); - Fmi2Builder.Fmi2ComponentVariable.PortValueMap portsToSet = new PortValueMapImpl(controllerPortMap); + Fmi2Builder.Fmi2ComponentVariable.PortValueMap portsToSet = + new PortValueMapImpl(controllerPortMap); // ASSERT - Assertions.assertThrows(RuntimeException.class,() -> tankInstance.set(portsToSet)); + Assertions.assertThrows(RuntimeException.class, () -> tankInstance.set(portsToSet)); } } diff --git a/maestro/src/main/java/org/intocps/maestro/BuilderHelper.java b/maestro/src/main/java/org/intocps/maestro/BuilderHelper.java index e712c64b1..6e3dafab1 100644 --- a/maestro/src/main/java/org/intocps/maestro/BuilderHelper.java +++ b/maestro/src/main/java/org/intocps/maestro/BuilderHelper.java @@ -9,10 +9,12 @@ import org.intocps.maestro.framework.core.ISimulationEnvironment; import org.intocps.maestro.framework.fmi2.ComponentInfo; import org.intocps.maestro.framework.fmi2.Fmi2SimulationEnvironment; +import org.intocps.maestro.framework.fmi2.InstanceInfo; import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; import org.intocps.maestro.framework.fmi2.api.mabl.FromMaBLToMaBLAPI; import org.intocps.maestro.framework.fmi2.api.mabl.MablApiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.ModelDescriptionContext; +import org.intocps.maestro.framework.fmi2.api.mabl.ModelDescriptionContext3; import org.intocps.maestro.framework.fmi2.api.mabl.variables.*; import org.intocps.maestro.typechecker.TypeComparator; import org.jgrapht.graph.DefaultDirectedGraph; @@ -48,11 +50,13 @@ public BuilderHelper(ACallExp callToBeReplaced, Map typesMap, var graph = buildInstanceMappingGraph(simulationSpecification); Map instances = new HashMap<>(); + Map fmi3Instances = new HashMap<>(); this.variables = callToBeReplaced.getArgs().stream() - .map(exp -> wrapAsVariable(builder, typesMap, simulationEnvironment, typesMap.get(exp), exp, instances, graph)) + .map(exp -> wrapAsVariable(builder, typesMap, simulationEnvironment, typesMap.get(exp), exp, instances, fmi3Instances, graph)) .collect(Collectors.toList()); FromMaBLToMaBLAPI.createBindings(instances, simulationEnvironment); + FromMaBLToMaBLAPI.createBindings3(fmi3Instances, simulationEnvironment); } private static String getLastVertexOfDirectedGraph(DefaultDirectedGraph graph, String startVertex) { @@ -93,7 +97,7 @@ public void caseAInstanceMappingStm(AInstanceMappingStm node, private static Fmi2Builder.Variable wrapAsVariable(MablApiBuilder builder, Map typesMap, ISimulationEnvironment simulationEnvironment, PType type, PExp exp, Map instances, - DefaultDirectedGraph graph) { + Map fmi3Instances, DefaultDirectedGraph graph) { Fmi2SimulationEnvironment env = null; @@ -110,49 +114,72 @@ public void caseAInstanceMappingStm(AInstanceMappingStm node, return new BooleanVariableFmi2Api(null, null, null, null, exp.clone()); } else if (typeComparator.compatible(AStringPrimitiveType.class, type)) { return new StringVariableFmi2Api(null, null, null, null, exp.clone()); - } else if (env != null && type instanceof AModuleType && ((AModuleType) type).getName().getText().equals("FMI2")) { - if (exp instanceof AIdentifierExp) { - String componentName = ((AIdentifierExp) exp).getName().getText(); - - FrameworkUnitInfo instance = env.getInstanceByLexName(componentName); - if (instance instanceof ComponentInfo) { - ModelDescriptionContext modelDescriptionContext = null; - try { - modelDescriptionContext = new ModelDescriptionContext(((ComponentInfo) instance).modelDescription); - } catch (IllegalAccessException | XPathExpressionException | InvocationTargetException e) { - throw new RuntimeException(e); - } + } else if (env != null && type instanceof AModuleType) { + String moduleTypeName = ((AModuleType) type).getName().getText(); + + if (moduleTypeName.equals("FMI2") || moduleTypeName.equals("FMI3")) { + if (exp instanceof AIdentifierExp) { + String componentName = ((AIdentifierExp) exp).getName().getText(); + + FrameworkUnitInfo instance = env.getInstanceByLexName(componentName); //This dummy statement is removed later. It ensures that the share variables are added to the root scope. PStm dummyStm = newABlockStm(); builder.getDynamicScope().add(dummyStm); - FmuVariableFmi2Api fmu = - new FmuVariableFmi2Api(instance.getOwnerIdentifier(), builder, modelDescriptionContext, dummyStm, newANameType("FMI2"), + if (instance instanceof ComponentInfo) { + try { + ModelDescriptionContext mdc = new ModelDescriptionContext(((ComponentInfo) instance).modelDescription); + + return new FmuVariableFmi2Api(instance.getOwnerIdentifier(), builder, mdc, dummyStm, newANameType("FMI2"), builder.getDynamicScope().getActiveScope(), builder.getDynamicScope(), null, new AIdentifierExp(new LexIdentifier(instance.getOwnerIdentifier().replace("{", "").replace("}", ""), null))); - return fmu; - } - throw new RuntimeException("exp is not identifying as a component: " + instance); - } else { - throw new RuntimeException("exp is not of type AIdentifierExp, but of type: " + exp.getClass()); - } + } catch (IllegalAccessException | XPathExpressionException | InvocationTargetException e) { + throw new RuntimeException(e); + } + } else if (instance instanceof InstanceInfo) { + + try { + ModelDescriptionContext3 mdc = new ModelDescriptionContext3(((InstanceInfo) instance).getModelDescription()); - } else if (env != null && type instanceof AModuleType && ((AModuleType) type).getName().getText().equals("FMI2Component")) { - try { - String environmentComponentName = ((AIdentifierExp) exp).getName().getText(); - if (graph != null) { - environmentComponentName = getLastVertexOfDirectedGraph(graph, environmentComponentName); + return new FmuVariableFmi3Api(instance.getOwnerIdentifier(), builder, mdc, dummyStm, newANameType("FMI3"), + builder.getDynamicScope().getActiveScope(), builder.getDynamicScope(), null, + new AIdentifierExp(new LexIdentifier(instance.getOwnerIdentifier().replace("{", "").replace("}", ""), null))); + } catch (IllegalAccessException | XPathExpressionException | InvocationTargetException e) { + throw new RuntimeException(e); + } + } + throw new RuntimeException("exp is not identifying as a component: " + instance); + } else { + throw new RuntimeException("exp is not of type AIdentifierExp, but of type: " + exp.getClass()); } - Map.Entry component = - FromMaBLToMaBLAPI.getComponentVariableFrom(builder, exp, env, environmentComponentName); - instances.put(component.getKey(), component.getValue()); - return component.getValue(); - } catch (IllegalAccessException | XPathExpressionException | InvocationTargetException e) { - throw new RuntimeException(e); + } else if (moduleTypeName.equals("FMI2Component") || moduleTypeName.equals("FMI3Instance")) { + try { + String environmentComponentName = ((AIdentifierExp) exp).getName().getText(); + if (graph != null) { + environmentComponentName = getLastVertexOfDirectedGraph(graph, environmentComponentName); + } + + if (moduleTypeName.equals("FMI2Component")) { + Map.Entry component = + FromMaBLToMaBLAPI.getComponentVariableFrom(builder, exp, env, environmentComponentName); + + instances.put(component.getKey(), component.getValue()); + return component.getValue(); + } else if (moduleTypeName.equals("FMI3Instance")) { + Map.Entry instance = + FromMaBLToMaBLAPI.getInstanceVariableFrom(builder, exp, env, environmentComponentName); + + fmi3Instances.put(instance.getKey(), instance.getValue()); + return instance.getValue(); + } + } catch (IllegalAccessException | XPathExpressionException | InvocationTargetException e) { + throw new RuntimeException(e); + } } + } else if (type instanceof AArrayType && (((AArrayType) type).getType() instanceof ANameType || ((AArrayType) type).getType() instanceof AModuleType)) { LexIdentifier itemName = ((AIdentifierExp) exp).getName(); @@ -174,7 +201,8 @@ public void caseAInstanceMappingStm(AInstanceMappingStm node, .collect(Collectors.toList()); return new ArrayVariableFmi2Api(null, type.clone(), null, null, null, exp, - initializerExps.stream().map(e -> wrapAsVariable(builder, typesMap, simulationEnvironment, typesMap.get(e), e, instances, graph)) + initializerExps.stream().map(e -> wrapAsVariable(builder, typesMap, simulationEnvironment, typesMap.get(e), e, instances, + fmi3Instances, graph)) .collect(Collectors.toList())); } diff --git a/maestro/src/main/java/org/intocps/maestro/template/MaBLTemplateGenerator.java b/maestro/src/main/java/org/intocps/maestro/template/MaBLTemplateGenerator.java index 7e0f96bb8..842dca19f 100644 --- a/maestro/src/main/java/org/intocps/maestro/template/MaBLTemplateGenerator.java +++ b/maestro/src/main/java/org/intocps/maestro/template/MaBLTemplateGenerator.java @@ -47,6 +47,7 @@ public class MaBLTemplateGenerator { public static final String FMI3_MODULE_NAME = "FMI3"; public static final String TYPECONVERTER_MODULE_NAME = "TypeConverter"; public static final String INITIALIZE_EXPANSION_FUNCTION_NAME = "initialize"; + public static final String INITIALIZE23_EXPANSION_FUNCTION_NAME = "initialize23"; public static final String INITIALIZE_TRANSFER_EXPANSION_FUNCTION_NAME = "initialize_transfer"; public static final String INITIALIZE_EXPANSION_MODULE_NAME = "Initializer"; public static final String FIXEDSTEP_FUNCTION_NAME = "fixedStepSizeTransfer"; @@ -457,7 +458,13 @@ public static ASimulationSpecificationCompilationUnit generateTemplate( stmMaintainer.add(createExpandInitialize(COMPONENTS_ARRAY_NAME, COMPONENTS_TRANSFER_ARRAY_NAME, START_TIME_NAME_OFFSET, END_TIME_NAME, jacobianStepConfig.endTime != null)); } else { - stmMaintainer.add(createExpandInitialize(COMPONENTS_ARRAY_NAME, START_TIME_NAME, END_TIME_NAME, jacobianStepConfig.endTime != null)); + if (instances.getFmi3List().isEmpty()) { + stmMaintainer.add( + createExpandInitialize(COMPONENTS_ARRAY_NAME, START_TIME_NAME, END_TIME_NAME, jacobianStepConfig.endTime != null)); + } else { + stmMaintainer.add(createExpandInitialize23(COMPONENTS_ARRAY_NAME, INSTANCES_ARRAY_NAME, START_TIME_NAME, END_TIME_NAME, + jacobianStepConfig.endTime != null)); + } } } @@ -692,6 +699,16 @@ public static PStm createExpandInitialize(String componentsArrayLexName, String aIdentifierExpFromString(endTimeLexName), MableAstFactory.newABoolLiteralExp(endTimeDefined)))); } + public static PStm createExpandInitialize23(String componentsArrayLexName, String instanceArrayLexName, String startTimeLexName, + String endTimeLexName, boolean endTimeDefined) { + return MableAstFactory.newExpressionStm( + MableAstFactory.newACallExp(newExpandToken(), newAIdentifierExp(MableAstFactory.newAIdentifier(INITIALIZE_EXPANSION_MODULE_NAME)), + MableAstFactory.newAIdentifier(INITIALIZE23_EXPANSION_FUNCTION_NAME), + Arrays.asList(aIdentifierExpFromString(componentsArrayLexName), aIdentifierExpFromString(instanceArrayLexName), + aIdentifierExpFromString(startTimeLexName), aIdentifierExpFromString(endTimeLexName), + MableAstFactory.newABoolLiteralExp(endTimeDefined)))); + } + public static AIdentifierExp aIdentifierExpFromString(String x) { return MableAstFactory.newAIdentifierExp(MableAstFactory.newAIdentifier(x)); } diff --git a/plugins/initializer/src/main/kotlin/Initializer.kt b/plugins/initializer/src/main/kotlin/Initializer.kt index 3a2e548f2..188b546e6 100644 --- a/plugins/initializer/src/main/kotlin/Initializer.kt +++ b/plugins/initializer/src/main/kotlin/Initializer.kt @@ -39,57 +39,62 @@ import java.util.function.Function import java.util.function.Predicate import java.util.stream.Collectors +@Suppress("UNCHECKED_CAST") @SimulationFramework(framework = Framework.FMI2) class Initializer : BasicMaestroExpansionPlugin { val f1_transfer = MableAstFactory.newAFunctionDeclaration( - LexIdentifier("initialize_transfer", null), - listOf( + LexIdentifier("initialize_transfer", null), listOf( MableAstFactory.newAFormalParameter( MableAstFactory.newAArrayType(MableAstFactory.newANameType("FMI2Component")), MableAstFactory.newAIdentifier("component") - ), - MableAstFactory.newAFormalParameter( + ), MableAstFactory.newAFormalParameter( MableAstFactory.newAArrayType(MableAstFactory.newANameType("FMI2Component")), MableAstFactory.newAIdentifier("component") - ), - MableAstFactory.newAFormalParameter( - MableAstFactory.newRealType(), - MableAstFactory.newAIdentifier("startTime") - ), - MableAstFactory.newAFormalParameter( - MableAstFactory.newRealType(), - MableAstFactory.newAIdentifier("endTime") - ), - MableAstFactory.newAFormalParameter( - MableAstFactory.newABoleanPrimitiveType(), - MableAstFactory.newAIdentifier("endTimeDefined") + ), MableAstFactory.newAFormalParameter( + MableAstFactory.newRealType(), MableAstFactory.newAIdentifier("startTime") + ), MableAstFactory.newAFormalParameter( + MableAstFactory.newRealType(), MableAstFactory.newAIdentifier("endTime") + ), MableAstFactory.newAFormalParameter( + MableAstFactory.newABoleanPrimitiveType(), MableAstFactory.newAIdentifier("endTimeDefined") ) - ), - MableAstFactory.newAVoidType() + ), MableAstFactory.newAVoidType() ) val f1 = MableAstFactory.newAFunctionDeclaration( - LexIdentifier("initialize", null), - listOf( + LexIdentifier("initialize", null), listOf( MableAstFactory.newAFormalParameter( MableAstFactory.newAArrayType(MableAstFactory.newANameType("FMI2Component")), MableAstFactory.newAIdentifier("component") ), MableAstFactory.newAFormalParameter( - MableAstFactory.newRealType(), - MableAstFactory.newAIdentifier("startTime") - ), + MableAstFactory.newRealType(), MableAstFactory.newAIdentifier("startTime") + ), MableAstFactory.newAFormalParameter( + MableAstFactory.newRealType(), MableAstFactory.newAIdentifier("endTime") + ), MableAstFactory.newAFormalParameter( + MableAstFactory.newABoleanPrimitiveType(), MableAstFactory.newAIdentifier("endTimeDefined") + ) + ), MableAstFactory.newAVoidType() + ) + + val f2_3 = MableAstFactory.newAFunctionDeclaration( + LexIdentifier("initialize23", null), listOf( MableAstFactory.newAFormalParameter( - MableAstFactory.newRealType(), - MableAstFactory.newAIdentifier("endTime") + MableAstFactory.newAArrayType(MableAstFactory.newANameType("FMI2Component")), + MableAstFactory.newAIdentifier("component") + ), MableAstFactory.newAFormalParameter( + MableAstFactory.newAArrayType(MableAstFactory.newANameType("FMI3Instance")), + MableAstFactory.newAIdentifier("instances") ), + MableAstFactory.newAFormalParameter( - MableAstFactory.newABoleanPrimitiveType(), - MableAstFactory.newAIdentifier("endTimeDefined") + MableAstFactory.newRealType(), MableAstFactory.newAIdentifier("startTime") + ), MableAstFactory.newAFormalParameter( + MableAstFactory.newRealType(), MableAstFactory.newAIdentifier("endTime") + ), MableAstFactory.newAFormalParameter( + MableAstFactory.newABoleanPrimitiveType(), MableAstFactory.newAIdentifier("endTimeDefined") ) - ), - MableAstFactory.newAVoidType() + ), MableAstFactory.newAVoidType() ) private val portsAlreadySet = HashMap>() @@ -124,10 +129,162 @@ class Initializer : BasicMaestroExpansionPlugin { } val declaredUnfoldFunctions: Set - get() = setOf(f1, f1_transfer) + get() = setOf(f1, f1_transfer, f2_3) fun getActiveDeclaration(declaredFunction: AFunctionDeclaration?): AFunctionDeclaration { - return if (declaredFunction == f1) f1 else f1_transfer + return if (declaredFunction == f1) f1 else if (declaredFunction == f1_transfer) f1_transfer else f2_3 + } + + enum class ARG_INDEX { + FMI2_INSTANCES, FMI3_INSTANCES, TRANSFER_INSTANCES, START_TIME, END_TIME, END_TIME_DEFINED + } + + /** + * Mapping function from arg to value when called with the builder api + */ + fun getArg( + declaredFunction: AFunctionDeclaration?, + formalArguments: MutableList>?, + index: ARG_INDEX + ): Fmi2Builder.Variable? { + when (declaredFunction) { + f1 -> { + return when (index) { + ARG_INDEX.FMI2_INSTANCES -> formalArguments?.get(0); + ARG_INDEX.START_TIME -> formalArguments?.get(1); + ARG_INDEX.END_TIME -> formalArguments?.get(2); + ARG_INDEX.END_TIME_DEFINED -> formalArguments?.get(3); + else -> null; + } + } + + f1_transfer -> { + return when (index) { + ARG_INDEX.FMI2_INSTANCES -> formalArguments?.get(0); + ARG_INDEX.TRANSFER_INSTANCES -> formalArguments?.get(1); + ARG_INDEX.START_TIME -> formalArguments?.get(2); + ARG_INDEX.END_TIME -> formalArguments?.get(3); + ARG_INDEX.END_TIME_DEFINED -> formalArguments?.get(4); + else -> null; + } + } + + f2_3 -> { + return when (index) { + ARG_INDEX.FMI2_INSTANCES -> formalArguments?.get(0); + ARG_INDEX.FMI3_INSTANCES -> formalArguments?.get(1); + ARG_INDEX.START_TIME -> formalArguments?.get(2); + ARG_INDEX.END_TIME -> formalArguments?.get(3); + ARG_INDEX.END_TIME_DEFINED -> formalArguments?.get(4); + else -> null; + } + } + + else -> return null + } + } + + /** + * Mapping function from arg to value when called as plain with exp + */ + fun getArg( + declaredFunction: AFunctionDeclaration?, + builder: MablApiBuilder, + env: Fmi2SimulationEnvironment, + formalArguments: List, + index: ARG_INDEX + ): Fmi2Builder.Variable? { + when (declaredFunction) { + f1 -> { + return when (index) { + ARG_INDEX.FMI2_INSTANCES -> ArrayVariableFmi2Api( + null, + null, + null, + null, + null, + null, + FromMaBLToMaBLAPI.getComponentVariablesFrom(builder, formalArguments[0], env).values.stream() + .collect(Collectors.toList()) as List>>? + ); + ARG_INDEX.START_TIME -> DoubleVariableFmi2Api(null, null, null, null, formalArguments[1].clone()); + ARG_INDEX.END_TIME -> DoubleVariableFmi2Api(null, null, null, null, formalArguments[2].clone()); + ARG_INDEX.END_TIME_DEFINED -> BooleanVariableFmi2Api( + null, null, null, null, formalArguments[3].clone() + ); + else -> null; + } + } + + f1_transfer -> { + return when (index) { + ARG_INDEX.FMI2_INSTANCES -> ArrayVariableFmi2Api( + null, + null, + null, + null, + null, + null, + FromMaBLToMaBLAPI.getComponentVariablesFrom(builder, formalArguments[0], env).values.stream() + .collect(Collectors.toList()) as List>>? + ); + ARG_INDEX.TRANSFER_INSTANCES -> ArrayVariableFmi2Api( + null, + null, + null, + null, + null, + null, + FromMaBLToMaBLAPI.getComponentVariablesFrom(builder, formalArguments[1], env).values.stream() + .collect(Collectors.toList()) as List>>? + ); + ARG_INDEX.START_TIME -> DoubleVariableFmi2Api(null, null, null, null, formalArguments[2].clone()); + ARG_INDEX.END_TIME -> DoubleVariableFmi2Api(null, null, null, null, formalArguments[3].clone()); + ARG_INDEX.END_TIME_DEFINED -> BooleanVariableFmi2Api( + null, null, null, null, formalArguments[4].clone() + ); + else -> null; + } + } + + f2_3 -> { + return when (index) { + ARG_INDEX.FMI2_INSTANCES -> ArrayVariableFmi2Api( + null, + null, + null, + null, + null, + null, + FromMaBLToMaBLAPI.getComponentVariablesFrom(builder, formalArguments[0], env).values.stream() + .collect(Collectors.toList()) as List>>? + ); + ARG_INDEX.FMI3_INSTANCES -> null; + ARG_INDEX.START_TIME -> DoubleVariableFmi2Api(null, null, null, null, formalArguments[2].clone()); + ARG_INDEX.END_TIME -> DoubleVariableFmi2Api(null, null, null, null, formalArguments[3].clone()); + ARG_INDEX.END_TIME_DEFINED -> BooleanVariableFmi2Api( + null, null, null, null, formalArguments[4].clone() + ); + else -> null; + } + } + + else -> return null + } + } + + private fun toCompMap(map: List?): Map { + return if (map == null) emptyMap() else map.stream() + .collect(Collectors.toMap({ v: ComponentVariableFmi2Api -> v.name }, + Function.identity(), + { u: ComponentVariableFmi2Api?, v: ComponentVariableFmi2Api? -> u }) { LinkedHashMap() }) + } + + private fun toInstanceMap(map: List?): Map { + return if (map == null) emptyMap() else map.stream() + .collect(Collectors.toMap({ v: InstanceVariableFmi3Api -> v.name }, + Function.identity(), + { u: InstanceVariableFmi3Api?, v: InstanceVariableFmi3Api? -> u }) { LinkedHashMap() }) } override fun expandWithRuntimeAddition( @@ -154,8 +311,7 @@ class Initializer : BasicMaestroExpansionPlugin { try { if (builder !is MablApiBuilder && builder != null) { throw ExpandException( - "Not supporting the given builder type. Expecting " + MablApiBuilder::class.java.simpleName + " got " + - builder.javaClass.simpleName + "Not supporting the given builder type. Expecting " + MablApiBuilder::class.java.simpleName + " got " + builder.javaClass.simpleName ) } @@ -165,43 +321,35 @@ class Initializer : BasicMaestroExpansionPlugin { val math = builder.mablToMablAPI.mathBuilder val booleanLogic = builder.booleanBuilder - val fmuInstancesTransfer: Map = - if (declaredFunction == f1) emptyMap() else ((formalArguments[1] as ArrayVariable<*, *>).items() as List).stream() - .collect(Collectors.toMap( - { v: ComponentVariableFmi2Api -> v.name }, Function.identity(), - { u: ComponentVariableFmi2Api?, v: ComponentVariableFmi2Api? -> u } - ) { LinkedHashMap() }); - val startTimeIndex = if (declaredFunction == f1) 1 else 2; - val endTimeIndex = if (declaredFunction == f1) 2 else 3; - val endTimeDefinedIndex = endTimeIndex + 1; - - // Convert raw MaBL to API - val externalStartTime = formalArguments[startTimeIndex] as DoubleVariableFmi2Api - val externalEndTime = formalArguments[endTimeIndex] as DoubleVariableFmi2Api - val externalEndTimeDefined = formalArguments[endTimeDefinedIndex] as BooleanVariableFmi2Api + + val fmuInstancesTransfer: List? = ((getArg( + declaredFunction, formalArguments, ARG_INDEX.TRANSFER_INSTANCES + ) as? ArrayVariable<*, *>)?.items()) as? List; + + val externalStartTime = + getArg(declaredFunction, formalArguments, ARG_INDEX.START_TIME) as DoubleVariableFmi2Api + val externalEndTime = getArg(declaredFunction, formalArguments, ARG_INDEX.END_TIME) as DoubleVariableFmi2Api + val externalEndTimeDefined = + getArg(declaredFunction, formalArguments, ARG_INDEX.END_TIME_DEFINED) as BooleanVariableFmi2Api + val endTimeVar = dynamicScope.store("fixed_end_time", 0.0) as DoubleVariableFmi2Api endTimeVar.setValue(externalEndTime) // use LinkedHashMap to preserve added order - val fmuInstances: MutableMap = - ((formalArguments[0] as ArrayVariable<*, *>).items() as List).stream() - .collect(Collectors.toMap( - { v: ComponentVariableFmi2Api -> v.name }, Function.identity(), - { u: ComponentVariableFmi2Api?, v: ComponentVariableFmi2Api? -> u } - ) { LinkedHashMap() }) - -// val fmuInstancesTransfer: MutableMap = -// ((formalArguments[1] as ArrayVariable<*, *>).items() as List).stream() -// .collect(Collectors.toMap( -// { v: ComponentVariableFmi2Api -> v.name }, Function.identity(), -// { u: ComponentVariableFmi2Api?, v: ComponentVariableFmi2Api? -> u } -// ) { LinkedHashMap() }) + val fmuInstances: List? = ((getArg( + declaredFunction, formalArguments, ARG_INDEX.FMI2_INSTANCES + ) as? ArrayVariable<*, *>)?.items() as? List) + + val fmu3Instances: List? = ((getArg( + declaredFunction, formalArguments, ARG_INDEX.FMI3_INSTANCES + ) as? ArrayVariable<*, *>)?.items() as? List) expansionLogic( config, dynamicScope, - fmuInstances, - fmuInstancesTransfer, + toCompMap(fmuInstances), + toInstanceMap(fmu3Instances), + toCompMap(fmuInstancesTransfer), externalStartTime, externalEndTime, externalEndTimeDefined, @@ -227,6 +375,7 @@ class Initializer : BasicMaestroExpansionPlugin { config: IPluginConfiguration?, dynamicScope: DynamicActiveBuilderScope, fmuInstancesIn: Map, + fmu3InstancesIn: Map, fmuInstancesTransfer: Map, externalStartTime: DoubleVariableFmi2Api, externalEndTime: DoubleVariableFmi2Api, @@ -247,17 +396,17 @@ class Initializer : BasicMaestroExpansionPlugin { maxConvergeAttempts = dynamicScope.store("maxConvergeAttempts", this.config!!.maxIterations) val fmuInstances = fmuInstancesIn.filterKeys { !fmuInstancesTransfer.keys.contains(it) }; + val fmu3Instances = fmu3InstancesIn.filterKeys { !fmuInstancesTransfer.keys.contains(it) }; logger.debug("Setup experiment for all components") fmuInstances.values.forEach { i -> i.setupExperiment( - externalStartTime, - externalEndTime, - externalEndTimeDefined, - this.config!!.relativeTolerance + externalStartTime, externalEndTime, externalEndTimeDefined, this.config!!.relativeTolerance ) }; - val connections = createConnections(env, fmuInstances) + + + val connections = createConnections(env, fmuInstances).plus(createConnections3(env, fmu3Instances)) val filterTargets = createTargetFilter(fmuInstancesTransfer, connections) @@ -265,8 +414,10 @@ class Initializer : BasicMaestroExpansionPlugin { val instantiationOrder = topologicalPlugin.findInstantiationOrderStrongComponents(connections, filterTargets) //Verification against prolog should only be done if it turned on and there is no loops - if (this.config!!.verifyAgainstProlog && instantiationOrder.all { i -> i.size == 1 }) - initializationPrologQuery.initializationOrderIsValid(instantiationOrder.flatten(), connections) + if (this.config!!.verifyAgainstProlog && instantiationOrder.all { i -> i.size == 1 }) initializationPrologQuery.initializationOrderIsValid( + instantiationOrder.flatten(), + connections + ) //Set variables for all components in IniPhase @@ -275,14 +426,12 @@ class Initializer : BasicMaestroExpansionPlugin { //Enter initialization Mode logger.debug("Enter initialization Mode") fmuInstances.values.forEach(Consumer { fmu: ComponentVariableFmi2Api -> fmu.enterInitializationMode() }) + //FIXME: missing parameters +// fmu3Instances.values.forEach(Consumer { fmu: InstanceVariableFmi3Api -> fmu.enterInitializationMode() }) val instructions = instantiationOrder.map { i -> createInitInstructions( - i.toList(), - dynamicScope, - fmuInstances, - booleanLogic, - math + i.toList(), dynamicScope, fmuInstances, booleanLogic, math ) } var stabilisationScope: ScopeFmi2Api? = null @@ -307,25 +456,21 @@ class Initializer : BasicMaestroExpansionPlugin { //Exit initialization Mode fmuInstances.values.forEach(Consumer { obj: ComponentVariableFmi2Api -> obj.exitInitializationMode() }) + fmu3Instances.values.forEach(Consumer { obj: InstanceVariableFmi3Api -> obj.exitInitializationMode() }) } + override fun expand( - declaredFunction: AFunctionDeclaration, formalArguments: List, config: IPluginConfiguration, - envIn: ISimulationEnvironment, errorReporter: IErrorReporter + declaredFunction: AFunctionDeclaration, + formalArguments: List, + config: IPluginConfiguration, + envIn: ISimulationEnvironment, + errorReporter: IErrorReporter ): List { logger.debug("Unfolding: {}", declaredFunction.toString()) val env = envIn as Fmi2SimulationEnvironment verifyArguments(declaredFunction, formalArguments, env) - - val startTimeIndex = if (declaredFunction == f1) 1 else 2; - val endTimeIndex = if (declaredFunction == f1) 2 else 3; - val endTimeDefinedIndex = endTimeIndex + 1; - - val startTime = formalArguments[startTimeIndex].clone() - val endTime = formalArguments[endTimeIndex].clone() - val endTimeDefined = formalArguments[endTimeDefinedIndex].clone() - return try { val setting = MablApiBuilder.MablSettings() setting.fmiErrorHandlingEnabled = false @@ -334,31 +479,37 @@ class Initializer : BasicMaestroExpansionPlugin { val math = builder.mablToMablAPI.mathBuilder val booleanLogic = builder.mablToMablAPI.booleanBuilder - // Convert raw MaBL to API - // TODO: Create a reference value type - val externalStartTime = DoubleVariableFmi2Api(null, null, null, null, startTime) - // TODO: Create a reference value type - val externalEndTime = DoubleVariableFmi2Api(null, null, null, null, endTime) - val externalEndTimeDefined = BooleanVariableFmi2Api(null, null, null, null, endTimeDefined) + val fmuInstancesTransfer: List? = (((getArg( + declaredFunction, builder, env, formalArguments, ARG_INDEX.TRANSFER_INSTANCES + ) as? ArrayVariable<*, *>)?.items()) as? List) + + val externalStartTime = + getArg(declaredFunction, builder, env, formalArguments, ARG_INDEX.START_TIME) as DoubleVariableFmi2Api + val externalEndTime = + getArg(declaredFunction, builder, env, formalArguments, ARG_INDEX.END_TIME) as DoubleVariableFmi2Api + val externalEndTimeDefined = getArg( + declaredFunction, builder, env, formalArguments, ARG_INDEX.END_TIME_DEFINED + ) as BooleanVariableFmi2Api + val endTimeVar = dynamicScope.store("fixed_end_time", 0.0) as DoubleVariableFmi2Api endTimeVar.setValue(externalEndTime) - // Import the external components into Fmi2API - val fmuInstances = FromMaBLToMaBLAPI.getComponentVariablesFrom(builder, formalArguments[0], env) + // use LinkedHashMap to preserve added order + val fmuInstances: List? = (((getArg( + declaredFunction, builder, env, formalArguments, ARG_INDEX.FMI2_INSTANCES + ) as? ArrayVariable<*, *>)?.items()) as? List) - val fmuInstancesTransfer: Map = - if (declaredFunction == f1) emptyMap() else FromMaBLToMaBLAPI.getComponentVariablesFrom( - builder, - formalArguments[1], - env - ).toMap() + val fmu3Instances: List? = (((getArg( + declaredFunction, builder, env, formalArguments, ARG_INDEX.FMI3_INSTANCES + ) as? ArrayVariable<*, *>)?.items()) as? List) expansionLogic( config, builder.dynamicScope, - fmuInstances, - fmuInstancesTransfer, + toCompMap(fmuInstances), + toInstanceMap(fmu3Instances), + toCompMap(fmuInstancesTransfer), externalStartTime, externalEndTime, externalEndTimeDefined, @@ -449,16 +600,14 @@ class Initializer : BasicMaestroExpansionPlugin { } private fun setRemainingInputs( - fmuInstances: Map, - builder: MablApiBuilder + fmuInstances: Map, builder: MablApiBuilder ) { for (comp in fmuInstances.values) { try { val scalarVariables = comp.modelDescription.scalarVariables - val inputsScalars = - scalarVariables.filter { x -> - PhasePredicates.inPhase().test(x) && !portSet(comp, x) - } + val inputsScalars = scalarVariables.filter { x -> + PhasePredicates.inPhase().test(x) && !portSet(comp, x) + } val ports = comp.getPorts(*inputsScalars.stream().mapToInt { sv -> Math.toIntExact(sv.getValueReference()) } @@ -478,9 +627,7 @@ class Initializer : BasicMaestroExpansionPlugin { } private fun setParameterOnPort( - port: PortFmi2Api, - comp: ComponentVariableFmi2Api, - builder: MablApiBuilder + port: PortFmi2Api, comp: ComponentVariableFmi2Api, builder: MablApiBuilder ) { val fmuName = comp.name // var value = findUseDefault(fmuName, port.scalarVariable, modelParameters) @@ -572,8 +719,7 @@ class Initializer : BasicMaestroExpansionPlugin { } private fun fmuCoSimInstruction( - fmuInstances: Map, - p: Fmi2SimulationEnvironment.Variable + fmuInstances: Map, p: Fmi2SimulationEnvironment.Variable ): FMUCoSimInstruction { val fmu = fmuInstances.values.find { x -> x.environmentName.equals(p.scalarVariable.instance.text) } // val fmu = fmuInstances.getValue(p.scalarVariable.instance.text) @@ -588,22 +734,18 @@ class Initializer : BasicMaestroExpansionPlugin { else -> throw ExpandException("Internal error") } - } else - throw ExpandException("Failed to retrieve FMUInstance by name: " + p.scalarVariable.instance.text) + } else throw ExpandException("Failed to retrieve FMUInstance by name: " + p.scalarVariable.instance.text) } private fun createConvergencePorts( - ports: List, - fmuInstances: Map + ports: List, fmuInstances: Map ): Map>> { - val fmuToPorts = ports.groupBy { i -> i.instance.text } - .map { i -> - i.key to i.value.map { p -> - fmuInstances.getValue(i.key).getPort(p.name) - } + val fmuToPorts = ports.groupBy { i -> i.instance.text }.map { i -> + i.key to i.value.map { p -> + fmuInstances.getValue(i.key).getPort(p.name) } - .toMap() + }.toMap() return fmuToPorts.map { (fmu, ports) -> fmuInstances.getValue(fmu) to ports.map { port -> port to fmuInstances[fmu]?.getSingle( @@ -615,14 +757,21 @@ class Initializer : BasicMaestroExpansionPlugin { private fun createConnections( - env: Fmi2SimulationEnvironment, - fmuInstances: Map + env: Fmi2SimulationEnvironment, fmuInstances: Map + ): Set { + return fmuInstances.values.flatMap { i: ComponentVariableFmi2Api -> + env.getRelations(i.environmentName) + .filter { rel: Fmi2SimulationEnvironment.Relation -> rel.direction == IRelation.Direction.OutputToInput } + }.toSet() + } + + private fun createConnections3( + env: Fmi2SimulationEnvironment, fmuInstances: Map ): Set { - return fmuInstances.values - .flatMap { i: ComponentVariableFmi2Api -> - env.getRelations(i.environmentName) - .filter { rel: Fmi2SimulationEnvironment.Relation -> rel.direction == IRelation.Direction.OutputToInput } - }.toSet() + return fmuInstances.values.flatMap { i: InstanceVariableFmi3Api -> + env.getRelations(i.environmentName) + .filter { rel: Fmi2SimulationEnvironment.Relation -> rel.direction == IRelation.Direction.OutputToInput } + }.toSet() } private fun createTargetFilter( @@ -656,9 +805,7 @@ class Initializer : BasicMaestroExpansionPlugin { @Throws(ExpandException::class) private fun verifyArguments( - declaredFunction: AFunctionDeclaration, - formalArguments: List?, - env: ISimulationEnvironment? + declaredFunction: AFunctionDeclaration, formalArguments: List?, env: ISimulationEnvironment? ) { //maybe some of these tests are not necessary - but they are in my unit test if (formalArguments == null || formalArguments.size != getActiveDeclaration(declaredFunction).formals.size) { @@ -710,12 +857,13 @@ class Initializer : BasicMaestroExpansionPlugin { return compilationUnit as AImportedModuleCompilationUnit } compilationUnit = AImportedModuleCompilationUnit() - compilationUnit!!.imports = - listOf("FMI2", "TypeConverter", "Math", "Logger", "MEnv", "BooleanLogic").map { identifier: String? -> - MableAstFactory.newAIdentifier( - identifier - ) - } + compilationUnit!!.imports = listOf( + "FMI2", "FMI3", "TypeConverter", "Math", "Logger", "MEnv", "BooleanLogic" + ).map { identifier: String? -> + MableAstFactory.newAIdentifier( + identifier + ) + } val module = AModuleDeclaration() module.name = MableAstFactory.newAIdentifier(name) module.setFunctions(ArrayList(declaredUnfoldFunctions)) @@ -743,23 +891,18 @@ class Initializer : BasicMaestroExpansionPlugin { init { val mapper = ObjectMapper() - val convertParameters: Map? = - if (parameters == null) null else mapper.convertValue( - parameters, - Map::class.java - ) as Map - - modelParameters = - convertParameters?.map { (key, value) -> - ModelParameter( - ModelConnection.Variable.parse(key), - value - ) - } + val convertParameters: Map? = if (parameters == null) null else mapper.convertValue( + parameters, Map::class.java + ) as Map + + modelParameters = convertParameters?.map { (key, value) -> + ModelParameter( + ModelConnection.Variable.parse(key), value + ) + } this.envParameters = if (envParameters == null) null else mapper.convertValue( - envParameters, - List::class.java + envParameters, List::class.java ) as List verifyAgainstProlog = verify?.asBoolean(false) ?: false @@ -782,9 +925,7 @@ class Initializer : BasicMaestroExpansionPlugin { val logger: Logger = LoggerFactory.getLogger(Initializer::class.java) private fun findParameterOrDefault( - compName: String, - sv: Fmi2ModelDescription.ScalarVariable, - modelParameters: List? + compName: String, sv: Fmi2ModelDescription.ScalarVariable, modelParameters: List? ): Any { val parameterValue = modelParameters?.firstOrNull { x: ModelParameter -> x.variable.instance.instanceName == compName && x.variable.variable == sv.name } From c85f4eea4a42e08947e74057039118d3d6802499 Mon Sep 17 00:00:00 2001 From: Kenneth Lausdahl Date: Thu, 5 Oct 2023 11:29:24 +0200 Subject: [PATCH 25/54] rename Fmi2Builder to FmiBuilder --- .../api/{Fmi2Builder.java => FmiBuilder.java} | 18 +-- .../framework/fmi2/api/mabl/BaseApiTest.java | 42 +++--- .../maestro/framework/fmi2/api/Factory.java | 2 +- .../fmi2/api/mabl/BooleanBuilderFmi2Api.java | 12 +- .../framework/fmi2/api/mabl/BuilderUtil.java | 4 +- .../fmi2/api/mabl/ConsolePrinter.java | 22 +-- .../framework/fmi2/api/mabl/DataWriter.java | 14 +- .../api/mabl/ExecutionEnvironmentFmi2Api.java | 38 ++--- .../framework/fmi2/api/mabl/FaultInject.java | 13 +- .../fmi2/api/mabl/FromMaBLToMaBLAPI.java | 9 +- .../fmi2/api/mabl/FunctionBuilder.java | 28 ++-- .../fmi2/api/mabl/LoggerFmi2Api.java | 14 +- .../fmi2/api/mabl/MablApiBuilder.java | 10 +- .../fmi2/api/mabl/MathBuilderFmi2Api.java | 10 +- .../mabl/NumericExpressionValueFmi2Api.java | 22 +-- .../framework/fmi2/api/mabl/PortFmi2Api.java | 8 +- .../framework/fmi2/api/mabl/PortFmi3Api.java | 43 +++--- .../fmi2/api/mabl/PredicateFmi2Api.java | 8 +- .../framework/fmi2/api/mabl/RealTime.java | 4 +- .../fmi2/api/mabl/SimulationControl.java | 12 +- .../framework/fmi2/api/mabl/VariableStep.java | 46 +++--- .../scoping/DynamicActiveBuilderScope.java | 16 +-- .../fmi2/api/mabl/scoping/IMablScope.java | 13 +- .../fmi2/api/mabl/scoping/IfMaBlScope.java | 10 +- .../fmi2/api/mabl/scoping/ScopeFmi2Api.java | 29 ++-- .../fmi2/api/mabl/scoping/TryMaBlScope.java | 8 +- .../fmi2/api/mabl/scoping/WhileMaBLScope.java | 4 +- .../mabl/values/BooleanExpressionValue.java | 4 +- .../mabl/values/DoubleExpressionValue.java | 14 +- .../api/mabl/values/IntExpressionValue.java | 12 +- .../values/PortValueExpresssionMapImpl.java | 6 +- .../api/mabl/values/PortValueMapImpl.java | 6 +- .../mabl/values/StringExpressionValue.java | 4 +- .../fmi2/api/mabl/values/ValueFmi2Api.java | 4 +- .../mabl/variables/ArrayVariableFmi2Api.java | 8 +- .../variables/BooleanVariableFmi2Api.java | 6 +- .../variables/ComponentVariableFmi2Api.java | 135 +++++++++--------- .../mabl/variables/DoubleVariableFmi2Api.java | 8 +- .../mabl/variables/FmuVariableFmi2Api.java | 23 ++- .../mabl/variables/FmuVariableFmi3Api.java | 46 +++--- .../variables/IndexedVariableFmi2Api.java | 4 +- .../variables/InstanceVariableFmi3Api.java | 133 +++++++++-------- .../mabl/variables/IntVariableFmi2Api.java | 12 +- .../mabl/variables/PortVariableMapImpl.java | 7 +- .../mabl/variables/RuntimeModuleVariable.java | 32 ++--- .../variables/StateMablVariableFmi2Api.java | 23 ++- .../variables/StateMablVariableFmi3Api.java | 22 ++- .../mabl/variables/StringVariableFmi2Api.java | 6 +- .../variables/VariableCreatorFmi2Api.java | 4 +- .../variables/VariableCreatorFmi3Api.java | 30 ++-- .../api/mabl/variables/VariableFmi2Api.java | 20 +-- .../src/main/kotlin/DerivativeEstimator.kt | 4 +- .../framework/fmi2/api/mabl/SetPortsTest.java | 4 +- .../org/intocps/maestro/BuilderHelper.java | 19 ++- .../org/intocps/maestro/BuilderFmi3Test.java | 14 +- .../java/org/intocps/maestro/BuilderTest.java | 21 +-- .../org/intocps/maestro/ImportCliTest.java | 5 +- .../intocps/maestro/fmi3/Fmi3ModuleTest.java | 10 +- .../plugin/BasicMaestroExpansionPlugin.java | 4 +- .../plugin/IMaestroExpansionPlugin.java | 4 +- .../maestro/plugin/DemoBuilderPlugin.java | 4 +- .../src/main/kotlin/Initializer.kt | 28 ++-- .../instructions/ComplexCoSimInstruction.kt | 8 +- .../kotlin/instructions/LoopSimInstruction.kt | 34 +++-- .../maestro/plugin/JacobianStepBuilder.java | 18 +-- .../org/intocps/maestro/plugin/Sigver.java | 38 ++--- 66 files changed, 610 insertions(+), 633 deletions(-) rename frameworks/builder/src/main/java/org/intocps/maestro/framework/fmi2/api/{Fmi2Builder.java => FmiBuilder.java} (97%) diff --git a/frameworks/builder/src/main/java/org/intocps/maestro/framework/fmi2/api/Fmi2Builder.java b/frameworks/builder/src/main/java/org/intocps/maestro/framework/fmi2/api/FmiBuilder.java similarity index 97% rename from frameworks/builder/src/main/java/org/intocps/maestro/framework/fmi2/api/Fmi2Builder.java rename to frameworks/builder/src/main/java/org/intocps/maestro/framework/fmi2/api/FmiBuilder.java index a71b8bc4e..117026dfb 100644 --- a/frameworks/builder/src/main/java/org/intocps/maestro/framework/fmi2/api/Fmi2Builder.java +++ b/frameworks/builder/src/main/java/org/intocps/maestro/framework/fmi2/api/FmiBuilder.java @@ -10,7 +10,7 @@ import java.util.Map; @SuppressWarnings("unused") -public interface Fmi2Builder { +public interface FmiBuilder { B build() throws Exception; SETTINGS getSettings(); @@ -63,7 +63,7 @@ public interface Fmi2Builder { Variable getFmuVariableFrom(E exp); - interface RuntimeModule extends Fmi2Builder.Variable> { + interface RuntimeModule extends FmiBuilder.Variable> { void initialize(List declaredFuncs); void initialize(RuntimeFunction... declaredFuncs); @@ -90,15 +90,15 @@ interface IFunctionBuilder { IFunctionBuilder setReturnType(String name); - IFunctionBuilder setReturnType(Fmi2Builder.RuntimeFunction.FunctionType.Type type); + IFunctionBuilder setReturnType(FmiBuilder.RuntimeFunction.FunctionType.Type type); - IFunctionBuilder addArgument(String name, Fmi2Builder.RuntimeFunction.FunctionType.Type type); + IFunctionBuilder addArgument(String name, FmiBuilder.RuntimeFunction.FunctionType.Type type); IFunctionBuilder useVargs(); IFunctionBuilder addArgument(String name, String type); - Fmi2Builder.RuntimeFunction build(); + FmiBuilder.RuntimeFunction build(); } interface RuntimeFunction { @@ -522,7 +522,7 @@ interface Fmu2Variable extends Variable> { // } Fmi2ComponentVariable instantiate(String namePrefix, TryScope enclosingTryScope, Scope scope, String environmentName); - Fmi2ComponentVariable instantiate(String namePrefix, Fmi2Builder.TryScope enclosingTryScope, Fmi2Builder.Scope scope, + Fmi2ComponentVariable instantiate(String namePrefix, FmiBuilder.TryScope enclosingTryScope, FmiBuilder.Scope scope, String environmentName, boolean loggingOn); Fmi2ComponentVariable instantiate(String name, TryScope enclosingTryScope, Scope scope); @@ -839,7 +839,7 @@ interface Variable { Scope getDeclaredScope(); } - interface ArrayVariable extends Variable> { + interface ArrayVariable extends Variable> { int size(); List> items(); @@ -850,7 +850,7 @@ interface ArrayVariable extends Variable> interface ExpressionValue extends ProvidesTypedReferenceExp { } - interface BooleanExpressionValue extends Fmi2Builder.ExpressionValue { + interface BooleanExpressionValue extends FmiBuilder.ExpressionValue { } interface DoubleExpressionValue extends NumericExpressionValue { @@ -859,7 +859,7 @@ interface DoubleExpressionValue extends NumericExpressionValue { interface IntExpressionValue extends NumericExpressionValue { } - interface StringExpressionValue extends Fmi2Builder.ExpressionValue { + interface StringExpressionValue extends FmiBuilder.ExpressionValue { } diff --git a/frameworks/fmi2api-test/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/BaseApiTest.java b/frameworks/fmi2api-test/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/BaseApiTest.java index 1d42c904b..08d4f034c 100644 --- a/frameworks/fmi2api-test/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/BaseApiTest.java +++ b/frameworks/fmi2api-test/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/BaseApiTest.java @@ -10,7 +10,7 @@ import org.intocps.maestro.ast.node.PStm; import org.intocps.maestro.core.messages.ErrorReporter; import org.intocps.maestro.core.messages.IErrorReporter; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.interpreter.DefaultExternalValueFactory; import org.intocps.maestro.interpreter.MableInterpreter; import org.intocps.maestro.interpreter.api.IValueLifecycleHandler; @@ -99,45 +99,43 @@ public void check(String spec, assertTrue(res, "Type check errors:" + out); - new MableInterpreter( - new DefaultExternalValueFactory(new File("target"),typeChecker::findModule, - new ByteArrayInputStream(runtimedata.getBytes(StandardCharsets.UTF_8)))).execute( - doc); + new MableInterpreter(new DefaultExternalValueFactory(new File("target"), typeChecker::findModule, + new ByteArrayInputStream(runtimedata.getBytes(StandardCharsets.UTF_8)))).execute(doc); } public static class MDebugAssert { - private final Fmi2Builder builder; - private final Fmi2Builder.RuntimeModule mdebugAssert; + private final FmiBuilder builder; + private final FmiBuilder.RuntimeModule mdebugAssert; - public MDebugAssert(Fmi2Builder builder, Fmi2Builder.RuntimeModule mdebugAssert) { + public MDebugAssert(FmiBuilder builder, FmiBuilder.RuntimeModule mdebugAssert) { this.builder = builder; this.mdebugAssert = mdebugAssert; } - public static MDebugAssert create(Fmi2Builder builder) { - Fmi2Builder.RuntimeModule mdebugAssert = builder.loadRuntimeModule(MDebugAssert.class.getSimpleName()); + public static MDebugAssert create(FmiBuilder builder) { + FmiBuilder.RuntimeModule mdebugAssert = builder.loadRuntimeModule(MDebugAssert.class.getSimpleName()); return new MDebugAssert(builder, mdebugAssert); } - public void assertEquals(Fmi2Builder.Variable a, Fmi2Builder.Variable b) { - this.mdebugAssert.callVoid(builder.getFunctionBuilder().addArgument("a", Fmi2Builder.RuntimeFunction.FunctionType.Type.Any) - .addArgument("b", Fmi2Builder.RuntimeFunction.FunctionType.Type.Any).setName("assertEquals").build(), a, b); + public void assertEquals(FmiBuilder.Variable a, FmiBuilder.Variable b) { + this.mdebugAssert.callVoid(builder.getFunctionBuilder().addArgument("a", FmiBuilder.RuntimeFunction.FunctionType.Type.Any) + .addArgument("b", FmiBuilder.RuntimeFunction.FunctionType.Type.Any).setName("assertEquals").build(), a, b); } - public void assertEquals(Object a, Fmi2Builder.Variable b) { - this.mdebugAssert.callVoid(builder.getFunctionBuilder().addArgument("a", Fmi2Builder.RuntimeFunction.FunctionType.Type.Any) - .addArgument("b", Fmi2Builder.RuntimeFunction.FunctionType.Type.Any).setName("assertEquals").build(), a, b); + public void assertEquals(Object a, FmiBuilder.Variable b) { + this.mdebugAssert.callVoid(builder.getFunctionBuilder().addArgument("a", FmiBuilder.RuntimeFunction.FunctionType.Type.Any) + .addArgument("b", FmiBuilder.RuntimeFunction.FunctionType.Type.Any).setName("assertEquals").build(), a, b); } - public void assertNotEquals(Fmi2Builder.Variable a, Fmi2Builder.Variable b) { - this.mdebugAssert.callVoid(builder.getFunctionBuilder().addArgument("a", Fmi2Builder.RuntimeFunction.FunctionType.Type.Any) - .addArgument("b", Fmi2Builder.RuntimeFunction.FunctionType.Type.Any).setName("assertNotEquals").build(), a, b); + public void assertNotEquals(FmiBuilder.Variable a, FmiBuilder.Variable b) { + this.mdebugAssert.callVoid(builder.getFunctionBuilder().addArgument("a", FmiBuilder.RuntimeFunction.FunctionType.Type.Any) + .addArgument("b", FmiBuilder.RuntimeFunction.FunctionType.Type.Any).setName("assertNotEquals").build(), a, b); } - public void assertNotEquals(Object a, Fmi2Builder.Variable b) { - this.mdebugAssert.callVoid(builder.getFunctionBuilder().addArgument("a", Fmi2Builder.RuntimeFunction.FunctionType.Type.Any) - .addArgument("b", Fmi2Builder.RuntimeFunction.FunctionType.Type.Any).setName("assertNotEquals").build(), a, b); + public void assertNotEquals(Object a, FmiBuilder.Variable b) { + this.mdebugAssert.callVoid(builder.getFunctionBuilder().addArgument("a", FmiBuilder.RuntimeFunction.FunctionType.Type.Any) + .addArgument("b", FmiBuilder.RuntimeFunction.FunctionType.Type.Any).setName("assertNotEquals").build(), a, b); } @IValueLifecycleHandler.ValueLifecycle(name = "MDebugAssert") diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/Factory.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/Factory.java index 5b9f7d0b9..e7022466c 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/Factory.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/Factory.java @@ -4,7 +4,7 @@ public class Factory { - public Fmi2Builder get(Types type) { + public FmiBuilder get(Types type) { switch (type) { case Mabl: default: diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/BooleanBuilderFmi2Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/BooleanBuilderFmi2Api.java index bc2d6ae78..3d80b7031 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/BooleanBuilderFmi2Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/BooleanBuilderFmi2Api.java @@ -1,7 +1,7 @@ package org.intocps.maestro.framework.fmi2.api.mabl; import org.intocps.maestro.ast.node.PStm; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.DynamicActiveBuilderScope; import org.intocps.maestro.framework.fmi2.api.mabl.variables.BooleanVariableFmi2Api; @@ -17,11 +17,11 @@ public class BooleanBuilderFmi2Api { private final DynamicActiveBuilderScope dynamicScope; private final MablApiBuilder builder; private String moduleIdentifier; - private Fmi2Builder.RuntimeModule runtimeModule; + private FmiBuilder.RuntimeModule runtimeModule; private boolean runtimeModuleMode = false; - public BooleanBuilderFmi2Api(MablApiBuilder mablApiBuilder, Fmi2Builder.RuntimeModule runtimeModule) { + public BooleanBuilderFmi2Api(MablApiBuilder mablApiBuilder, FmiBuilder.RuntimeModule runtimeModule) { this(mablApiBuilder.getDynamicScope(), mablApiBuilder); this.runtimeModuleMode = true; this.runtimeModule = runtimeModule; @@ -36,15 +36,15 @@ public BooleanBuilderFmi2Api(DynamicActiveBuilderScope dynamicScope, MablApiBuil } - public BooleanVariableFmi2Api allTrue(String variablePrefix, List parameters) { + public BooleanVariableFmi2Api allTrue(String variablePrefix, List parameters) { return allTrueFalse(variablePrefix, parameters, ALL_TRUE_FUNCTION_NAME); } - public BooleanVariableFmi2Api allFalse(String variablePrefix, List parameters) { + public BooleanVariableFmi2Api allFalse(String variablePrefix, List parameters) { return allTrueFalse(variablePrefix, parameters, ALL_FALSE_FUNCTION_NAME); } - private BooleanVariableFmi2Api allTrueFalse(String variablePrefix, List parameters, + private BooleanVariableFmi2Api allTrueFalse(String variablePrefix, List parameters, String function) { String variableName = dynamicScope.getName(variablePrefix); diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/BuilderUtil.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/BuilderUtil.java index f83e7f12c..40a3da138 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/BuilderUtil.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/BuilderUtil.java @@ -4,7 +4,7 @@ import org.intocps.maestro.ast.node.PStateDesignator; import org.intocps.maestro.ast.node.PStm; import org.intocps.maestro.ast.node.PType; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.variables.ComponentVariableFmi2Api; import org.intocps.maestro.framework.fmi2.api.mabl.variables.FmuVariableFmi2Api; import org.intocps.maestro.framework.fmi2.api.mabl.variables.VariableFmi2Api; @@ -66,7 +66,7 @@ public static List createTypeConvertingAssignment(PStateDesignator designa return statements; } - public static List createTypeConvertingAssignment(MablApiBuilder builder, Fmi2Builder.Scope scope, PStateDesignator designator, + public static List createTypeConvertingAssignment(MablApiBuilder builder, FmiBuilder.Scope scope, PStateDesignator designator, PExp value, PType valueType, PType targetType) { return createTypeConvertingAssignment(designator, value, valueType, targetType); diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/ConsolePrinter.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/ConsolePrinter.java index 133295839..7590e213d 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/ConsolePrinter.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/ConsolePrinter.java @@ -1,23 +1,23 @@ package org.intocps.maestro.framework.fmi2.api.mabl; import org.intocps.maestro.ast.node.PStm; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; public class ConsolePrinter { - private final Fmi2Builder.RuntimeModule module; - private final Fmi2Builder.RuntimeFunction printFunc; - private final Fmi2Builder.RuntimeFunction printlnFunc; + private final FmiBuilder.RuntimeModule module; + private final FmiBuilder.RuntimeFunction printFunc; + private final FmiBuilder.RuntimeFunction printlnFunc; - public ConsolePrinter(MablApiBuilder builder, Fmi2Builder.RuntimeModule module) { + public ConsolePrinter(MablApiBuilder builder, FmiBuilder.RuntimeModule module) { this.module = module; - printFunc = builder.getFunctionBuilder().setName("print").addArgument("format", Fmi2Builder.RuntimeFunction.FunctionType.Type.String) - .addArgument("args", Fmi2Builder.RuntimeFunction.FunctionType.Type.Any).useVargs() - .setReturnType(Fmi2Builder.RuntimeFunction.FunctionType.Type.Void).build(); + printFunc = builder.getFunctionBuilder().setName("print").addArgument("format", FmiBuilder.RuntimeFunction.FunctionType.Type.String) + .addArgument("args", FmiBuilder.RuntimeFunction.FunctionType.Type.Any).useVargs() + .setReturnType(FmiBuilder.RuntimeFunction.FunctionType.Type.Void).build(); - printlnFunc = builder.getFunctionBuilder().setName("println").addArgument("format", Fmi2Builder.RuntimeFunction.FunctionType.Type.String) - .addArgument("args", Fmi2Builder.RuntimeFunction.FunctionType.Type.Any).useVargs() - .setReturnType(Fmi2Builder.RuntimeFunction.FunctionType.Type.Void).build(); + printlnFunc = builder.getFunctionBuilder().setName("println").addArgument("format", FmiBuilder.RuntimeFunction.FunctionType.Type.String) + .addArgument("args", FmiBuilder.RuntimeFunction.FunctionType.Type.Any).useVargs() + .setReturnType(FmiBuilder.RuntimeFunction.FunctionType.Type.Void).build(); module.initialize(printFunc, printlnFunc); } diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/DataWriter.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/DataWriter.java index 69f480fed..da0aad597 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/DataWriter.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/DataWriter.java @@ -3,7 +3,7 @@ import org.intocps.maestro.ast.AVariableDeclaration; import org.intocps.maestro.ast.MableAstFactory; import org.intocps.maestro.ast.node.*; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.DynamicActiveBuilderScope; import org.intocps.maestro.framework.fmi2.api.mabl.variables.DoubleVariableFmi2Api; @@ -20,7 +20,7 @@ public class DataWriter { private final MablApiBuilder mablApiBuilder; private final String FUNCTION_CLOSE = "close"; private String moduleIdentifier; - private Fmi2Builder.RuntimeModule runtimeModule; + private FmiBuilder.RuntimeModule runtimeModule; private boolean runtimeModuleMode = false; @@ -31,7 +31,7 @@ public DataWriter(DynamicActiveBuilderScope dynamicScope, MablApiBuilder mablApi this.moduleIdentifier = "dataWriter"; } - public DataWriter(MablApiBuilder mablApiBuilder, Fmi2Builder.RuntimeModule runtimeModule) { + public DataWriter(MablApiBuilder mablApiBuilder, FmiBuilder.RuntimeModule runtimeModule) { this(mablApiBuilder.getDynamicScope(), mablApiBuilder); this.runtimeModuleMode = true; this.runtimeModule = runtimeModule; @@ -86,7 +86,7 @@ public class DataWriterInstance { * The name of the variable with the data writer instance configuration */ private String dataWriterInstanceConfigurationVariableName; - private Fmi2Builder.RuntimeModule runtimeModule; + private FmiBuilder.RuntimeModule runtimeModule; public DataWriterInstance(DynamicActiveBuilderScope dynamicScope, MablApiBuilder mablApiBuilder, DataWriter dataWriter) { @@ -96,7 +96,7 @@ public DataWriterInstance(DynamicActiveBuilderScope dynamicScope, MablApiBuilder } public DataWriterInstance(DynamicActiveBuilderScope dynamicScope, MablApiBuilder mablApiBuilder, DataWriter dataWriter, - Fmi2Builder.RuntimeModule runtimeModule) { + FmiBuilder.RuntimeModule runtimeModule) { this(dynamicScope, mablApiBuilder, dataWriter); this.runtimeModuleMode = true; this.runtimeModule = runtimeModule; @@ -141,8 +141,8 @@ public void log(DoubleVariableFmi2Api time) { if (!initialized) { throw new RuntimeException("DataWriter has not been initialized!"); } - AExpressionStm stm = MableAstFactory.newExpressionStm(MableAstFactory - .newACallExp(MableAstFactory.newAIdentifierExp(this.dataWriter.moduleIdentifier), + AExpressionStm stm = MableAstFactory.newExpressionStm( + MableAstFactory.newACallExp(MableAstFactory.newAIdentifierExp(this.dataWriter.moduleIdentifier), MableAstFactory.newAIdentifier(this.FUNCTION_WRITEDATAPOINT), Stream.concat( Arrays.asList(MableAstFactory.newAIdentifierExp(this.dataWriterInstanceConfigurationVariableName), time.getReferenceExp().clone()).stream(), diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/ExecutionEnvironmentFmi2Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/ExecutionEnvironmentFmi2Api.java index a91d67119..9768f37a9 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/ExecutionEnvironmentFmi2Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/ExecutionEnvironmentFmi2Api.java @@ -1,53 +1,53 @@ package org.intocps.maestro.framework.fmi2.api.mabl; import org.intocps.maestro.ast.node.PStm; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.variables.*; public class ExecutionEnvironmentFmi2Api { - private final Fmi2Builder.RuntimeFunction realFunc; - private final Fmi2Builder.RuntimeFunction boolFunc; - private final Fmi2Builder.RuntimeFunction intFunc; - private final Fmi2Builder.RuntimeFunction stringFunc; - private final Fmi2Builder.RuntimeModule module; + private final FmiBuilder.RuntimeFunction realFunc; + private final FmiBuilder.RuntimeFunction boolFunc; + private final FmiBuilder.RuntimeFunction intFunc; + private final FmiBuilder.RuntimeFunction stringFunc; + private final FmiBuilder.RuntimeModule module; - public ExecutionEnvironmentFmi2Api(MablApiBuilder builder, Fmi2Builder.RuntimeModule module) { + public ExecutionEnvironmentFmi2Api(MablApiBuilder builder, FmiBuilder.RuntimeModule module) { this.module = module; - realFunc = builder.getFunctionBuilder().setName("getReal").addArgument("id", Fmi2Builder.RuntimeFunction.FunctionType.Type.String) - .setReturnType(Fmi2Builder.RuntimeFunction.FunctionType.Type.Double).build(); + realFunc = builder.getFunctionBuilder().setName("getReal").addArgument("id", FmiBuilder.RuntimeFunction.FunctionType.Type.String) + .setReturnType(FmiBuilder.RuntimeFunction.FunctionType.Type.Double).build(); - boolFunc = builder.getFunctionBuilder().setName("getBool").addArgument("id", Fmi2Builder.RuntimeFunction.FunctionType.Type.String) - .setReturnType(Fmi2Builder.RuntimeFunction.FunctionType.Type.Boolean).build(); + boolFunc = builder.getFunctionBuilder().setName("getBool").addArgument("id", FmiBuilder.RuntimeFunction.FunctionType.Type.String) + .setReturnType(FmiBuilder.RuntimeFunction.FunctionType.Type.Boolean).build(); - intFunc = builder.getFunctionBuilder().setName("getInt").addArgument("id", Fmi2Builder.RuntimeFunction.FunctionType.Type.String) - .setReturnType(Fmi2Builder.RuntimeFunction.FunctionType.Type.Int).build(); + intFunc = builder.getFunctionBuilder().setName("getInt").addArgument("id", FmiBuilder.RuntimeFunction.FunctionType.Type.String) + .setReturnType(FmiBuilder.RuntimeFunction.FunctionType.Type.Int).build(); - stringFunc = builder.getFunctionBuilder().setName("getString").addArgument("id", Fmi2Builder.RuntimeFunction.FunctionType.Type.String) - .setReturnType(Fmi2Builder.RuntimeFunction.FunctionType.Type.String).build(); + stringFunc = builder.getFunctionBuilder().setName("getString").addArgument("id", FmiBuilder.RuntimeFunction.FunctionType.Type.String) + .setReturnType(FmiBuilder.RuntimeFunction.FunctionType.Type.String).build(); module.initialize(realFunc, boolFunc, intFunc, stringFunc); } public DoubleVariableFmi2Api getReal(String id) { - Fmi2Builder.Variable v = module.call(realFunc, id); + FmiBuilder.Variable v = module.call(realFunc, id); return (DoubleVariableFmi2Api) v; } public BooleanVariableFmi2Api getBool(String id) { - Fmi2Builder.Variable v = module.call(boolFunc, id); + FmiBuilder.Variable v = module.call(boolFunc, id); return (BooleanVariableFmi2Api) v; } public IntVariableFmi2Api getInt(String id) { - Fmi2Builder.Variable v = module.call(intFunc, id); + FmiBuilder.Variable v = module.call(intFunc, id); return (IntVariableFmi2Api) v; } public StringVariableFmi2Api getString(String id) { - Fmi2Builder.Variable v = module.call(stringFunc, id); + FmiBuilder.Variable v = module.call(stringFunc, id); return (StringVariableFmi2Api) v; } diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/FaultInject.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/FaultInject.java index 449f67dcf..0acbd801a 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/FaultInject.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/FaultInject.java @@ -3,7 +3,7 @@ import org.intocps.maestro.ast.node.AInstanceMappingStm; import org.intocps.maestro.ast.node.PExp; import org.intocps.maestro.ast.node.PStm; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.DynamicActiveBuilderScope; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.IMablScope; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.TryMaBlScope; @@ -29,7 +29,7 @@ public FaultInject(DynamicActiveBuilderScope dynamicScope, MablApiBuilder mablAp this.moduleIdentifier = "faultInject"; } - public FaultInject(MablApiBuilder mablApiBuilder, Fmi2Builder.RuntimeModule runtimeModule) { + public FaultInject(MablApiBuilder mablApiBuilder, FmiBuilder.RuntimeModule runtimeModule) { this(mablApiBuilder.getDynamicScope(), mablApiBuilder); this.moduleIdentifier = runtimeModule.getName(); } @@ -65,11 +65,10 @@ public ComponentVariableFmi2Api faultInject(FmuVariableFmi2Api creator, Componen this.dynamicScope.add(mapping); this.dynamicScope.addAll((Arrays.asList(newAAssignmentStm(newAIdentifierStateDesignator(newAIdentifier(fiComponentName)), - newACallExp(newAIdentifierExp(getModuleIdentifier()), newAIdentifier("faultInject"), - Arrays.asList(newAIdentifierExp(creator.getName()), newAIdentifierExp(component.getName()), - newAStringLiteralExp(constraintId)))), - newIf(newEqual(newAIdentifierExp(fiComponentName), newNullExp()), - newABlockStm(newError(newAStringLiteralExp(fiComponentName + " IS NULL "))), null)))); + newACallExp(newAIdentifierExp(getModuleIdentifier()), newAIdentifier("faultInject"), + Arrays.asList(newAIdentifierExp(creator.getName()), newAIdentifierExp(component.getName()), + newAStringLiteralExp(constraintId)))), newIf(newEqual(newAIdentifierExp(fiComponentName), newNullExp()), + newABlockStm(newError(newAStringLiteralExp(fiComponentName + " IS NULL "))), null)))); return fiComp; } diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/FromMaBLToMaBLAPI.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/FromMaBLToMaBLAPI.java index 0678093c6..7031446d5 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/FromMaBLToMaBLAPI.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/FromMaBLToMaBLAPI.java @@ -7,7 +7,7 @@ import org.intocps.maestro.framework.fmi2.ComponentInfo; import org.intocps.maestro.framework.fmi2.Fmi2SimulationEnvironment; import org.intocps.maestro.framework.fmi2.InstanceInfo; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.variables.ComponentVariableFmi2Api; import org.intocps.maestro.framework.fmi2.api.mabl.variables.FmuVariableFmi2Api; import org.intocps.maestro.framework.fmi2.api.mabl.variables.FmuVariableFmi3Api; @@ -82,8 +82,7 @@ public static Map.Entry getComponentVariableFr } } - public static Map.Entry getInstanceVariableFrom(MablApiBuilder builder, PExp exp, - Fmi2SimulationEnvironment env, + public static Map.Entry getInstanceVariableFrom(MablApiBuilder builder, PExp exp, Fmi2SimulationEnvironment env, String environmentComponentName) throws IllegalAccessException, XPathExpressionException, InvocationTargetException { if (exp instanceof AIdentifierExp) { String componentName = ((AIdentifierExp) exp).getName().getText(); @@ -131,7 +130,7 @@ public static Map.Entry getInstanceVariableFrom } public static void createBindings(Map instances, - ISimulationEnvironment env) throws Fmi2Builder.Port.PortLinkException { + ISimulationEnvironment env) throws FmiBuilder.Port.PortLinkException { for (Map.Entry entry : instances.entrySet()) { java.util.Set relations = getRelations(entry, env); for (IRelation relation : relations.stream().filter(x -> x.getDirection() == Fmi2SimulationEnvironment.Relation.Direction.OutputToInput && @@ -172,7 +171,7 @@ public static void createBindings(Map instance } public static void createBindings3(Map instances, - ISimulationEnvironment env) throws Fmi2Builder.Port.PortLinkException { + ISimulationEnvironment env) throws FmiBuilder.Port.PortLinkException { for (Map.Entry entry : instances.entrySet()) { java.util.Set relations = getRelations3(entry, env); for (IRelation relation : relations.stream().filter(x -> x.getDirection() == Fmi2SimulationEnvironment.Relation.Direction.OutputToInput && diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/FunctionBuilder.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/FunctionBuilder.java index 5b13b2c04..f963e5399 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/FunctionBuilder.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/FunctionBuilder.java @@ -1,16 +1,16 @@ package org.intocps.maestro.framework.fmi2.api.mabl; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import java.util.List; import java.util.Map; import java.util.Vector; -public class FunctionBuilder implements Fmi2Builder.IFunctionBuilder { +public class FunctionBuilder implements FmiBuilder.IFunctionBuilder { String name; - Fmi2Builder.RuntimeFunction.FunctionType returnType; - List> args = new Vector<>(); + FmiBuilder.RuntimeFunction.FunctionType returnType; + List> args = new Vector<>(); boolean usingVargs = false; @Override @@ -21,19 +21,19 @@ public FunctionBuilder setName(String name) { @Override public FunctionBuilder setReturnType(String name) { - returnType = new Fmi2Builder.RuntimeFunction.FunctionType(name); + returnType = new FmiBuilder.RuntimeFunction.FunctionType(name); return this; } @Override - public FunctionBuilder setReturnType(Fmi2Builder.RuntimeFunction.FunctionType.Type type) { - returnType = new Fmi2Builder.RuntimeFunction.FunctionType(type); + public FunctionBuilder setReturnType(FmiBuilder.RuntimeFunction.FunctionType.Type type) { + returnType = new FmiBuilder.RuntimeFunction.FunctionType(type); return this; } @Override - public FunctionBuilder addArgument(String name, Fmi2Builder.RuntimeFunction.FunctionType.Type type) { - Fmi2Builder.RuntimeFunction.FunctionType t = new Fmi2Builder.RuntimeFunction.FunctionType(type); + public FunctionBuilder addArgument(String name, FmiBuilder.RuntimeFunction.FunctionType.Type type) { + FmiBuilder.RuntimeFunction.FunctionType t = new FmiBuilder.RuntimeFunction.FunctionType(type); args.add(Map.entry(name, t)); return this; } @@ -46,20 +46,20 @@ public FunctionBuilder useVargs() { @Override public FunctionBuilder addArgument(String name, String type) { - Fmi2Builder.RuntimeFunction.FunctionType t = new Fmi2Builder.RuntimeFunction.FunctionType(type); + FmiBuilder.RuntimeFunction.FunctionType t = new FmiBuilder.RuntimeFunction.FunctionType(type); args.add(Map.entry(name, t)); return this; } @Override - public Fmi2Builder.RuntimeFunction build() { + public FmiBuilder.RuntimeFunction build() { final String name = this.name; - final Fmi2Builder.RuntimeFunction.FunctionType returnType = this.returnType; - final List> args = new Vector<>(this.args); + final FmiBuilder.RuntimeFunction.FunctionType returnType = this.returnType; + final List> args = new Vector<>(this.args); - return new Fmi2Builder.RuntimeFunction() { + return new FmiBuilder.RuntimeFunction() { @Override public String getName() { return name; diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/LoggerFmi2Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/LoggerFmi2Api.java index 94cb576df..537ab710a 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/LoggerFmi2Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/LoggerFmi2Api.java @@ -1,21 +1,21 @@ package org.intocps.maestro.framework.fmi2.api.mabl; import org.intocps.maestro.ast.node.PStm; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.ScopeFmi2Api; public class LoggerFmi2Api { - final Fmi2Builder.RuntimeModule module; + final FmiBuilder.RuntimeModule module; - final Fmi2Builder.RuntimeFunction logFunction; + final FmiBuilder.RuntimeFunction logFunction; - public LoggerFmi2Api(MablApiBuilder builder, Fmi2Builder.RuntimeModule module) { + public LoggerFmi2Api(MablApiBuilder builder, FmiBuilder.RuntimeModule module) { this.module = module; - logFunction = builder.getFunctionBuilder().setName("log").addArgument("format", Fmi2Builder.RuntimeFunction.FunctionType.Type.String) - .addArgument("args", Fmi2Builder.RuntimeFunction.FunctionType.Type.Any).useVargs() - .setReturnType(Fmi2Builder.RuntimeFunction.FunctionType.Type.Void).build(); + logFunction = builder.getFunctionBuilder().setName("log").addArgument("format", FmiBuilder.RuntimeFunction.FunctionType.Type.String) + .addArgument("args", FmiBuilder.RuntimeFunction.FunctionType.Type.Any).useVargs() + .setReturnType(FmiBuilder.RuntimeFunction.FunctionType.Type.Void).build(); module.initialize(logFunction); } diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/MablApiBuilder.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/MablApiBuilder.java index d4c83d2eb..ac689fb20 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/MablApiBuilder.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/MablApiBuilder.java @@ -8,7 +8,7 @@ import org.intocps.maestro.ast.analysis.DepthFirstAnalysisAdaptor; import org.intocps.maestro.ast.node.*; import org.intocps.maestro.framework.fmi2.api.DerivativeEstimator; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.DynamicActiveBuilderScope; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.IMablScope; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.ScopeFmi2Api; @@ -25,7 +25,7 @@ import static org.intocps.maestro.ast.MableBuilder.newVariable; -public class MablApiBuilder implements Fmi2Builder { +public class MablApiBuilder implements FmiBuilder { static ScopeFmi2Api rootScope; final ScopeFmi2Api externalScope = new ScopeFmi2Api(this); @@ -511,7 +511,7 @@ public void defaultInPStm(PStm node) throws AnalysisException { // TODO: added "import FMI3" after "import FMI2". Should probably figure out a smarter way to do this unit.setImports(Stream.concat(Stream.of(newAIdentifier("FMI2")), - Stream.concat(Stream.of(newAIdentifier("FMI3")), importedModules.stream().map(MableAstFactory::newAIdentifier))) + Stream.concat(Stream.of(newAIdentifier("FMI3")), importedModules.stream().map(MableAstFactory::newAIdentifier))) .collect(Collectors.toList())); @@ -596,12 +596,12 @@ public RealTime getRealTimeModule() { return load("RealTime", runtime -> new RealTime(this, runtime)); } - T load(String moduleType, Function, T> creator, Object... args) { + T load(String moduleType, Function, T> creator, Object... args) { if (instanceCache.containsKey(moduleType)) { return (T) instanceCache.get(moduleType); } - Fmi2Builder.RuntimeModule runtimeModule = this.loadRuntimeModule(this.mainErrorHandlingScope, (s, var) -> { + FmiBuilder.RuntimeModule runtimeModule = this.loadRuntimeModule(this.mainErrorHandlingScope, (s, var) -> { if (args == null || args.length == 0) { ((ScopeFmi2Api) s).getBlock().getBody().addAll(0, var); } else { diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/MathBuilderFmi2Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/MathBuilderFmi2Api.java index 20264a62d..853d12dad 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/MathBuilderFmi2Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/MathBuilderFmi2Api.java @@ -3,7 +3,7 @@ import org.intocps.maestro.ast.node.ARealNumericPrimitiveType; import org.intocps.maestro.ast.node.PExp; import org.intocps.maestro.ast.node.PStm; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.DynamicActiveBuilderScope; import org.intocps.maestro.framework.fmi2.api.mabl.variables.ArrayVariableFmi2Api; import org.intocps.maestro.framework.fmi2.api.mabl.variables.BooleanVariableFmi2Api; @@ -32,8 +32,8 @@ public MathBuilderFmi2Api(DynamicActiveBuilderScope dynamicScope, MablApiBuilder } - private BooleanVariableFmi2Api checkConvergenceInternal(Fmi2Builder.ProvidesTypedReferenceExp a, Fmi2Builder.ProvidesTypedReferenceExp b, - Fmi2Builder.ProvidesTypedReferenceExp absoluteTolerance, Fmi2Builder.ProvidesTypedReferenceExp relativeTolerance) { + private BooleanVariableFmi2Api checkConvergenceInternal(FmiBuilder.ProvidesTypedReferenceExp a, FmiBuilder.ProvidesTypedReferenceExp b, + FmiBuilder.ProvidesTypedReferenceExp absoluteTolerance, FmiBuilder.ProvidesTypedReferenceExp relativeTolerance) { String variableName = dynamicScope.getName("convergence"); PStm stm = newALocalVariableStm(newAVariableDeclaration(newAIdentifier(variableName), newABoleanPrimitiveType(), newAExpInitializer( @@ -45,8 +45,8 @@ private BooleanVariableFmi2Api checkConvergenceInternal(Fmi2Builder.ProvidesType } - public BooleanVariableFmi2Api checkConvergence(Fmi2Builder.ProvidesTypedReferenceExp a, Fmi2Builder.ProvidesTypedReferenceExp b, - Fmi2Builder.DoubleVariable absoluteTolerance, Fmi2Builder.DoubleVariable relativeTolerance) { + public BooleanVariableFmi2Api checkConvergence(FmiBuilder.ProvidesTypedReferenceExp a, FmiBuilder.ProvidesTypedReferenceExp b, + FmiBuilder.DoubleVariable absoluteTolerance, FmiBuilder.DoubleVariable relativeTolerance) { if (Stream.of(a, b, absoluteTolerance, relativeTolerance).allMatch(x -> x.getType() instanceof ARealNumericPrimitiveType)) { return this.checkConvergenceInternal(a, b, absoluteTolerance, relativeTolerance); } else { diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/NumericExpressionValueFmi2Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/NumericExpressionValueFmi2Api.java index 493762cfc..b9e22f7c5 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/NumericExpressionValueFmi2Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/NumericExpressionValueFmi2Api.java @@ -1,7 +1,7 @@ package org.intocps.maestro.framework.fmi2.api.mabl; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder.NumericExpressionValue; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder.NumericExpressionValue; import static org.intocps.maestro.ast.MableAstFactory.*; @@ -23,34 +23,34 @@ public abstract class NumericExpressionValueFmi2Api implements NumericExpression public abstract NumericExpressionValueFmi2Api multiply(double v); - public abstract NumericExpressionValueFmi2Api addition(Fmi2Builder.NumericTypedReferenceExp v); + public abstract NumericExpressionValueFmi2Api addition(FmiBuilder.NumericTypedReferenceExp v); - public abstract NumericExpressionValueFmi2Api divide(Fmi2Builder.NumericTypedReferenceExp v); + public abstract NumericExpressionValueFmi2Api divide(FmiBuilder.NumericTypedReferenceExp v); - public abstract NumericExpressionValueFmi2Api subtraction(Fmi2Builder.NumericTypedReferenceExp v); + public abstract NumericExpressionValueFmi2Api subtraction(FmiBuilder.NumericTypedReferenceExp v); - public abstract NumericExpressionValueFmi2Api multiply(Fmi2Builder.NumericTypedReferenceExp v); + public abstract NumericExpressionValueFmi2Api multiply(FmiBuilder.NumericTypedReferenceExp v); - public PredicateFmi2Api lessThan(Fmi2Builder.NumericTypedReferenceExp var) { + public PredicateFmi2Api lessThan(FmiBuilder.NumericTypedReferenceExp var) { return new PredicateFmi2Api(newALessBinaryExp(getExp(), var.getExp())); } - public PredicateFmi2Api greaterThan(Fmi2Builder.NumericTypedReferenceExp var) { + public PredicateFmi2Api greaterThan(FmiBuilder.NumericTypedReferenceExp var) { return new PredicateFmi2Api(newAGreaterBinaryExp(getExp(), var.getExp())); } - public PredicateFmi2Api equalTo(Fmi2Builder.NumericTypedReferenceExp var) { + public PredicateFmi2Api equalTo(FmiBuilder.NumericTypedReferenceExp var) { return new PredicateFmi2Api(newAEqualBinaryExp(getExp(), var.getExp())); } - public PredicateFmi2Api lessEqualTo(Fmi2Builder.NumericTypedReferenceExp var) { + public PredicateFmi2Api lessEqualTo(FmiBuilder.NumericTypedReferenceExp var) { return new PredicateFmi2Api(newALessEqualBinaryExp(getExp(), var.getExp())); } - public PredicateFmi2Api greaterEqualTo(Fmi2Builder.NumericTypedReferenceExp var) { + public PredicateFmi2Api greaterEqualTo(FmiBuilder.NumericTypedReferenceExp var) { return new PredicateFmi2Api(newAGreaterEqualBinaryExp(getExp(), var.getExp())); } diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/PortFmi2Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/PortFmi2Api.java index bc2cd0fd6..0d8390752 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/PortFmi2Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/PortFmi2Api.java @@ -2,7 +2,7 @@ import org.intocps.maestro.ast.node.PType; import org.intocps.maestro.fmi.Fmi2ModelDescription; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.variables.ComponentVariableFmi2Api; import org.intocps.maestro.framework.fmi2.api.mabl.variables.VariableFmi2Api; @@ -11,7 +11,7 @@ import static org.intocps.maestro.ast.MableAstFactory.*; -public class PortFmi2Api implements Fmi2Builder.Port { +public class PortFmi2Api implements FmiBuilder.Port { public final ComponentVariableFmi2Api aMablFmi2ComponentAPI; public final Fmi2ModelDescription.ScalarVariable scalarVariable; @@ -78,7 +78,7 @@ public Long getPortReferenceValue() { @Override - public void linkTo(Fmi2Builder.Port... receivers) throws PortLinkException { + public void linkTo(FmiBuilder.Port... receivers) throws PortLinkException { if (receivers == null || receivers.length == 0) { return; @@ -88,7 +88,7 @@ public void linkTo(Fmi2Builder.Port... rece throw new PortLinkException("Can only link output ports. This port is: " + this.scalarVariable.causality, this); } - for (Fmi2Builder.Port receiver : receivers) { + for (FmiBuilder.Port receiver : receivers) { PortFmi2Api receiverPort = (PortFmi2Api) receiver; if (receiverPort.scalarVariable.causality != Fmi2ModelDescription.Causality.Input) { diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/PortFmi3Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/PortFmi3Api.java index 69863a1da..303838f7b 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/PortFmi3Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/PortFmi3Api.java @@ -1,20 +1,16 @@ package org.intocps.maestro.framework.fmi2.api.mabl; import org.intocps.maestro.ast.node.PType; -import org.intocps.maestro.fmi.Fmi2ModelDescription; import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3Causality; import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; -import org.intocps.maestro.framework.fmi2.api.mabl.variables.ComponentVariableFmi2Api; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.variables.InstanceVariableFmi3Api; import org.intocps.maestro.framework.fmi2.api.mabl.variables.VariableFmi2Api; import java.util.ArrayList; import java.util.List; -import static org.intocps.maestro.ast.MableAstFactory.*; - -public class PortFmi3Api implements Fmi2Builder.Port { +public class PortFmi3Api implements FmiBuilder.Port { public final InstanceVariableFmi3Api aMablFmi3InstanceAPI; public final Fmi3ModelDescription.Fmi3ScalarVariable scalarVariable; @@ -32,7 +28,8 @@ public PortFmi3Api(InstanceVariableFmi3Api aMablFmi3InstanceAPI, Fmi3ModelDescri @Override public String toString() { - return "Port( '" + aMablFmi3InstanceAPI.getName() + "." + scalarVariable.getVariable().getName() + "' , '" + scalarVariable.getVariable().getTypeIdentifier().name() + "')"; + return "Port( '" + aMablFmi3InstanceAPI.getName() + "." + scalarVariable.getVariable().getName() + "' , '" + + scalarVariable.getVariable().getTypeIdentifier().name() + "')"; } public VariableFmi2Api getSharedAsVariable() { @@ -45,15 +42,15 @@ public void setSharedAsVariable(VariableFmi2Api sharedAsVariable) { public PType getType() { switch (scalarVariable.getVariable().getTypeIdentifier()) { -// case Boolean: -// return newBoleanType(); -// case Real: -// return newRealType(); -// case Integer: -// return newIntType(); -// case String: -// return newStringType(); -// case Enumeration: + // case Boolean: + // return newBoleanType(); + // case Real: + // return newRealType(); + // case Integer: + // return newIntType(); + // case String: + // return newStringType(); + // case Enumeration: default: return null; } @@ -61,8 +58,7 @@ public PType getType() { @Override public String getQualifiedName() { - return this.aMablFmi3InstanceAPI.getOwner().getFmuIdentifier() + "." + this.aMablFmi3InstanceAPI.getEnvironmentName() + "." + - this.getName(); + return this.aMablFmi3InstanceAPI.getOwner().getFmuIdentifier() + "." + this.aMablFmi3InstanceAPI.getEnvironmentName() + "." + this.getName(); } @Override @@ -82,7 +78,7 @@ public Long getPortReferenceValue() { @Override - public void linkTo(Fmi2Builder.Port... receivers) throws PortLinkException { + public void linkTo(FmiBuilder.Port... receivers) throws PortLinkException { if (receivers == null || receivers.length == 0) { return; @@ -92,12 +88,12 @@ public void linkTo(Fmi2Builder.Port... throw new PortLinkException("Can only link output ports. This port is: " + this.scalarVariable.getVariable().getCausality(), this); } - for (Fmi2Builder.Port receiver : receivers) { + for (FmiBuilder.Port receiver : receivers) { PortFmi3Api receiverPort = (PortFmi3Api) receiver; if (receiverPort.scalarVariable.getVariable().getCausality() != Fmi3Causality.Input) { - throw new PortLinkException("Receivers must be input ports. This receiver is: " + receiverPort.scalarVariable.getVariable().getCausality(), - receiverPort); + throw new PortLinkException( + "Receivers must be input ports. This receiver is: " + receiverPort.scalarVariable.getVariable().getCausality(), receiverPort); } // HEJ: TBD - This check fails with "already linked" in expansion since both rbmq fmus connect to single actuation @@ -144,8 +140,7 @@ public String toLexName() { } public String getMultiModelScalarVariableName() { - return this.aMablFmi3InstanceAPI.getOwner().getFmuIdentifier() + "." + this.aMablFmi3InstanceAPI.getEnvironmentName() + "." + - this.getName(); + return this.aMablFmi3InstanceAPI.getOwner().getFmuIdentifier() + "." + this.aMablFmi3InstanceAPI.getEnvironmentName() + "." + this.getName(); } public String getMultiModelScalarVariableNameWithoutFmu() { diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/PredicateFmi2Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/PredicateFmi2Api.java index 58ab735bb..47b3f8d9e 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/PredicateFmi2Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/PredicateFmi2Api.java @@ -2,13 +2,13 @@ import org.intocps.maestro.ast.node.PExp; import org.intocps.maestro.ast.node.PType; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.variables.BooleanVariableFmi2Api; import org.intocps.maestro.framework.fmi2.api.mabl.variables.VariableUtil; import static org.intocps.maestro.ast.MableAstFactory.*; -public class PredicateFmi2Api implements Fmi2Builder.Predicate, Fmi2Builder.ProvidesTypedReferenceExp { +public class PredicateFmi2Api implements FmiBuilder.Predicate, FmiBuilder.ProvidesTypedReferenceExp { private final PExp exp; @@ -27,7 +27,7 @@ public PredicateFmi2Api or(PredicateFmi2Api p) { } @Override - public PredicateFmi2Api and(Fmi2Builder.Predicate p) { + public PredicateFmi2Api and(FmiBuilder.Predicate p) { if (p instanceof PredicateFmi2Api) { return this.and((PredicateFmi2Api) p); } else { @@ -36,7 +36,7 @@ public PredicateFmi2Api and(Fmi2Builder.Predicate p) { } @Override - public PredicateFmi2Api or(Fmi2Builder.Predicate p) { + public PredicateFmi2Api or(FmiBuilder.Predicate p) { if (p instanceof PredicateFmi2Api) { return this.or((PredicateFmi2Api) p); } else { diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/RealTime.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/RealTime.java index 52c6f3ef5..48c3b58bd 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/RealTime.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/RealTime.java @@ -4,7 +4,7 @@ import org.intocps.maestro.ast.node.AExpressionStm; import org.intocps.maestro.ast.node.PExp; import org.intocps.maestro.ast.node.PStm; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.DynamicActiveBuilderScope; import org.intocps.maestro.framework.fmi2.api.mabl.variables.DoubleVariableFmi2Api; @@ -25,7 +25,7 @@ public RealTime(DynamicActiveBuilderScope dynamicScope, MablApiBuilder mablApiBu this.moduleIdentifier = "realTime"; } - public RealTime(MablApiBuilder mablApiBuilder, Fmi2Builder.RuntimeModule runtimeModule) { + public RealTime(MablApiBuilder mablApiBuilder, FmiBuilder.RuntimeModule runtimeModule) { this(mablApiBuilder.getDynamicScope(), mablApiBuilder); this.moduleIdentifier = runtimeModule.getName(); } diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/SimulationControl.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/SimulationControl.java index 7a1c219cd..988d2408d 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/SimulationControl.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/SimulationControl.java @@ -1,29 +1,29 @@ package org.intocps.maestro.framework.fmi2.api.mabl; import org.intocps.maestro.ast.node.PStm; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.variables.BooleanVariableFmi2Api; import org.intocps.maestro.framework.fmi2.api.mabl.variables.VariableFmi2Api; public class SimulationControl { @org.jetbrains.annotations.NotNull private final MablApiBuilder builder; - private final Fmi2Builder.RuntimeModule module; - private final Fmi2Builder.RuntimeFunction stopRequestedFunc; + private final FmiBuilder.RuntimeModule module; + private final FmiBuilder.RuntimeFunction stopRequestedFunc; - public SimulationControl(MablApiBuilder builder, Fmi2Builder.RuntimeModule module) { + public SimulationControl(MablApiBuilder builder, FmiBuilder.RuntimeModule module) { this.builder = builder; this.module = module; stopRequestedFunc = - builder.getFunctionBuilder().setName("stopRequested").setReturnType(Fmi2Builder.RuntimeFunction.FunctionType.Type.Boolean).build(); + builder.getFunctionBuilder().setName("stopRequested").setReturnType(FmiBuilder.RuntimeFunction.FunctionType.Type.Boolean).build(); module.initialize(stopRequestedFunc); } public BooleanVariableFmi2Api stopRequested() { - Fmi2Builder.Variable res = module.call(stopRequestedFunc); + FmiBuilder.Variable res = module.call(stopRequestedFunc); VariableFmi2Api r2 = (VariableFmi2Api) res; return new BooleanVariableFmi2Api(r2.getDeclaringStm(), r2.getDeclaredScope(), builder.getDynamicScope(), r2.getDesignator(), diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/VariableStep.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/VariableStep.java index 55b94515f..eecd3e7f7 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/VariableStep.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/VariableStep.java @@ -2,7 +2,7 @@ import org.intocps.maestro.ast.MableAstFactory; import org.intocps.maestro.ast.node.*; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.DynamicActiveBuilderScope; import org.intocps.maestro.framework.fmi2.api.mabl.variables.*; @@ -15,7 +15,7 @@ public class VariableStep { private final DynamicActiveBuilderScope dynamicScope; private final MablApiBuilder mablApiBuilder; private String moduleIdentifier; - private Fmi2Builder.RuntimeModule runtimeModule; + private FmiBuilder.RuntimeModule runtimeModule; private boolean runtimeModuleMode = false; @@ -25,7 +25,7 @@ public VariableStep(DynamicActiveBuilderScope dynamicScope, MablApiBuilder mablA this.moduleIdentifier = "variableStep"; } - public VariableStep(MablApiBuilder mablApiBuilder, Fmi2Builder.RuntimeModule runtimeModule) { + public VariableStep(MablApiBuilder mablApiBuilder, FmiBuilder.RuntimeModule runtimeModule) { this(mablApiBuilder.getDynamicScope(), mablApiBuilder); this.runtimeModuleMode = true; this.runtimeModule = runtimeModule; @@ -71,7 +71,7 @@ public class VariableStepInstance { /** * The name of the variable with the variable step instance configuration */ - private Fmi2Builder.RuntimeModule runtimeModule; + private FmiBuilder.RuntimeModule runtimeModule; private String variableStepConfigurationIdentifier; private String portsWithDataIdentifier; @@ -84,7 +84,7 @@ public VariableStepInstance(DynamicActiveBuilderScope dynamicScope, MablApiBuild } public VariableStepInstance(DynamicActiveBuilderScope dynamicScope, MablApiBuilder mablApiBuilder, VariableStep variableStep, - Fmi2Builder.RuntimeModule runtimeModule) { + FmiBuilder.RuntimeModule runtimeModule) { this(dynamicScope, mablApiBuilder, variableStep); this.runtimeModuleMode = true; this.runtimeModule = runtimeModule; @@ -128,8 +128,8 @@ public DoubleVariableFmi2Api getStepSize(DoubleVariableFmi2Api simTime) { AExpressionStm addDataPointStm; PStm targetVarStm; - addDataPointStm = MableAstFactory.newExpressionStm(MableAstFactory - .newACallExp(MableAstFactory.newAIdentifierExp(this.variableStep.getModuleIdentifier()), + addDataPointStm = MableAstFactory.newExpressionStm( + MableAstFactory.newACallExp(MableAstFactory.newAIdentifierExp(this.variableStep.getModuleIdentifier()), MableAstFactory.newAIdentifier(FUNCTION_ADDDATAPOINT), Arrays.asList(MableAstFactory.newAIdentifierExp(variableStepConfigurationIdentifier), simTime.getExp(), MableAstFactory.newAIdentifierExp(portsWithDataIdentifier)))); @@ -196,8 +196,8 @@ public void initialize(Map fmus //ports with data variable List portsWithData = ports.stream().map(p -> p.getSharedAsVariable().getReferenceExp().clone()).collect(Collectors.toList()); - portsWithDataStm = MableAstFactory.newALocalVariableStm(MableAstFactory - .newAVariableDeclaration(MableAstFactory.newAIdentifier(portsWithDataIdentifier), + portsWithDataStm = MableAstFactory.newALocalVariableStm( + MableAstFactory.newAVariableDeclaration(MableAstFactory.newAIdentifier(portsWithDataIdentifier), MableAstFactory.newAArrayType(MableAstFactory.newARealNumericPrimitiveType()), portsWithData.size(), portsWithData.size() > 0 ? MableAstFactory.newAArrayInitializer(portsWithData) : null)); @@ -205,23 +205,23 @@ public void initialize(Map fmus //fmu names variable List fmuNames = fmus.entrySet().stream().map(v -> v.getKey().getExp()).collect(Collectors.toList()); - fmuNamesStm = MableAstFactory.newALocalVariableStm(MableAstFactory - .newAVariableDeclaration(MableAstFactory.newAIdentifier(fmuInstanceNamesIdentifier), + fmuNamesStm = MableAstFactory.newALocalVariableStm( + MableAstFactory.newAVariableDeclaration(MableAstFactory.newAIdentifier(fmuInstanceNamesIdentifier), MableAstFactory.newAArrayType(MableAstFactory.newAStringPrimitiveType()), fmuNames.size(), MableAstFactory.newAArrayInitializer(fmuNames))); //fmu instances variable List fmuInstances = fmus.values().stream().map(x -> x.getReferenceExp().clone()).collect(Collectors.toList()); - fmuInstancesStm = MableAstFactory.newALocalVariableStm(MableAstFactory - .newAVariableDeclaration(MableAstFactory.newAIdentifier(fmuInstancesIdentifier), + fmuInstancesStm = MableAstFactory.newALocalVariableStm( + MableAstFactory.newAVariableDeclaration(MableAstFactory.newAIdentifier(fmuInstancesIdentifier), MableAstFactory.newAArrayType(MableAstFactory.newANameType("FMI2Component")), fmuInstances.size(), MableAstFactory.newAArrayInitializer(fmuInstances))); //setFMUs function - setFMUsStm = MableAstFactory.newALocalVariableStm(MableAstFactory - .newAVariableDeclaration(MableAstFactory.newAIdentifier(variableStepConfigurationIdentifier), - MableAstFactory.newANameType(TYPE_VARIABLESTEPCONFIG), MableAstFactory.newAExpInitializer(MableAstFactory - .newACallExp(MableAstFactory.newAIdentifierExp(this.variableStep.getModuleIdentifier()), + setFMUsStm = MableAstFactory.newALocalVariableStm( + MableAstFactory.newAVariableDeclaration(MableAstFactory.newAIdentifier(variableStepConfigurationIdentifier), + MableAstFactory.newANameType(TYPE_VARIABLESTEPCONFIG), MableAstFactory.newAExpInitializer( + MableAstFactory.newACallExp(MableAstFactory.newAIdentifierExp(this.variableStep.getModuleIdentifier()), MableAstFactory.newAIdentifier(FUNCTION_SETFMUS), Arrays.asList(MableAstFactory.newAIdentifierExp(fmuInstanceNamesIdentifier), MableAstFactory.newAIdentifierExp(fmuInstancesIdentifier)))))); @@ -231,22 +231,22 @@ public void initialize(Map fmus List portNames = ports.stream().map(p -> MableAstFactory.newAStringLiteralExp(p.getMultiModelScalarVariableName())).collect(Collectors.toList()); - portNamesStm = MableAstFactory.newALocalVariableStm(MableAstFactory - .newAVariableDeclaration(MableAstFactory.newAIdentifier(portNamesIdentifier), + portNamesStm = MableAstFactory.newALocalVariableStm( + MableAstFactory.newAVariableDeclaration(MableAstFactory.newAIdentifier(portNamesIdentifier), MableAstFactory.newAArrayType(MableAstFactory.newAStringPrimitiveType()), portNames.size(), portNames.size() > 0 ? MableAstFactory.newAArrayInitializer(portNames) : null)); //initializePortNames function - initializePortNamesStm = MableAstFactory.newExpressionStm(MableAstFactory - .newACallExp(MableAstFactory.newAIdentifierExp(this.variableStep.getModuleIdentifier()), + initializePortNamesStm = MableAstFactory.newExpressionStm( + MableAstFactory.newACallExp(MableAstFactory.newAIdentifierExp(this.variableStep.getModuleIdentifier()), MableAstFactory.newAIdentifier(FUNCTION_INITIALIZEPORTNAMES), Arrays.asList(MableAstFactory.newAIdentifierExp(variableStepConfigurationIdentifier), MableAstFactory.newAIdentifierExp(portNamesIdentifier)))); //setEndTime function - setEndTimeStm = MableAstFactory.newExpressionStm(MableAstFactory - .newACallExp(MableAstFactory.newAIdentifierExp(this.variableStep.getModuleIdentifier()), + setEndTimeStm = MableAstFactory.newExpressionStm( + MableAstFactory.newACallExp(MableAstFactory.newAIdentifierExp(this.variableStep.getModuleIdentifier()), MableAstFactory.newAIdentifier(FUNCTION_SETENDTIME), Arrays.asList(MableAstFactory.newAIdentifierExp(variableStepConfigurationIdentifier), endTime.getExp()))); diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/DynamicActiveBuilderScope.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/DynamicActiveBuilderScope.java index c0821a3e7..43fa0fa2b 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/DynamicActiveBuilderScope.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/DynamicActiveBuilderScope.java @@ -3,14 +3,14 @@ import org.intocps.maestro.ast.node.PStm; import org.intocps.maestro.fmi.Fmi2ModelDescription; import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.variables.*; import java.net.URI; import java.util.Collection; import java.util.Set; -public class DynamicActiveBuilderScope implements IMablScope, Fmi2Builder.DynamicActiveScope { +public class DynamicActiveBuilderScope implements IMablScope, FmiBuilder.DynamicActiveScope { final private IMablScope root; private IMablScope activeScope; @@ -29,18 +29,18 @@ public IMablScope activate(ScopeFmi2Api activeScope) { return this.activeScope; } - Fmi2Builder.Scope getRootScope() { + FmiBuilder.Scope getRootScope() { return root; } @Override - public WhileMaBLScope enterWhile(Fmi2Builder.Predicate predicate) { + public WhileMaBLScope enterWhile(FmiBuilder.Predicate predicate) { return activeScope.enterWhile(predicate); } @Override - public IfMaBlScope enterIf(Fmi2Builder.Predicate predicate) { + public IfMaBlScope enterIf(FmiBuilder.Predicate predicate) { return activeScope.enterIf(predicate); } @@ -56,7 +56,7 @@ public ScopeFmi2Api leave() { @Override - public Fmi2Builder.ScopeElement parent() { + public FmiBuilder.ScopeElement parent() { return this.activeScope.parent(); } @@ -66,7 +66,7 @@ public PStm getDeclaration() { } @Override - public

> P findParent(Class

clz) { + public

> P findParent(Class

clz) { return this.activeScope.findParent(clz); } @@ -186,7 +186,7 @@ public ArrayVariableFmi2Api store(String name, V value[]) { } @Override - public Fmi2Builder.Variable store(Fmi2Builder.Value tag) { + public FmiBuilder.Variable store(FmiBuilder.Value tag) { return activeScope.store(tag); } diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/IMablScope.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/IMablScope.java index 85bcc8d43..93c2b9069 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/IMablScope.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/IMablScope.java @@ -3,17 +3,17 @@ import org.intocps.maestro.ast.node.PStm; import org.intocps.maestro.fmi.Fmi2ModelDescription; import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.variables.*; import java.net.URI; import java.util.Collection; import java.util.Set; -public interface IMablScope extends Fmi2Builder.Scope { +public interface IMablScope extends FmiBuilder.Scope { @Override - Fmi2Builder.ScopeElement parent(); + FmiBuilder.ScopeElement parent(); IntVariableFmi2Api getFmiStatusVariable(); @@ -29,10 +29,10 @@ public interface IMablScope extends Fmi2Builder.Scope { BooleanVariableFmi2Api store(boolean value); @Override - WhileMaBLScope enterWhile(Fmi2Builder.Predicate predicate); + WhileMaBLScope enterWhile(FmiBuilder.Predicate predicate); @Override - IfMaBlScope enterIf(Fmi2Builder.Predicate predicate); + IfMaBlScope enterIf(FmiBuilder.Predicate predicate); @Override IMablScope parallel(); @@ -85,7 +85,7 @@ public interface IMablScope extends Fmi2Builder.Scope { ArrayVariableFmi2Api store(String name, V value[]); @Override - Fmi2Builder.Variable store(Fmi2Builder.Value tag); + FmiBuilder.Variable store(FmiBuilder.Value tag); IntVariableFmi2Api store(String stabilisation_loop, IntVariableFmi2Api stabilisation_loop_max_iterations); @@ -99,6 +99,7 @@ public interface IMablScope extends Fmi2Builder.Scope { FmuVariableFmi2Api createFMU(String name, String loaderName, String... args) throws Exception; FmuVariableFmi3Api createFMU(String name, Fmi3ModelDescription modelDescription, URI path) throws Exception; + FmuVariableFmi3Api createFMU3(String name, String loaderName, String... args) throws Exception; Var copy(String name, Var variable); diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/IfMaBlScope.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/IfMaBlScope.java index be1afb2b5..7518244f4 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/IfMaBlScope.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/IfMaBlScope.java @@ -1,10 +1,10 @@ package org.intocps.maestro.framework.fmi2.api.mabl.scoping; import org.intocps.maestro.ast.node.PStm; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.MablApiBuilder; -public class IfMaBlScope implements Fmi2Builder.IfScope { +public class IfMaBlScope implements FmiBuilder.IfScope { private final MablApiBuilder builder; private final PStm declaration; private final ScopeFmi2Api declaringScope; @@ -37,7 +37,7 @@ public ScopeFmi2Api leave() { } @Override - public Fmi2Builder.Scoping parent() { + public FmiBuilder.Scoping parent() { return this.declaringScope; } @@ -47,8 +47,8 @@ public PStm getDeclaration() { } @Override - public

> P findParent(Class

clz) { - Fmi2Builder.ScopeElement parent = this; + public

> P findParent(Class

clz) { + FmiBuilder.ScopeElement parent = this; while ((parent = parent.parent()) != null) { if (clz.isAssignableFrom(parent.getClass())) { return clz.cast(parent()); diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/ScopeFmi2Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/ScopeFmi2Api.java index 721c4847c..2633507df 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/ScopeFmi2Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/ScopeFmi2Api.java @@ -6,7 +6,7 @@ import org.intocps.maestro.ast.node.*; import org.intocps.maestro.fmi.Fmi2ModelDescription; import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.MablApiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.PredicateFmi2Api; import org.intocps.maestro.framework.fmi2.api.mabl.values.*; @@ -21,11 +21,11 @@ import static org.intocps.maestro.ast.MableAstFactory.*; import static org.intocps.maestro.ast.MableBuilder.newVariable; -public class ScopeFmi2Api implements IMablScope, Fmi2Builder.WhileScope { +public class ScopeFmi2Api implements IMablScope, FmiBuilder.WhileScope { private final MablApiBuilder builder; private final SBlockStm block; private final List fmi2ComponentVariables = new ArrayList<>(); - Fmi2Builder.ScopeElement parent; + FmiBuilder.ScopeElement parent; IntVariableFmi2Api fmiStatusVariable = null; public ScopeFmi2Api(MablApiBuilder builder) { @@ -35,7 +35,7 @@ public ScopeFmi2Api(MablApiBuilder builder) { } - public ScopeFmi2Api(MablApiBuilder builder, Fmi2Builder.ScopeElement parent, SBlockStm block) { + public ScopeFmi2Api(MablApiBuilder builder, FmiBuilder.ScopeElement parent, SBlockStm block) { this.builder = builder; this.parent = parent; this.block = block; @@ -46,7 +46,7 @@ public SBlockStm getBlock() { } @Override - public WhileMaBLScope enterWhile(Fmi2Builder.Predicate predicate) { + public WhileMaBLScope enterWhile(FmiBuilder.Predicate predicate) { if (predicate instanceof PredicateFmi2Api) { PredicateFmi2Api predicate_ = (PredicateFmi2Api) predicate; SBlockStm whileBlock = new ABasicBlockStm(); @@ -75,7 +75,7 @@ public TryMaBlScope enterTry() { @Override - public IfMaBlScope enterIf(Fmi2Builder.Predicate predicate) { + public IfMaBlScope enterIf(FmiBuilder.Predicate predicate) { if (predicate instanceof PredicateFmi2Api) { PredicateFmi2Api predicate_ = (PredicateFmi2Api) predicate; @@ -324,7 +324,7 @@ private ArrayVariableFmi2Api instantiateMDArrayRecursively(V[] array, PSt List> variables = new ArrayList<>(); for (int i = 0; i < array.length; i++) { PType type; - Fmi2Builder.ExpressionValue value; + FmiBuilder.ExpressionValue value; if (array instanceof Double[]) { type = newARealNumericPrimitiveType(); @@ -420,7 +420,7 @@ public IMablScope enterScope() { @Override - public Fmi2Builder.Variable store(Fmi2Builder.Value tag) { + public FmiBuilder.Variable store(FmiBuilder.Value tag) { return storePrivate(builder.getNameGenerator().getName(), tag); } @@ -456,7 +456,7 @@ public ArrayVariableFmi2Api storeInArray(String namePrefix, VariableFmi2Api[] va newAIdentifierExp(name), Arrays.asList(variables)); } - private Fmi2Builder.Variable storePrivate(String name, Fmi2Builder.Value tag) { + private FmiBuilder.Variable storePrivate(String name, FmiBuilder.Value tag) { if (!(tag instanceof ValueFmi2Api)) { throw new IllegalArgumentException(); @@ -465,7 +465,7 @@ private Fmi2Builder.Variable storePrivate(String name, Fmi2Builder. ValueFmi2Api v = (ValueFmi2Api) tag; PExp initial = null; - Fmi2Builder.Variable variable; + FmiBuilder.Variable variable; if (v.getType() instanceof ARealNumericPrimitiveType) { if (v.get() != null) { @@ -559,7 +559,7 @@ public FmuVariableFmi2Api createFMU(String name, Fmi2ModelDescription modelDescr } @Override - public Fmi2Builder.ScopeElement parent() { + public FmiBuilder.ScopeElement parent() { return this.parent; } @@ -569,7 +569,7 @@ public PStm getDeclaration() { } @Override - public

> P findParent(Class

clz) { + public

> P findParent(Class

clz) { return this.findParentScope(clz); } @@ -595,7 +595,7 @@ public IntVariableFmi2Api getFmiStatusVariable() { } } else { //ignore try and if - Fmi2Builder.ScopeElement p = parent; + FmiBuilder.ScopeElement p = parent; while ((p = p.parent()) != null) { if (p instanceof ScopeFmi2Api) { return ((ScopeFmi2Api) p).getFmiStatusVariable(); @@ -614,10 +614,9 @@ public void registerComponentVariableFmi2Api(ComponentVariableFmi2Api componentV } - @Override public S findParentScope(Class type) { - Fmi2Builder.ScopeElement p = this; + FmiBuilder.ScopeElement p = this; while ((p = p.parent()) != null) { if (type.isAssignableFrom(p.getClass())) { return type.cast(p); diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/TryMaBlScope.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/TryMaBlScope.java index 2fd77310d..eb72571f6 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/TryMaBlScope.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/TryMaBlScope.java @@ -1,12 +1,12 @@ package org.intocps.maestro.framework.fmi2.api.mabl.scoping; import org.intocps.maestro.ast.node.PStm; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.MablApiBuilder; import static org.intocps.maestro.ast.MableAstFactory.newABlockStm; -public class TryMaBlScope implements Fmi2Builder.TryScope { +public class TryMaBlScope implements FmiBuilder.TryScope { private final MablApiBuilder builder; private final PStm declaration; private final ScopeFmi2Api declaringScope; @@ -72,8 +72,8 @@ public PStm getDeclaration() { } @Override - public

> P findParent(Class

clz) { - Fmi2Builder.ScopeElement parent = this; + public

> P findParent(Class

clz) { + FmiBuilder.ScopeElement parent = this; while ((parent = parent.parent()) != null) { if (clz.isAssignableFrom(parent.getClass())) { return clz.cast(parent()); diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/WhileMaBLScope.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/WhileMaBLScope.java index 5158c6a19..3db3b602e 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/WhileMaBLScope.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/WhileMaBLScope.java @@ -2,10 +2,10 @@ import org.intocps.maestro.ast.node.PStm; import org.intocps.maestro.ast.node.SBlockStm; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.MablApiBuilder; -public class WhileMaBLScope extends ScopeFmi2Api implements Fmi2Builder.WhileScope { +public class WhileMaBLScope extends ScopeFmi2Api implements FmiBuilder.WhileScope { private final MablApiBuilder builder; private final PStm declaration; private final SBlockStm block; diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/BooleanExpressionValue.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/BooleanExpressionValue.java index 5956bc001..fb891d632 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/BooleanExpressionValue.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/BooleanExpressionValue.java @@ -1,12 +1,12 @@ package org.intocps.maestro.framework.fmi2.api.mabl.values; import org.intocps.maestro.ast.node.PExp; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.PredicateFmi2Api; import static org.intocps.maestro.ast.MableAstFactory.newABoolLiteralExp; -public class BooleanExpressionValue extends PredicateFmi2Api implements Fmi2Builder.ExpressionValue, Fmi2Builder.BooleanExpressionValue { +public class BooleanExpressionValue extends PredicateFmi2Api implements FmiBuilder.ExpressionValue, FmiBuilder.BooleanExpressionValue { public BooleanExpressionValue(PExp exp) { super(exp); diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/DoubleExpressionValue.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/DoubleExpressionValue.java index c098b10b3..04cab6221 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/DoubleExpressionValue.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/DoubleExpressionValue.java @@ -3,14 +3,14 @@ import org.intocps.maestro.ast.node.ARealNumericPrimitiveType; import org.intocps.maestro.ast.node.PExp; import org.intocps.maestro.ast.node.PType; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.NumericExpressionValueFmi2Api; import org.intocps.maestro.framework.fmi2.api.mabl.PredicateFmi2Api; import static org.intocps.maestro.ast.MableAstFactory.*; -public class DoubleExpressionValue extends NumericExpressionValueFmi2Api implements Fmi2Builder.DoubleExpressionValue { +public class DoubleExpressionValue extends NumericExpressionValueFmi2Api implements FmiBuilder.DoubleExpressionValue { final PType type = new ARealNumericPrimitiveType(); final PExp exp; @@ -79,27 +79,27 @@ public DoubleExpressionValue multiply(double v) { } @Override - public DoubleExpressionValue addition(Fmi2Builder.NumericTypedReferenceExp v) { + public DoubleExpressionValue addition(FmiBuilder.NumericTypedReferenceExp v) { return new DoubleExpressionValue(newPlusExp(getExp(), v.getExp())); } @Override - public DoubleExpressionValue divide(Fmi2Builder.NumericTypedReferenceExp v) { + public DoubleExpressionValue divide(FmiBuilder.NumericTypedReferenceExp v) { return new DoubleExpressionValue(newDivideExp(getExp(), v.getExp())); } @Override - public DoubleExpressionValue subtraction(Fmi2Builder.NumericTypedReferenceExp v) { + public DoubleExpressionValue subtraction(FmiBuilder.NumericTypedReferenceExp v) { return new DoubleExpressionValue(newMinusExp(getExp(), v.getExp())); } @Override - public DoubleExpressionValue multiply(Fmi2Builder.NumericTypedReferenceExp v) { + public DoubleExpressionValue multiply(FmiBuilder.NumericTypedReferenceExp v) { return new DoubleExpressionValue(newMultiplyExp(getExp(), v.getExp())); } @Override - public PredicateFmi2Api lessThan(Fmi2Builder.NumericTypedReferenceExp endTimeVar) { + public PredicateFmi2Api lessThan(FmiBuilder.NumericTypedReferenceExp endTimeVar) { return new PredicateFmi2Api(newALessBinaryExp(getExp(), endTimeVar.getExp())); } } diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/IntExpressionValue.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/IntExpressionValue.java index 98c494d3e..3566077ea 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/IntExpressionValue.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/IntExpressionValue.java @@ -3,13 +3,13 @@ import org.intocps.maestro.ast.node.AIntNumericPrimitiveType; import org.intocps.maestro.ast.node.PExp; import org.intocps.maestro.ast.node.PType; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.NumericExpressionValueFmi2Api; import static org.intocps.maestro.ast.MableAstFactory.*; -public class IntExpressionValue extends NumericExpressionValueFmi2Api implements Fmi2Builder.IntExpressionValue { +public class IntExpressionValue extends NumericExpressionValueFmi2Api implements FmiBuilder.IntExpressionValue { final PType type = new AIntNumericPrimitiveType(); final PExp exp; @@ -79,7 +79,7 @@ public DoubleExpressionValue multiply(double v) { } @Override - public NumericExpressionValueFmi2Api addition(Fmi2Builder.NumericTypedReferenceExp v) { + public NumericExpressionValueFmi2Api addition(FmiBuilder.NumericTypedReferenceExp v) { if (v instanceof DoubleExpressionValue) { return new DoubleExpressionValue(newPlusExp(this.getExp(), v.getExp())); } else if (v instanceof IntExpressionValue) { @@ -90,7 +90,7 @@ public NumericExpressionValueFmi2Api addition(Fmi2Builder.NumericTypedReferenceE } @Override - public NumericExpressionValueFmi2Api divide(Fmi2Builder.NumericTypedReferenceExp v) { + public NumericExpressionValueFmi2Api divide(FmiBuilder.NumericTypedReferenceExp v) { if (v instanceof DoubleExpressionValue || v instanceof IntExpressionValue) { return new DoubleExpressionValue(newDivideExp(this.getExp(), v.getExp())); } else { @@ -99,7 +99,7 @@ public NumericExpressionValueFmi2Api divide(Fmi2Builder.NumericTypedReferenceExp } @Override - public NumericExpressionValueFmi2Api subtraction(Fmi2Builder.NumericTypedReferenceExp v) { + public NumericExpressionValueFmi2Api subtraction(FmiBuilder.NumericTypedReferenceExp v) { if (v instanceof DoubleExpressionValue) { return new DoubleExpressionValue(newMinusExp(this.getExp(), v.getExp())); } else if (v instanceof IntExpressionValue) { @@ -110,7 +110,7 @@ public NumericExpressionValueFmi2Api subtraction(Fmi2Builder.NumericTypedReferen } @Override - public NumericExpressionValueFmi2Api multiply(Fmi2Builder.NumericTypedReferenceExp v) { + public NumericExpressionValueFmi2Api multiply(FmiBuilder.NumericTypedReferenceExp v) { if (v instanceof DoubleExpressionValue) { return new DoubleExpressionValue(newMultiplyExp(this.getExp(), v.getExp())); } else if (v instanceof IntExpressionValue) { diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/PortValueExpresssionMapImpl.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/PortValueExpresssionMapImpl.java index 21eb559fa..52c02e5c5 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/PortValueExpresssionMapImpl.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/PortValueExpresssionMapImpl.java @@ -1,11 +1,11 @@ package org.intocps.maestro.framework.fmi2.api.mabl.values; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import java.util.HashMap; import java.util.Map; -public class PortValueExpresssionMapImpl extends HashMap, Fmi2Builder.ExpressionValue> implements Fmi2Builder.Fmi2ComponentVariable.PortExpressionValueMap { +public class PortValueExpresssionMapImpl extends HashMap, FmiBuilder.ExpressionValue> implements FmiBuilder.Fmi2ComponentVariable.PortExpressionValueMap { public PortValueExpresssionMapImpl(int initialCapacity, float loadFactor) { super(initialCapacity, loadFactor); } @@ -17,7 +17,7 @@ public PortValueExpresssionMapImpl(int initialCapacity) { public PortValueExpresssionMapImpl() { } - public PortValueExpresssionMapImpl(Map, ? extends Fmi2Builder.ExpressionValue> m) { + public PortValueExpresssionMapImpl(Map, ? extends FmiBuilder.ExpressionValue> m) { super(m); } } diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/PortValueMapImpl.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/PortValueMapImpl.java index 2a05839eb..0a6171ac6 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/PortValueMapImpl.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/PortValueMapImpl.java @@ -1,11 +1,11 @@ package org.intocps.maestro.framework.fmi2.api.mabl.values; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import java.util.HashMap; import java.util.Map; -public class PortValueMapImpl extends HashMap, Fmi2Builder.Value> implements Fmi2Builder.Fmi2ComponentVariable.PortValueMap { +public class PortValueMapImpl extends HashMap, FmiBuilder.Value> implements FmiBuilder.Fmi2ComponentVariable.PortValueMap { public PortValueMapImpl(int initialCapacity, float loadFactor) { super(initialCapacity, loadFactor); } @@ -17,7 +17,7 @@ public PortValueMapImpl(int initialCapacity) { public PortValueMapImpl() { } - public PortValueMapImpl(Map, ? extends Fmi2Builder.Value> m) { + public PortValueMapImpl(Map, ? extends FmiBuilder.Value> m) { super(m); } } diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/StringExpressionValue.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/StringExpressionValue.java index bfd3a4c40..c16724acf 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/StringExpressionValue.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/StringExpressionValue.java @@ -2,12 +2,12 @@ import org.intocps.maestro.ast.node.PExp; import org.intocps.maestro.ast.node.PType; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import static org.intocps.maestro.ast.MableAstFactory.newAStringLiteralExp; import static org.intocps.maestro.ast.MableAstFactory.newAStringPrimitiveType; -public class StringExpressionValue implements Fmi2Builder.ExpressionValue, Fmi2Builder.StringExpressionValue { +public class StringExpressionValue implements FmiBuilder.ExpressionValue, FmiBuilder.StringExpressionValue { private final PExp exp; public StringExpressionValue(PExp exp) { diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/ValueFmi2Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/ValueFmi2Api.java index c8e9fd59e..3fbdd3ce5 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/ValueFmi2Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/ValueFmi2Api.java @@ -1,9 +1,9 @@ package org.intocps.maestro.framework.fmi2.api.mabl.values; import org.intocps.maestro.ast.node.PType; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; -public class ValueFmi2Api implements Fmi2Builder.Value { +public class ValueFmi2Api implements FmiBuilder.Value { final V value; final PType type; private boolean primitive; diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/ArrayVariableFmi2Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/ArrayVariableFmi2Api.java index c3dee6475..070c39f22 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/ArrayVariableFmi2Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/ArrayVariableFmi2Api.java @@ -1,7 +1,7 @@ package org.intocps.maestro.framework.fmi2.api.mabl.variables; import org.intocps.maestro.ast.node.*; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.IMablScope; import java.util.Collections; @@ -10,10 +10,10 @@ import static org.intocps.maestro.ast.MableAstFactory.newAArayStateDesignator; import static org.intocps.maestro.ast.MableAstFactory.newAAssignmentStm; -public class ArrayVariableFmi2Api extends VariableFmi2Api> implements Fmi2Builder.ArrayVariable { +public class ArrayVariableFmi2Api extends VariableFmi2Api> implements FmiBuilder.ArrayVariable { private final List> items; - public ArrayVariableFmi2Api(PStm declaration, PType type, IMablScope declaredScope, Fmi2Builder.DynamicActiveScope dynamicScope, + public ArrayVariableFmi2Api(PStm declaration, PType type, IMablScope declaredScope, FmiBuilder.DynamicActiveScope dynamicScope, PStateDesignator designator, PExp referenceExp, List> items) { super(declaration, type, declaredScope, dynamicScope, designator, referenceExp); this.items = Collections.unmodifiableList(items); @@ -30,7 +30,7 @@ public List> items() { } @Override - public void setValue(Fmi2Builder.IntExpressionValue index, Fmi2Builder.ExpressionValue value) { + public void setValue(FmiBuilder.IntExpressionValue index, FmiBuilder.ExpressionValue value) { AAssigmentStm stm = newAAssignmentStm(newAArayStateDesignator(this.getDesignator(), index.getExp()), value.getExp()); } } diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/BooleanVariableFmi2Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/BooleanVariableFmi2Api.java index f75950071..b3562e889 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/BooleanVariableFmi2Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/BooleanVariableFmi2Api.java @@ -3,17 +3,17 @@ import org.intocps.maestro.ast.node.PExp; import org.intocps.maestro.ast.node.PStateDesignator; import org.intocps.maestro.ast.node.PStm; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.PredicateFmi2Api; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.IMablScope; import static org.intocps.maestro.ast.MableAstFactory.newABoleanPrimitiveType; -public class BooleanVariableFmi2Api extends VariableFmi2Api implements Fmi2Builder.BoolVariable { +public class BooleanVariableFmi2Api extends VariableFmi2Api implements FmiBuilder.BoolVariable { private final PredicateFmi2Api predicate; - public BooleanVariableFmi2Api(PStm declaration, IMablScope declaredScope, Fmi2Builder.DynamicActiveScope dynamicScope, + public BooleanVariableFmi2Api(PStm declaration, IMablScope declaredScope, FmiBuilder.DynamicActiveScope dynamicScope, PStateDesignator designator, PExp referenceExp) { super(declaration, newABoleanPrimitiveType(), declaredScope, dynamicScope, designator, referenceExp); this.predicate = new PredicateFmi2Api(referenceExp); diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/ComponentVariableFmi2Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/ComponentVariableFmi2Api.java index fd212775d..cf6c395c1 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/ComponentVariableFmi2Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/ComponentVariableFmi2Api.java @@ -8,7 +8,7 @@ import org.intocps.maestro.ast.node.*; import org.intocps.maestro.fmi.Fmi2ModelDescription; import org.intocps.maestro.framework.core.RelationVariable; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.*; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.IMablScope; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.ScopeFmi2Api; @@ -33,7 +33,7 @@ @SuppressWarnings("rawtypes") -public class ComponentVariableFmi2Api extends VariableFmi2Api> implements Fmi2Builder.Fmi2ComponentVariable { +public class ComponentVariableFmi2Api extends VariableFmi2Api> implements FmiBuilder.Fmi2ComponentVariable { final static Logger logger = LoggerFactory.getLogger(ComponentVariableFmi2Api.class); private final static int FMI_OK = 0; private final static int FMI_WARNING = 1; @@ -55,7 +55,7 @@ public class ComponentVariableFmi2Api extends VariableFmi2Api>> tentativeBuffer = new HashMap<>(); private final Map> tentativeBufferIndexMap = new HashMap<>(); private final String environmentName; - Predicate isLinked = p -> ((PortFmi2Api) p).getSourcePort() != null; + Predicate isLinked = p -> ((PortFmi2Api) p).getSourcePort() != null; ModelDescriptionContext modelDescriptionContext; private ArrayVariableFmi2Api derSharedBuffer; private DoubleVariableFmi2Api currentTimeVar = null; @@ -103,8 +103,8 @@ public void setVariablesToLog(List variablesToLog) { } @Override - public void share(Fmi2Builder.Port port, Fmi2Builder.Variable value) { - Map, Fmi2Builder.Variable> map = new HashMap<>(); + public void share(FmiBuilder.Port port, FmiBuilder.Variable value) { + Map, FmiBuilder.Variable> map = new HashMap<>(); map.put(port, value); share(map); } @@ -256,8 +256,8 @@ public void setDebugLogging(List categories, boolean enableLogging) { } @Override - public void setupExperiment(Fmi2Builder.DoubleVariable startTime, Fmi2Builder.DoubleVariable endTime, - Fmi2Builder.BoolVariable endTimeDefined, Double tolerance) { + public void setupExperiment(FmiBuilder.DoubleVariable startTime, FmiBuilder.DoubleVariable endTime, + FmiBuilder.BoolVariable endTimeDefined, Double tolerance) { this.setupExperiment(((DoubleVariableFmi2Api) startTime).getReferenceExp().clone(), ((DoubleVariableFmi2Api) endTime).getReferenceExp().clone(), ((BooleanVariableFmi2Api) endTimeDefined).getReferenceExp().clone(), tolerance); @@ -273,7 +273,7 @@ private void setupExperiment(PExp startTime, PExp endTime, PExp endTimeDefined, this.setupExperiment(scope, startTime, endTime, endTimeDefined, tolerance); } - private void setupExperiment(Fmi2Builder.Scope scope, PExp startTime, PExp endTime, PExp endTimeDefined, Double tolerance) { + private void setupExperiment(FmiBuilder.Scope scope, PExp startTime, PExp endTime, PExp endTimeDefined, Double tolerance) { AAssigmentStm stm = newAAssignmentStm(((IMablScope) scope).getFmiStatusVariable().getDesignator().clone(), call(this.getReferenceExp().clone(), createFunctionName(FmiFunctionType.SETUPEXPERIMENT), new ArrayList<>( Arrays.asList(newABoolLiteralExp(tolerance != null), newARealLiteralExp(tolerance != null ? tolerance : 0d), @@ -297,19 +297,19 @@ public void exitInitializationMode() { } @Override - public void setupExperiment(Fmi2Builder.Scope scope, Fmi2Builder.DoubleVariable startTime, Fmi2Builder.DoubleVariable endTime, - Fmi2Builder.BoolVariable endTimeDefined, Double tolerance) { + public void setupExperiment(FmiBuilder.Scope scope, FmiBuilder.DoubleVariable startTime, FmiBuilder.DoubleVariable endTime, + FmiBuilder.BoolVariable endTimeDefined, Double tolerance) { this.setupExperiment(scope, ((DoubleVariableFmi2Api) startTime).getReferenceExp().clone(), ((DoubleVariableFmi2Api) endTime).getReferenceExp().clone(), endTimeDefined.getExp().clone(), tolerance); } @Override - public void setupExperiment(Fmi2Builder.Scope scope, double startTime, Double endTime, Double tolerance) { + public void setupExperiment(FmiBuilder.Scope scope, double startTime, Double endTime, Double tolerance) { this.setupExperiment(scope, newARealLiteralExp(startTime), newARealLiteralExp(endTime), newABoolLiteralExp(true), tolerance); } @Override - public void enterInitializationMode(Fmi2Builder.Scope scope) { + public void enterInitializationMode(FmiBuilder.Scope scope) { PStm stm = stateTransitionFunction(FmiFunctionType.ENTERINITIALIZATIONMODE); scope.add(stm); if (builder.getSettings().fmiErrorHandlingEnabled) { @@ -319,7 +319,7 @@ public void enterInitializationMode(Fmi2Builder.Scope scope) { } @Override - public void exitInitializationMode(Fmi2Builder.Scope scope) { + public void exitInitializationMode(FmiBuilder.Scope scope) { PStm stm = stateTransitionFunction(FmiFunctionType.EXITINITIALIZATIONMODE); scope.add(stm); if (builder.getSettings().fmiErrorHandlingEnabled) { @@ -329,33 +329,32 @@ public void exitInitializationMode(Fmi2Builder.Scope scope) { } @Override - public Map.Entry, Fmi2Builder.DoubleVariable> step(Fmi2Builder.Scope scope, - Fmi2Builder.DoubleVariable currentCommunicationPoint, Fmi2Builder.DoubleVariable communicationStepSize, - Fmi2Builder.BoolVariable noSetFMUStatePriorToCurrentPoint) { + public Map.Entry, FmiBuilder.DoubleVariable> step(FmiBuilder.Scope scope, + FmiBuilder.DoubleVariable currentCommunicationPoint, FmiBuilder.DoubleVariable communicationStepSize, + FmiBuilder.BoolVariable noSetFMUStatePriorToCurrentPoint) { return step(scope, currentCommunicationPoint, communicationStepSize, ((VariableFmi2Api) noSetFMUStatePriorToCurrentPoint).getReferenceExp()); } @Override - public Map.Entry, Fmi2Builder.DoubleVariable> step(Fmi2Builder.Scope scope, - Fmi2Builder.DoubleVariable currentCommunicationPoint, Fmi2Builder.DoubleVariable communicationStepSize) { + public Map.Entry, FmiBuilder.DoubleVariable> step(FmiBuilder.Scope scope, + FmiBuilder.DoubleVariable currentCommunicationPoint, FmiBuilder.DoubleVariable communicationStepSize) { return step(scope, currentCommunicationPoint, communicationStepSize, newABoolLiteralExp(false)); } @Override - public Map.Entry, Fmi2Builder.DoubleVariable> step( - Fmi2Builder.DoubleVariable currentCommunicationPoint, Fmi2Builder.DoubleVariable communicationStepSize, - Fmi2Builder.BoolVariable noSetFMUStatePriorToCurrentPoint) { + public Map.Entry, FmiBuilder.DoubleVariable> step(FmiBuilder.DoubleVariable currentCommunicationPoint, + FmiBuilder.DoubleVariable communicationStepSize, FmiBuilder.BoolVariable noSetFMUStatePriorToCurrentPoint) { return step(dynamicScope, currentCommunicationPoint, communicationStepSize, noSetFMUStatePriorToCurrentPoint); } @Override - public Map.Entry, Fmi2Builder.DoubleVariable> step( - Fmi2Builder.DoubleVariable currentCommunicationPoint, Fmi2Builder.DoubleVariable communicationStepSize) { + public Map.Entry, FmiBuilder.DoubleVariable> step(FmiBuilder.DoubleVariable currentCommunicationPoint, + FmiBuilder.DoubleVariable communicationStepSize) { return step(dynamicScope, currentCommunicationPoint, communicationStepSize, newABoolLiteralExp(false)); } - private Map.Entry, Fmi2Builder.DoubleVariable> step(Fmi2Builder.Scope scope, - Fmi2Builder.DoubleVariable currentCommunicationPoint, Fmi2Builder.DoubleVariable communicationStepSize, + private Map.Entry, FmiBuilder.DoubleVariable> step(FmiBuilder.Scope scope, + FmiBuilder.DoubleVariable currentCommunicationPoint, FmiBuilder.DoubleVariable communicationStepSize, PExp noSetFMUStatePriorToCurrentPoint) { scope.add(newAAssignmentStm(((IMablScope) scope).getFmiStatusVariable().getDesignator().clone(), @@ -433,9 +432,9 @@ public PortFmi2Api getPort(int valueReference) { //TODO: Move tentative buffer and global share buffer logic to its own module so that it is not coupled with the component logic? public Map> getTentative(IMablScope scope, String... names) { // Get filtered port values - Fmi2Builder.Port[] filteredPorts = this.ports.stream() + FmiBuilder.Port[] filteredPorts = this.ports.stream() .filter(p -> Arrays.asList(names).contains(p.getName()) && (p.scalarVariable.causality == Fmi2ModelDescription.Causality.Output)) - .toArray(Fmi2Builder.Port[]::new); + .toArray(FmiBuilder.Port[]::new); Map> portToValueMap = get(scope, filteredPorts); if (portToValueMap.isEmpty()) { return Map.of(); @@ -475,13 +474,12 @@ public Map> getTentative(IMablScope scope, S } @Override - public Map> get(Fmi2Builder.Port... ports) { + public Map> get(FmiBuilder.Port... ports) { return get(builder.getDynamicScope().getActiveScope(), ports); } @Override - public Map> get(Fmi2Builder.Scope scope, - Fmi2Builder.Port... ports) { + public Map> get(FmiBuilder.Scope scope, FmiBuilder.Port... ports) { List selectedPorts; if (ports == null || ports.length == 0) { @@ -497,7 +495,7 @@ public Map> get(Fmi2Builder.Scope scop selectedPorts.stream().map(p -> p.scalarVariable.getType().type).distinct() .map(t -> selectedPorts.stream().filter(p -> p.scalarVariable.getType().type.equals(t)) - .sorted(Comparator.comparing(Fmi2Builder.Port::getPortReferenceValue)).collect(Collectors.toList())) + .sorted(Comparator.comparing(FmiBuilder.Port::getPortReferenceValue)).collect(Collectors.toList())) .forEach(l -> typeToSortedPorts.put(l.get(0).scalarVariable.getType(), l)); for (Map.Entry> e : typeToSortedPorts.entrySet()) { @@ -557,7 +555,7 @@ public Map> get(Fmi2Builder.Scope scop * @param scope The builder scope. * @return Derivative ports with a list of derivative values up to max derivative order */ - public Map>> getDerivatives(List ports, Fmi2Builder.Scope scope) { + public Map>> getDerivatives(List ports, FmiBuilder.Scope scope) { Map>> derivativePortsToReturn = new HashMap<>(); // If any target ports exists that can interpolate the port is also linked and derivatives should be retrieved. @@ -636,20 +634,20 @@ public Map>> getDerivatives(List Map> get() { - return get(builder.getDynamicScope(), outputPorts.toArray(Fmi2Builder.Port[]::new)); + return get(builder.getDynamicScope(), outputPorts.toArray(FmiBuilder.Port[]::new)); } @Override public Map> get(int... valueReferences) { List accept = Arrays.stream(valueReferences).boxed().collect(Collectors.toList()); return get(builder.getDynamicScope(), - outputPorts.stream().filter(p -> accept.contains(p.getPortReferenceValue().intValue())).toArray(Fmi2Builder.Port[]::new)); + outputPorts.stream().filter(p -> accept.contains(p.getPortReferenceValue().intValue())).toArray(FmiBuilder.Port[]::new)); } @Override public Map> get(String... names) { List accept = Arrays.asList(names); - Fmi2Builder.Port[] ports = this.ports.stream().filter(p -> accept.contains(p.getName())).toArray(Fmi2Builder.Port[]::new); + FmiBuilder.Port[] ports = this.ports.stream().filter(p -> accept.contains(p.getName())).toArray(FmiBuilder.Port[]::new); return get(builder.getDynamicScope(), ports); } @@ -666,15 +664,15 @@ public Map> getAndShare(String... names) { } @Override - public Map, ? extends Fmi2Builder.Variable> getAndShare( - Fmi2Builder.Port... ports) { + public Map, ? extends FmiBuilder.Variable> getAndShare( + FmiBuilder.Port... ports) { Map> values = get(ports); share(values); return values; } @Override - public Map, ? extends Fmi2Builder.Variable> getAndShare() { + public Map, ? extends FmiBuilder.Variable> getAndShare() { Map> values = get(); share(values); return values; @@ -686,12 +684,12 @@ public VariableFmi2Api getShared(String name) { } @Override - public VariableFmi2Api getShared(Fmi2Builder.Port port) { + public VariableFmi2Api getShared(FmiBuilder.Port port) { return ((PortFmi2Api) port).getSharedAsVariable(); } @Override - public VariableFmi2Api getSingle(Fmi2Builder.Port port) { + public VariableFmi2Api getSingle(FmiBuilder.Port port) { return (VariableFmi2Api) this.get(port).entrySet().iterator().next().getValue(); } @@ -741,11 +739,11 @@ public VariableFmi2Api getSingle(String name) { } - public void set(Fmi2Builder.Port p, Fmi2Builder.ExpressionValue v) { + public void set(FmiBuilder.Port p, FmiBuilder.ExpressionValue v) { this.set(new PortValueExpresssionMapImpl(Map.of(p, v))); } - public void set(Fmi2Builder.Scope scope, Fmi2Builder.Port p, Fmi2Builder.ExpressionValue v) { + public void set(FmiBuilder.Scope scope, FmiBuilder.Port p, FmiBuilder.ExpressionValue v) { this.set(scope, new PortValueMapImpl(Map.of(p, v))); } @@ -753,7 +751,7 @@ public void set(PortExpressionValueMap value) { this.set(builder.getDynamicScope().getActiveScope(), value); } - public void set(Fmi2Builder.Scope scope, PortExpressionValueMap value) { + public void set(FmiBuilder.Scope scope, PortExpressionValueMap value) { if (value == null || value.isEmpty()) { return; } @@ -761,13 +759,13 @@ public void set(Fmi2Builder.Scope scope, PortExpressionValueMap selectedPorts = value.keySet().stream().map(PortFmi2Api.class::cast).collect(Collectors.toList()); set(scope, selectedPorts, port -> { - Fmi2Builder.ExpressionValue value_ = value.get(port); + FmiBuilder.ExpressionValue value_ = value.get(port); return Map.entry(value_.getExp(), value_.getType()); }); } @Override - public void set(Fmi2Builder.Scope scope, PortValueMap value) { + public void set(FmiBuilder.Scope scope, PortValueMap value) { if (value == null || value.isEmpty()) { @@ -799,7 +797,7 @@ public void set(Fmi2Builder.Scope scope, PortValueMap void set(Fmi2Builder.Scope scope, PortVariableMap value) { + public void set(FmiBuilder.Scope scope, PortVariableMap value) { List selectedPorts; if (value == null || value.isEmpty()) { @@ -813,7 +811,7 @@ public void set(Fmi2Builder.Scope scope, PortVariableMap Map.entry(((VariableFmi2Api) valueFinal.get(port)).getReferenceExp().clone(), ((VariableFmi2Api) valueFinal.get(port)).type)); } - public void set(Fmi2Builder.Scope scope, List selectedPorts, Function> portToValue) { + public void set(FmiBuilder.Scope scope, List selectedPorts, Function> portToValue) { Set selectedPortsAsStrings = selectedPorts.stream() .map(p -> p.getName() + "-" + p.aMablFmi2ComponentAPI.getName() + "-" + p.aMablFmi2ComponentAPI.getOwner().getName()) @@ -827,14 +825,14 @@ public void set(Fmi2Builder.Scope scope, List selectedPorts, } List sortedPorts = - selectedPorts.stream().sorted(Comparator.comparing(Fmi2Builder.Port::getPortReferenceValue)).collect(Collectors.toList()); + selectedPorts.stream().sorted(Comparator.comparing(FmiBuilder.Port::getPortReferenceValue)).collect(Collectors.toList()); // Group by the string value of the port type as grouping by the port type itself doesnt utilise equals sortedPorts.stream().collect(Collectors.groupingBy(i -> i.getType().toString())).forEach((key, value) -> { ArrayVariableFmi2Api vrefBuf = getValueReferenceBuffer(); PType type = value.get(0).getType(); for (int i = 0; i < value.size(); i++) { - Fmi2Builder.Port p = value.get(i); + FmiBuilder.Port p = value.get(i); PStateDesignator designator = vrefBuf.items().get(i).getDesignator().clone(); scope.add(newAAssignmentStm(designator, newAIntLiteralExp(p.getPortReferenceValue().intValue()))); } @@ -873,7 +871,7 @@ public void set(Fmi2Builder.Scope scope, List selectedPorts, * @param ports The ports for which derivative should be set from SHARED derivative ports * @param scope The builder scope */ - private void setDerivativesForSharedPorts(List ports, Fmi2Builder.Scope scope) { + private void setDerivativesForSharedPorts(List ports, FmiBuilder.Scope scope) { // Find all ports for which derivatives should be passed together with the derivatives and their order. LinkedHashMap> mapPortsToDerPortsWithOrder = ports.stream().filter(port -> port.getSourcePort() != null).map(port -> { @@ -945,7 +943,7 @@ private void setDerivativesForSharedPorts(List ports, Fmi2Builder.S * @param scope the builder scope */ public void setDerivatives(ArrayVariableFmi2Api derValInBuf, ArrayVariableFmi2Api derOrderInBuf, ArrayVariableFmi2Api derRefInBuf, - Fmi2Builder.Scope scope) { + FmiBuilder.Scope scope) { int arraySize = derValInBuf.size(); // Create set derivatives statement which calls setRealOutputDerivatives with derRefInBuf, arraySize, derOrderInBuf and @@ -969,18 +967,17 @@ public void set(PortValueMap value) } @Override - public void set(Fmi2Builder.Port port, Fmi2Builder.Variable value) { + public void set(FmiBuilder.Port port, FmiBuilder.Variable value) { this.set(new PortVariableMapImpl(Map.of(port, value))); } @Override - public void set(Fmi2Builder.Scope scope, Fmi2Builder.Port port, - Fmi2Builder.Variable value) { + public void set(FmiBuilder.Scope scope, FmiBuilder.Port port, FmiBuilder.Variable value) { this.set(scope, new PortVariableMapImpl(Map.of(port, value))); } @Override - public void set(Fmi2Builder.Port port, Fmi2Builder.Value value) { + public void set(FmiBuilder.Port port, FmiBuilder.Value value) { PortValueMap map = new PortValueMapImpl(); map.put(port, value); set(map); @@ -994,14 +991,14 @@ public void set(PortVariableMap scope, Fmi2Builder.Port... filterPorts) { + public void setLinked(FmiBuilder.Scope scope, FmiBuilder.Port... filterPorts) { List selectedPorts = ports.stream().filter(isLinked).collect(Collectors.toList()); if (filterPorts != null && filterPorts.length != 0) { - List filterList = Arrays.asList(filterPorts); + List filterList = Arrays.asList(filterPorts); - for (Fmi2Builder.Port p : filterList) { + for (FmiBuilder.Port p : filterList) { if (!isLinked.test(p)) { logger.warn("Filter for setLinked contains unlined port. Its ignored. {}", p); } @@ -1035,11 +1032,11 @@ public void setLinked(Fmi2Builder.Scope scope, Fmi2Builder.Port accept = Arrays.asList(filterNames); - this.setLinked(dynamicScope, getPorts().stream().filter(p -> accept.contains(p.getName())).toArray(Fmi2Builder.Port[]::new)); + this.setLinked(dynamicScope, getPorts().stream().filter(p -> accept.contains(p.getName())).toArray(FmiBuilder.Port[]::new)); } @Override public void setLinked(long... filterValueReferences) { List accept = Arrays.stream(filterValueReferences).boxed().collect(Collectors.toList()); - this.setLinked(dynamicScope, getPorts().stream().filter(p -> accept.contains(p.getPortReferenceValue())).toArray(Fmi2Builder.Port[]::new)); + this.setLinked(dynamicScope, getPorts().stream().filter(p -> accept.contains(p.getPortReferenceValue())).toArray(FmiBuilder.Port[]::new)); } @Override - public void setInt(Map> values) { + public void setInt(Map> values) { } @Override - public void setString(Map> value) { + public void setString(Map> value) { } @@ -1074,7 +1071,7 @@ public void terminate() { } @Override - public void terminate(Fmi2Builder.Scope scope) { + public void terminate(FmiBuilder.Scope scope) { PStm stm = stateTransitionFunction(FmiFunctionType.TERMINATE); scope.add(stm); if (builder.getSettings().fmiErrorHandlingEnabled) { @@ -1084,13 +1081,13 @@ public void terminate(Fmi2Builder.Scope scope) { } @Override - public void share(Map, ? extends Fmi2Builder.Variable> values) { + public void share(Map, ? extends FmiBuilder.Variable> values) { // Group by the string value of the port type as grouping by the port type itself doesnt utilise equals values.entrySet().stream().collect(Collectors.groupingBy(map -> ((PortFmi2Api) map.getKey()).getType().toString())).entrySet().stream() .forEach(map -> { PType type = ((PortFmi2Api) map.getValue().get(0).getKey()).getType(); - Map data = + Map data = map.getValue().stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); data.keySet().stream().map(PortFmi2Api.class::cast).sorted(Comparator.comparing(PortFmi2Api::getPortReferenceValue)) @@ -1244,12 +1241,12 @@ private ArrayVariableFmi2Api growBuffer(ArrayVariableFmi2Api buf } @Override - public Fmi2Builder.StateVariable getState() throws XPathExpressionException { + public FmiBuilder.StateVariable getState() throws XPathExpressionException { return getState(builder.getDynamicScope()); } @Override - public Fmi2Builder.StateVariable getState(Fmi2Builder.Scope scope) throws XPathExpressionException { + public FmiBuilder.StateVariable getState(FmiBuilder.Scope scope) throws XPathExpressionException { if (!this.modelDescriptionContext.getModelDescription().getCanGetAndSetFmustate()) { throw new RuntimeException("Unable to get state on fmu: " + this.getOwner() + " with instance name: " + this.getName()); diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/DoubleVariableFmi2Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/DoubleVariableFmi2Api.java index ac088bb2b..877a603a9 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/DoubleVariableFmi2Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/DoubleVariableFmi2Api.java @@ -4,14 +4,14 @@ import org.intocps.maestro.ast.node.PStateDesignator; import org.intocps.maestro.ast.node.PStm; import org.intocps.maestro.ast.node.PType; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.IMablScope; import org.intocps.maestro.framework.fmi2.api.mabl.values.DoubleExpressionValue; import static org.intocps.maestro.ast.MableAstFactory.newARealNumericPrimitiveType; -public class DoubleVariableFmi2Api extends VariableFmi2Api implements Fmi2Builder.DoubleVariable { - public DoubleVariableFmi2Api(PStm declaration, IMablScope declaredScope, Fmi2Builder.DynamicActiveScope dynamicScope, +public class DoubleVariableFmi2Api extends VariableFmi2Api implements FmiBuilder.DoubleVariable { + public DoubleVariableFmi2Api(PStm declaration, IMablScope declaredScope, FmiBuilder.DynamicActiveScope dynamicScope, PStateDesignator designator, PExp referenceExp) { super(declaration, newARealNumericPrimitiveType(), declaredScope, dynamicScope, designator, referenceExp); } @@ -24,7 +24,7 @@ public void set(Double value) { @Override - public void setValue(Fmi2Builder.DoubleExpressionValue value) { + public void setValue(FmiBuilder.DoubleExpressionValue value) { super.setValue(value.getExp()); } diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/FmuVariableFmi2Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/FmuVariableFmi2Api.java index 91edabb6b..58473a3bf 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/FmuVariableFmi2Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/FmuVariableFmi2Api.java @@ -3,7 +3,7 @@ import org.intocps.maestro.ast.MableAstFactory; import org.intocps.maestro.ast.node.*; import org.intocps.maestro.fmi.Fmi2ModelDescription; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.MablApiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.ModelDescriptionContext; import org.intocps.maestro.framework.fmi2.api.mabl.PredicateFmi2Api; @@ -15,20 +15,20 @@ import static org.intocps.maestro.ast.MableBuilder.call; import static org.intocps.maestro.ast.MableBuilder.newVariable; -public class FmuVariableFmi2Api extends VariableFmi2Api> implements Fmi2Builder.Fmu2Variable { +public class FmuVariableFmi2Api extends VariableFmi2Api> implements FmiBuilder.Fmu2Variable { private final ModelDescriptionContext modelDescriptionContext; private final MablApiBuilder builder; private String fmuIdentifier; public FmuVariableFmi2Api(String fmuIdentifier, MablApiBuilder builder, ModelDescriptionContext modelDescriptionContext, PStm declaration, - PType type, IMablScope declaredScope, Fmi2Builder.DynamicActiveScope dynamicScope, PStateDesignator designator, PExp referenceExp) { + PType type, IMablScope declaredScope, FmiBuilder.DynamicActiveScope dynamicScope, PStateDesignator designator, PExp referenceExp) { this(builder, modelDescriptionContext, declaration, type, declaredScope, dynamicScope, designator, referenceExp); this.fmuIdentifier = fmuIdentifier; } public FmuVariableFmi2Api(MablApiBuilder builder, ModelDescriptionContext modelDescriptionContext, PStm declaration, PType type, - IMablScope declaredScope, Fmi2Builder.DynamicActiveScope dynamicScope, PStateDesignator designator, PExp referenceExp) { + IMablScope declaredScope, FmiBuilder.DynamicActiveScope dynamicScope, PStateDesignator designator, PExp referenceExp) { super(declaration, type, declaredScope, dynamicScope, designator, referenceExp); this.builder = builder; this.modelDescriptionContext = modelDescriptionContext; @@ -84,14 +84,14 @@ public ComponentVariableFmi2Api instantiate(String name) { // } // } @Override - public ComponentVariableFmi2Api instantiate(String namePrefix, Fmi2Builder.TryScope enclosingTryScope, Fmi2Builder.Scope scope, + public ComponentVariableFmi2Api instantiate(String namePrefix, FmiBuilder.TryScope enclosingTryScope, FmiBuilder.Scope scope, String environmentName) { - return instantiate(namePrefix, enclosingTryScope, scope, environmentName, true); + return instantiate(namePrefix, enclosingTryScope, scope, environmentName, true); } @Override - public ComponentVariableFmi2Api instantiate(String namePrefix, Fmi2Builder.TryScope enclosingTryScope, - Fmi2Builder.Scope scope, String environmentName, boolean loggingOn) { + public ComponentVariableFmi2Api instantiate(String namePrefix, FmiBuilder.TryScope enclosingTryScope, FmiBuilder.Scope scope, + String environmentName, boolean loggingOn) { String name = builder.getNameGenerator().getName(namePrefix); //TODO: Extract bool visible and bool loggingOn from configuration @@ -110,11 +110,10 @@ public ComponentVariableFmi2Api instantiate(String namePrefix, Fmi2Builder.TrySc mTryScope.parent().addBefore(mTryScope.getDeclaration(), var); ComponentVariableFmi2Api compVar; - if(environmentName == null) { + if (environmentName == null) { compVar = new ComponentVariableFmi2Api(var, this, name, this.modelDescriptionContext, builder, mTryScope.parent(), newAIdentifierStateDesignator(newAIdentifier(name)), newAIdentifierExp(name)); - } - else { + } else { AInstanceMappingStm mapping = newAInstanceMappingStm(newAIdentifier(name), environmentName); compVar = new ComponentVariableFmi2Api(var, this, name, this.modelDescriptionContext, builder, mTryScope.parent(), @@ -146,7 +145,7 @@ public ComponentVariableFmi2Api instantiate(String namePrefix, Fmi2Builder.TrySc } @Override - public ComponentVariableFmi2Api instantiate(String namePrefix, Fmi2Builder.TryScope enclosingTryScope, Fmi2Builder.Scope scope) { + public ComponentVariableFmi2Api instantiate(String namePrefix, FmiBuilder.TryScope enclosingTryScope, FmiBuilder.Scope scope) { return instantiate(namePrefix, enclosingTryScope, scope, null); } diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/FmuVariableFmi3Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/FmuVariableFmi3Api.java index 0b18e53f2..61316dfcb 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/FmuVariableFmi3Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/FmuVariableFmi3Api.java @@ -1,45 +1,40 @@ package org.intocps.maestro.framework.fmi2.api.mabl.variables; -import org.intocps.fmi.jnifmuapi.fmi3.Fmi3Instance; import org.intocps.maestro.ast.MableAstFactory; import org.intocps.maestro.ast.node.*; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.MablApiBuilder; -import org.intocps.maestro.framework.fmi2.api.mabl.ModelDescriptionContext; import org.intocps.maestro.framework.fmi2.api.mabl.ModelDescriptionContext3; import org.intocps.maestro.framework.fmi2.api.mabl.PredicateFmi2Api; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.IMablScope; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.ScopeFmi2Api; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.TryMaBlScope; -import java.util.Arrays; -import java.util.HashMap; -import java.util.stream.Collectors; - import static org.intocps.maestro.ast.MableAstFactory.*; import static org.intocps.maestro.ast.MableBuilder.call; import static org.intocps.maestro.ast.MableBuilder.newVariable; -public class FmuVariableFmi3Api extends VariableFmi2Api> implements Fmi2Builder.Fmu3Variable { -// public FmuVariableFmi3Api(PStm declaration, PType type, IMablScope declaredScope, Fmi2Builder.DynamicActiveScope dynamicScope, -// PStateDesignator designator, PExp referenceExp) { -// super(declaration, type, declaredScope, dynamicScope, designator, referenceExp); -// } +public class FmuVariableFmi3Api extends VariableFmi2Api> implements FmiBuilder.Fmu3Variable { + // public FmuVariableFmi3Api(PStm declaration, PType type, IMablScope declaredScope, Fmi2Builder.DynamicActiveScope dynamicScope, + // PStateDesignator designator, PExp referenceExp) { + // super(declaration, type, declaredScope, dynamicScope, designator, referenceExp); + // } private final ModelDescriptionContext3 modelDescriptionContext; private final MablApiBuilder builder; private String fmuIdentifier; -// + + // public FmuVariableFmi3Api(String fmuIdentifier, MablApiBuilder builder, ModelDescriptionContext3 modelDescriptionContext, PStm declaration, - PType type, IMablScope declaredScope, Fmi2Builder.DynamicActiveScope dynamicScope, PStateDesignator designator, PExp referenceExp) { + PType type, IMablScope declaredScope, FmiBuilder.DynamicActiveScope dynamicScope, PStateDesignator designator, PExp referenceExp) { this(builder, modelDescriptionContext, declaration, type, declaredScope, dynamicScope, designator, referenceExp); this.fmuIdentifier = fmuIdentifier; } public FmuVariableFmi3Api(MablApiBuilder builder, ModelDescriptionContext3 modelDescriptionContext, PStm declaration, PType type, - IMablScope declaredScope, Fmi2Builder.DynamicActiveScope dynamicScope, PStateDesignator designator, PExp referenceExp) { + IMablScope declaredScope, FmiBuilder.DynamicActiveScope dynamicScope, PStateDesignator designator, PExp referenceExp) { super(declaration, type, declaredScope, dynamicScope, designator, referenceExp); this.builder = builder; this.modelDescriptionContext = modelDescriptionContext; @@ -49,7 +44,7 @@ public ModelDescriptionContext3 getModelDescriptionContext() { return modelDescriptionContext; } -// @Override + // @Override public InstanceVariableFmi3Api instantiate(String name, String environmentName, ArrayVariableFmi2Api variables) { IMablScope scope = builder.getDynamicScope().getActiveScope(); return instantiate(name, scope.findParentScope(TryMaBlScope.class), scope, environmentName, variables); @@ -61,11 +56,12 @@ public InstanceVariableFmi3Api instantiate(String name, ArrayVariableFmi2Api var } - public InstanceVariableFmi3Api instantiate(String namePrefix, Fmi2Builder.TryScope enclosingTryScope, Fmi2Builder.Scope scope, + public InstanceVariableFmi3Api instantiate(String namePrefix, FmiBuilder.TryScope enclosingTryScope, FmiBuilder.Scope scope, String environmentName, ArrayVariableFmi2Api variables) { - return instantiate(namePrefix, enclosingTryScope, scope, environmentName, true, variables ); + return instantiate(namePrefix, enclosingTryScope, scope, environmentName, true, variables); } - public InstanceVariableFmi3Api instantiate(String namePrefix, Fmi2Builder.TryScope enclosingTryScope, Fmi2Builder.Scope scope, + + public InstanceVariableFmi3Api instantiate(String namePrefix, FmiBuilder.TryScope enclosingTryScope, FmiBuilder.Scope scope, String environmentName, boolean loggingOn, ArrayVariableFmi2Api variables) { String name = builder.getNameGenerator().getName(namePrefix); @@ -73,13 +69,9 @@ public InstanceVariableFmi3Api instantiate(String namePrefix, Fmi2Builder.TrySco var var = newVariable(name, newANameType("FMI3Instance"), newNullExp()); - - - PStm instantiateAssign = newAAssignmentStm(newAIdentifierStateDesignator(name), - call(getReferenceExp().clone(), "instantiateCoSimulation", newAStringLiteralExp(name), newABoolLiteralExp(true), - newABoolLiteralExp(loggingOn), newABoolLiteralExp(true), newABoolLiteralExp(true), - variables.getReferenceExp().clone())); + call(getReferenceExp().clone(), "instantiateCoSimulation", newAStringLiteralExp(name), newABoolLiteralExp(true), + newABoolLiteralExp(loggingOn), newABoolLiteralExp(true), newABoolLiteralExp(true), variables.getReferenceExp().clone())); if (enclosingTryScope == null) { throw new IllegalArgumentException("Call to instantiate is not allowed with a null enclosing try scope"); @@ -123,7 +115,9 @@ public InstanceVariableFmi3Api instantiate(String namePrefix, Fmi2Builder.TrySco return compVar; } - public InstanceVariableFmi3Api instantiate(String namePrefix, Fmi2Builder.TryScope enclosingTryScope, Fmi2Builder.Scope scope, ArrayVariableFmi2Api variables) { + + public InstanceVariableFmi3Api instantiate(String namePrefix, FmiBuilder.TryScope enclosingTryScope, FmiBuilder.Scope scope, + ArrayVariableFmi2Api variables) { return instantiate(namePrefix, enclosingTryScope, scope, null, variables); } diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/IndexedVariableFmi2Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/IndexedVariableFmi2Api.java index d50f85474..d7ccfa489 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/IndexedVariableFmi2Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/IndexedVariableFmi2Api.java @@ -1,9 +1,9 @@ package org.intocps.maestro.framework.fmi2.api.mabl.variables; import org.intocps.maestro.ast.node.PStm; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; -public interface IndexedVariableFmi2Api extends Fmi2Builder.Variable { +public interface IndexedVariableFmi2Api extends FmiBuilder.Variable { PStm getDeclaringStm(); } diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/InstanceVariableFmi3Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/InstanceVariableFmi3Api.java index 4004d65e7..665151647 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/InstanceVariableFmi3Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/InstanceVariableFmi3Api.java @@ -10,7 +10,7 @@ import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3TypeEnum; import org.intocps.maestro.framework.fmi2.RelationVariable; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.*; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.IMablScope; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.ScopeFmi2Api; @@ -34,7 +34,7 @@ @SuppressWarnings("rawtypes") -public class InstanceVariableFmi3Api extends VariableFmi2Api> implements Fmi2Builder.Fmi3InstanceVariable { +public class InstanceVariableFmi3Api extends VariableFmi2Api> implements FmiBuilder.Fmi3InstanceVariable { final static Logger logger = LoggerFactory.getLogger(InstanceVariableFmi3Api.class); private final static int FMI_OK = 0; private final static int FMI_WARNING = 1; @@ -56,7 +56,7 @@ public class InstanceVariableFmi3Api extends VariableFmi2Api>> tentativeBuffer = new HashMap<>(); private final Map> tentativeBufferIndexMap = new HashMap<>(); private final String environmentName; - Predicate isLinked = p -> ((PortFmi3Api) p).getSourcePort() != null; + Predicate isLinked = p -> ((PortFmi3Api) p).getSourcePort() != null; ModelDescriptionContext3 modelDescriptionContext; private ArrayVariableFmi2Api derSharedBuffer; private DoubleVariableFmi2Api currentTimeVar = null; @@ -105,8 +105,8 @@ public void setVariablesToLog(List variablesToLog) { } @Override - public void share(Fmi2Builder.Port port, Fmi2Builder.Variable value) { - Map, Fmi2Builder.Variable> map = new HashMap<>(); + public void share(FmiBuilder.Port port, FmiBuilder.Variable value) { + Map, FmiBuilder.Variable> map = new HashMap<>(); map.put(port, value); share(map); } @@ -258,8 +258,8 @@ public void setDebugLogging(List categories, boolean enableLogging) { } @Override - public void setupExperiment(Fmi2Builder.DoubleVariable startTime, Fmi2Builder.DoubleVariable endTime, - Fmi2Builder.BoolVariable endTimeDefined, Double tolerance) { + public void setupExperiment(FmiBuilder.DoubleVariable startTime, FmiBuilder.DoubleVariable endTime, + FmiBuilder.BoolVariable endTimeDefined, Double tolerance) { this.setupExperiment(((DoubleVariableFmi2Api) startTime).getReferenceExp().clone(), ((DoubleVariableFmi2Api) endTime).getReferenceExp().clone(), ((BooleanVariableFmi2Api) endTimeDefined).getReferenceExp().clone(), tolerance); @@ -275,7 +275,7 @@ private void setupExperiment(PExp startTime, PExp endTime, PExp endTimeDefined, this.setupExperiment(scope, startTime, endTime, endTimeDefined, tolerance); } - private void setupExperiment(Fmi2Builder.Scope scope, PExp startTime, PExp endTime, PExp endTimeDefined, Double tolerance) { + private void setupExperiment(FmiBuilder.Scope scope, PExp startTime, PExp endTime, PExp endTimeDefined, Double tolerance) { AAssigmentStm stm = newAAssignmentStm(((IMablScope) scope).getFmiStatusVariable().getDesignator().clone(), call(this.getReferenceExp().clone(), createFunctionName(FmiFunctionType.SETUPEXPERIMENT), new ArrayList<>( Arrays.asList(newABoolLiteralExp(tolerance != null), newARealLiteralExp(tolerance != null ? tolerance : 0d), @@ -299,19 +299,19 @@ public void exitInitializationMode() { } @Override - public void setupExperiment(Fmi2Builder.Scope scope, Fmi2Builder.DoubleVariable startTime, Fmi2Builder.DoubleVariable endTime, - Fmi2Builder.BoolVariable endTimeDefined, Double tolerance) { + public void setupExperiment(FmiBuilder.Scope scope, FmiBuilder.DoubleVariable startTime, FmiBuilder.DoubleVariable endTime, + FmiBuilder.BoolVariable endTimeDefined, Double tolerance) { this.setupExperiment(scope, ((DoubleVariableFmi2Api) startTime).getReferenceExp().clone(), ((DoubleVariableFmi2Api) endTime).getReferenceExp().clone(), endTimeDefined.getExp().clone(), tolerance); } @Override - public void setupExperiment(Fmi2Builder.Scope scope, double startTime, Double endTime, Double tolerance) { + public void setupExperiment(FmiBuilder.Scope scope, double startTime, Double endTime, Double tolerance) { this.setupExperiment(scope, newARealLiteralExp(startTime), newARealLiteralExp(endTime), newABoolLiteralExp(true), tolerance); } @Override - public void enterInitializationMode(Fmi2Builder.Scope scope, boolean toleranceDefined, double tolerance, double startTime, + public void enterInitializationMode(FmiBuilder.Scope scope, boolean toleranceDefined, double tolerance, double startTime, boolean stopTimeDefined, double stopTime) { PStm stm = stateTransitionFunction(FmiFunctionType.ENTERINITIALIZATIONMODE); scope.add(stm); @@ -322,7 +322,7 @@ public void enterInitializationMode(Fmi2Builder.Scope scope, boolean toler } @Override - public void exitInitializationMode(Fmi2Builder.Scope scope) { + public void exitInitializationMode(FmiBuilder.Scope scope) { PStm stm = stateTransitionFunction(FmiFunctionType.EXITINITIALIZATIONMODE); scope.add(stm); if (builder.getSettings().fmiErrorHandlingEnabled) { @@ -332,33 +332,32 @@ public void exitInitializationMode(Fmi2Builder.Scope scope) { } @Override - public Map.Entry, Fmi2Builder.DoubleVariable> step(Fmi2Builder.Scope scope, - Fmi2Builder.DoubleVariable currentCommunicationPoint, Fmi2Builder.DoubleVariable communicationStepSize, - Fmi2Builder.BoolVariable noSetFMUStatePriorToCurrentPoint) { + public Map.Entry, FmiBuilder.DoubleVariable> step(FmiBuilder.Scope scope, + FmiBuilder.DoubleVariable currentCommunicationPoint, FmiBuilder.DoubleVariable communicationStepSize, + FmiBuilder.BoolVariable noSetFMUStatePriorToCurrentPoint) { return step(scope, currentCommunicationPoint, communicationStepSize, ((VariableFmi2Api) noSetFMUStatePriorToCurrentPoint).getReferenceExp()); } @Override - public Map.Entry, Fmi2Builder.DoubleVariable> step(Fmi2Builder.Scope scope, - Fmi2Builder.DoubleVariable currentCommunicationPoint, Fmi2Builder.DoubleVariable communicationStepSize) { + public Map.Entry, FmiBuilder.DoubleVariable> step(FmiBuilder.Scope scope, + FmiBuilder.DoubleVariable currentCommunicationPoint, FmiBuilder.DoubleVariable communicationStepSize) { return step(scope, currentCommunicationPoint, communicationStepSize, newABoolLiteralExp(false)); } @Override - public Map.Entry, Fmi2Builder.DoubleVariable> step( - Fmi2Builder.DoubleVariable currentCommunicationPoint, Fmi2Builder.DoubleVariable communicationStepSize, - Fmi2Builder.BoolVariable noSetFMUStatePriorToCurrentPoint) { + public Map.Entry, FmiBuilder.DoubleVariable> step(FmiBuilder.DoubleVariable currentCommunicationPoint, + FmiBuilder.DoubleVariable communicationStepSize, FmiBuilder.BoolVariable noSetFMUStatePriorToCurrentPoint) { return step(dynamicScope, currentCommunicationPoint, communicationStepSize, noSetFMUStatePriorToCurrentPoint); } @Override - public Map.Entry, Fmi2Builder.DoubleVariable> step( - Fmi2Builder.DoubleVariable currentCommunicationPoint, Fmi2Builder.DoubleVariable communicationStepSize) { + public Map.Entry, FmiBuilder.DoubleVariable> step(FmiBuilder.DoubleVariable currentCommunicationPoint, + FmiBuilder.DoubleVariable communicationStepSize) { return step(dynamicScope, currentCommunicationPoint, communicationStepSize, newABoolLiteralExp(false)); } - private Map.Entry, Fmi2Builder.DoubleVariable> step(Fmi2Builder.Scope scope, - Fmi2Builder.DoubleVariable currentCommunicationPoint, Fmi2Builder.DoubleVariable communicationStepSize, + private Map.Entry, FmiBuilder.DoubleVariable> step(FmiBuilder.Scope scope, + FmiBuilder.DoubleVariable currentCommunicationPoint, FmiBuilder.DoubleVariable communicationStepSize, PExp noSetFMUStatePriorToCurrentPoint) { scope.add(newAAssignmentStm(((IMablScope) scope).getFmiStatusVariable().getDesignator().clone(), @@ -436,9 +435,9 @@ public PortFmi3Api getPort(int valueReference) { //TODO: Move tentative buffer and global share buffer logic to its own module so that it is not coupled with the component logic? public Map> getTentative(IMablScope scope, String... names) { // Get filtered port values - Fmi2Builder.Port[] filteredPorts = this.ports.stream() + FmiBuilder.Port[] filteredPorts = this.ports.stream() .filter(p -> Arrays.asList(names).contains(p.getName()) && (p.scalarVariable.getVariable().getCausality() == Fmi3Causality.Output)) - .toArray(Fmi2Builder.Port[]::new); + .toArray(FmiBuilder.Port[]::new); Map> portToValueMap = get(scope, filteredPorts); if (portToValueMap.isEmpty()) { return Map.of(); @@ -478,13 +477,13 @@ public Map> getTentative(IMablScope scope, S } @Override - public Map> get(Fmi2Builder.Port... ports) { + public Map> get(FmiBuilder.Port... ports) { return get(builder.getDynamicScope().getActiveScope(), ports); } @Override - public Map> get(Fmi2Builder.Scope scope, - Fmi2Builder.Port... ports) { + public Map> get(FmiBuilder.Scope scope, + FmiBuilder.Port... ports) { List selectedPorts; if (ports == null || ports.length == 0) { @@ -500,7 +499,7 @@ public Map> get(Fmi2Builder.Scope scop selectedPorts.stream().map(p -> p.scalarVariable.getVariable().getTypeIdentifier()).distinct() .map(t -> selectedPorts.stream().filter(p -> p.scalarVariable.getVariable().getTypeIdentifier().equals(t)) - .sorted(Comparator.comparing(Fmi2Builder.Port::getPortReferenceValue)).collect(Collectors.toList())) + .sorted(Comparator.comparing(FmiBuilder.Port::getPortReferenceValue)).collect(Collectors.toList())) .forEach(l -> typeToSortedPorts.put(l.get(0).scalarVariable.getVariable().getTypeIdentifier(), l)); for (Map.Entry> e : typeToSortedPorts.entrySet()) { @@ -561,7 +560,7 @@ public Map> get(Fmi2Builder.Scope scop * @param scope The builder scope. * @return Derivative ports with a list of derivative values up to max derivative order */ - public Map>> getDerivatives(List ports, Fmi2Builder.Scope scope) { + public Map>> getDerivatives(List ports, FmiBuilder.Scope scope) { Map>> derivativePortsToReturn = new HashMap<>(); // // If any target ports exists that can interpolate the port is also linked and derivatives should be retrieved. @@ -641,20 +640,20 @@ public Map>> getDerivatives(List Map> get() { - return get(builder.getDynamicScope(), outputPorts.toArray(Fmi2Builder.Port[]::new)); + return get(builder.getDynamicScope(), outputPorts.toArray(FmiBuilder.Port[]::new)); } @Override public Map> get(int... valueReferences) { List accept = Arrays.stream(valueReferences).boxed().collect(Collectors.toList()); return get(builder.getDynamicScope(), - outputPorts.stream().filter(p -> accept.contains(p.getPortReferenceValue().intValue())).toArray(Fmi2Builder.Port[]::new)); + outputPorts.stream().filter(p -> accept.contains(p.getPortReferenceValue().intValue())).toArray(FmiBuilder.Port[]::new)); } @Override public Map> get(String... names) { List accept = Arrays.asList(names); - Fmi2Builder.Port[] ports = this.ports.stream().filter(p -> accept.contains(p.getName())).toArray(Fmi2Builder.Port[]::new); + FmiBuilder.Port[] ports = this.ports.stream().filter(p -> accept.contains(p.getName())).toArray(FmiBuilder.Port[]::new); return get(builder.getDynamicScope(), ports); } @@ -671,15 +670,15 @@ public Map> getAndShare(String... names) { } @Override - public Map, ? extends Fmi2Builder.Variable> getAndShare( - Fmi2Builder.Port... ports) { + public Map, ? extends FmiBuilder.Variable> getAndShare( + FmiBuilder.Port... ports) { Map> values = get(ports); share(values); return values; } @Override - public Map, ? extends Fmi2Builder.Variable> getAndShare() { + public Map, ? extends FmiBuilder.Variable> getAndShare() { Map> values = get(); share(values); return values; @@ -691,12 +690,12 @@ public VariableFmi2Api getShared(String name) { } @Override - public VariableFmi2Api getShared(Fmi2Builder.Port port) { + public VariableFmi2Api getShared(FmiBuilder.Port port) { return ((PortFmi3Api) port).getSharedAsVariable(); } @Override - public VariableFmi2Api getSingle(Fmi2Builder.Port port) { + public VariableFmi2Api getSingle(FmiBuilder.Port port) { return (VariableFmi2Api) this.get(port).entrySet().iterator().next().getValue(); } @@ -746,12 +745,12 @@ public VariableFmi2Api getSingle(String name) { } - public void set(Fmi2Builder.Port p, Fmi2Builder.ExpressionValue v) { + public void set(FmiBuilder.Port p, FmiBuilder.ExpressionValue v) { this.set(new PortValueExpresssionMapImpl(Map.of(p, v))); ; } - public void set(Fmi2Builder.Scope scope, Fmi2Builder.Port p, Fmi2Builder.ExpressionValue v) { + public void set(FmiBuilder.Scope scope, FmiBuilder.Port p, FmiBuilder.ExpressionValue v) { this.set(scope, new PortValueMapImpl(Map.of(p, v))); } @@ -759,7 +758,7 @@ public void set(PortExpressionValueMap value) { this.set(builder.getDynamicScope().getActiveScope(), value); } - public void set(Fmi2Builder.Scope scope, PortExpressionValueMap value) { + public void set(FmiBuilder.Scope scope, PortExpressionValueMap value) { if (value == null || value.isEmpty()) { return; } @@ -767,13 +766,13 @@ public void set(Fmi2Builder.Scope scope, PortExpressionValueMap selectedPorts = value.keySet().stream().map(PortFmi3Api.class::cast).collect(Collectors.toList()); set(scope, selectedPorts, port -> { - Fmi2Builder.ExpressionValue value_ = value.get(port); + FmiBuilder.ExpressionValue value_ = value.get(port); return Map.entry(value_.getExp(), value_.getType()); }); } @Override - public void set(Fmi2Builder.Scope scope, PortValueMap value) { + public void set(FmiBuilder.Scope scope, PortValueMap value) { if (value == null || value.isEmpty()) { @@ -805,7 +804,7 @@ public void set(Fmi2Builder.Scope scope, PortValueMap void set(Fmi2Builder.Scope scope, PortVariableMap value) { + public void set(FmiBuilder.Scope scope, PortVariableMap value) { List selectedPorts; if (value == null || value.isEmpty()) { @@ -819,7 +818,7 @@ public void set(Fmi2Builder.Scope scope, PortVariableMap Map.entry(((VariableFmi2Api) valueFinal.get(port)).getReferenceExp().clone(), ((VariableFmi2Api) valueFinal.get(port)).type)); } - public void set(Fmi2Builder.Scope scope, List selectedPorts, Function> portToValue) { + public void set(FmiBuilder.Scope scope, List selectedPorts, Function> portToValue) { Set selectedPortsAsStrings = selectedPorts.stream() .map(p -> p.getName() + "-" + p.aMablFmi3InstanceAPI.getName() + "-" + p.aMablFmi3InstanceAPI.getOwner().getName()).collect(toSet()); @@ -832,14 +831,14 @@ public void set(Fmi2Builder.Scope scope, List selectedPorts, } List sortedPorts = - selectedPorts.stream().sorted(Comparator.comparing(Fmi2Builder.Port::getPortReferenceValue)).collect(Collectors.toList()); + selectedPorts.stream().sorted(Comparator.comparing(FmiBuilder.Port::getPortReferenceValue)).collect(Collectors.toList()); // Group by the string value of the port type as grouping by the port type itself doesnt utilise equals sortedPorts.stream().collect(Collectors.groupingBy(i -> i.getType().toString())).forEach((key, value) -> { ArrayVariableFmi2Api vrefBuf = getValueReferenceBuffer(); PType type = value.get(0).getType(); for (int i = 0; i < value.size(); i++) { - Fmi2Builder.Port p = value.get(i); + FmiBuilder.Port p = value.get(i); PStateDesignator designator = vrefBuf.items().get(i).getDesignator().clone(); scope.add(newAAssignmentStm(designator, newAIntLiteralExp(p.getPortReferenceValue().intValue()))); } @@ -952,7 +951,7 @@ public void set(Fmi2Builder.Scope scope, List selectedPorts, * @param scope the builder scope */ public void setDerivatives(ArrayVariableFmi2Api derValInBuf, ArrayVariableFmi2Api derOrderInBuf, ArrayVariableFmi2Api derRefInBuf, - Fmi2Builder.Scope scope) { + FmiBuilder.Scope scope) { int arraySize = derValInBuf.size(); // Create set derivatives statement which calls setRealOutputDerivatives with derRefInBuf, arraySize, derOrderInBuf and @@ -977,18 +976,18 @@ public void set(PortValueMap val @Override - public void set(Fmi2Builder.Port port, Fmi2Builder.Variable value) { + public void set(FmiBuilder.Port port, FmiBuilder.Variable value) { this.set(new PortVariableMapImpl(Map.of(port, value))); } @Override - public void set(Fmi2Builder.Scope scope, Fmi2Builder.Port port, - Fmi2Builder.Variable value) { + public void set(FmiBuilder.Scope scope, FmiBuilder.Port port, + FmiBuilder.Variable value) { this.set(scope, new PortVariableMapImpl(Map.of(port, value))); } @Override - public void set(Fmi2Builder.Port port, Fmi2Builder.Value value) { + public void set(FmiBuilder.Port port, FmiBuilder.Value value) { PortValueMap map = new PortValueMapImpl(); map.put(port, value); set(map); @@ -1000,14 +999,14 @@ public void set(PortVariableMap scope, Fmi2Builder.Port... filterPorts) { + public void setLinked(FmiBuilder.Scope scope, FmiBuilder.Port... filterPorts) { List selectedPorts = ports.stream().filter(isLinked).collect(Collectors.toList()); if (filterPorts != null && filterPorts.length != 0) { - List filterList = Arrays.asList(filterPorts); + List filterList = Arrays.asList(filterPorts); - for (Fmi2Builder.Port p : filterList) { + for (FmiBuilder.Port p : filterList) { if (!isLinked.test(p)) { logger.warn("Filter for setLinked contains unlined port. Its ignored. {}", p); } @@ -1041,11 +1040,11 @@ public void setLinked(Fmi2Builder.Scope scope, Fmi2Builder.Port[]) null); + this.setLinked(dynamicScope, (FmiBuilder.Port[]) null); } @Override - public void setLinked(Fmi2Builder.Port... filterPorts) { + public void setLinked(FmiBuilder.Port... filterPorts) { this.setLinked(dynamicScope, filterPorts); } @@ -1053,24 +1052,24 @@ public void setLinked(Fmi2Builder.Port... filterPorts) { @Override public void setLinked(String... filterNames) { List accept = Arrays.asList(filterNames); - this.setLinked(dynamicScope, getPorts().stream().filter(p -> accept.contains(p.getName())).toArray(Fmi2Builder.Port[]::new)); + this.setLinked(dynamicScope, getPorts().stream().filter(p -> accept.contains(p.getName())).toArray(FmiBuilder.Port[]::new)); } @Override public void setLinked(long... filterValueReferences) { List accept = Arrays.stream(filterValueReferences).boxed().collect(Collectors.toList()); - this.setLinked(dynamicScope, getPorts().stream().filter(p -> accept.contains(p.getPortReferenceValue())).toArray(Fmi2Builder.Port[]::new)); + this.setLinked(dynamicScope, getPorts().stream().filter(p -> accept.contains(p.getPortReferenceValue())).toArray(FmiBuilder.Port[]::new)); } @Override - public void setInt(Map> values) { + public void setInt(Map> values) { } @Override - public void setString(Map> value) { + public void setString(Map> value) { } @@ -1080,7 +1079,7 @@ public void terminate() { } @Override - public void terminate(Fmi2Builder.Scope scope) { + public void terminate(FmiBuilder.Scope scope) { PStm stm = stateTransitionFunction(FmiFunctionType.TERMINATE); scope.add(stm); if (builder.getSettings().fmiErrorHandlingEnabled) { @@ -1091,7 +1090,7 @@ public void terminate(Fmi2Builder.Scope scope) { // TODO: implement this from the other share function below. This for now to build. @Override - public void share(Map, ? extends Fmi2Builder.Variable> values) { + public void share(Map, ? extends FmiBuilder.Variable> values) { ; } @@ -1256,12 +1255,12 @@ private ArrayVariableFmi2Api growBuffer(ArrayVariableFmi2Api buf } @Override - public Fmi2Builder.StateVariable getState() throws XPathExpressionException { + public FmiBuilder.StateVariable getState() throws XPathExpressionException { return getState(builder.getDynamicScope()); } @Override - public Fmi2Builder.StateVariable getState(Fmi2Builder.Scope scope) throws XPathExpressionException { + public FmiBuilder.StateVariable getState(FmiBuilder.Scope scope) throws XPathExpressionException { if (!this.modelDescriptionContext.getModelDescription().getCanGetAndSetFmustate()) { throw new RuntimeException("Unable to get state on fmu: " + this.getOwner() + " with instance name: " + this.getName()); } diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/IntVariableFmi2Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/IntVariableFmi2Api.java index 94a45f8ec..db5911373 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/IntVariableFmi2Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/IntVariableFmi2Api.java @@ -1,14 +1,14 @@ package org.intocps.maestro.framework.fmi2.api.mabl.variables; import org.intocps.maestro.ast.node.*; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.IMablScope; import org.intocps.maestro.framework.fmi2.api.mabl.values.IntExpressionValue; import static org.intocps.maestro.ast.MableAstFactory.*; -public class IntVariableFmi2Api extends VariableFmi2Api implements Fmi2Builder.IntVariable { - public IntVariableFmi2Api(PStm declaration, IMablScope declaredScope, Fmi2Builder.DynamicActiveScope dynamicScope, +public class IntVariableFmi2Api extends VariableFmi2Api implements FmiBuilder.IntVariable { + public IntVariableFmi2Api(PStm declaration, IMablScope declaredScope, FmiBuilder.DynamicActiveScope dynamicScope, PStateDesignator designator, PExp referenceExp) { super(declaration, newARealNumericPrimitiveType(), declaredScope, dynamicScope, designator, referenceExp); } @@ -19,7 +19,7 @@ public void decrement() { this.decrement(dynamicScope); } - public void decrement(Fmi2Builder.Scope scope) { + public void decrement(FmiBuilder.Scope scope) { scope.add(newAAssignmentStm(this.getDesignator(), newMinusExp(this.getReferenceExp(), newAIntLiteralExp(1)))); } @@ -34,11 +34,11 @@ public IntExpressionValue toMath() { } @Override - public void setValue(Fmi2Builder.IntExpressionValue addition) { + public void setValue(FmiBuilder.IntExpressionValue addition) { declaredScope.add(newAAssignmentStm(this.getDesignator(), addition.getExp())); } - public void increment(Fmi2Builder.Scope scope) { + public void increment(FmiBuilder.Scope scope) { scope.add(newAAssignmentStm(this.getDesignator(), newPlusExp(this.getReferenceExp(), newAIntLiteralExp(1)))); } diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/PortVariableMapImpl.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/PortVariableMapImpl.java index a84690828..dec8237c8 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/PortVariableMapImpl.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/PortVariableMapImpl.java @@ -1,13 +1,12 @@ package org.intocps.maestro.framework.fmi2.api.mabl.variables; import org.intocps.maestro.ast.node.PStm; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import java.util.HashMap; import java.util.Map; -public class PortVariableMapImpl extends HashMap, Fmi2Builder.Variable> implements Fmi2Builder.FmiSimulationInstance.PortVariableMap { +public class PortVariableMapImpl extends HashMap, FmiBuilder.Variable> implements FmiBuilder.FmiSimulationInstance.PortVariableMap { public PortVariableMapImpl(int initialCapacity, float loadFactor) { super(initialCapacity, loadFactor); } @@ -19,7 +18,7 @@ public PortVariableMapImpl(int initialCapacity) { public PortVariableMapImpl() { } - public PortVariableMapImpl(Map, ? extends Fmi2Builder.Variable> m) { + public PortVariableMapImpl(Map, ? extends FmiBuilder.Variable> m) { super(m); } } diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/RuntimeModuleVariable.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/RuntimeModuleVariable.java index e708de6a0..97f32d8c2 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/RuntimeModuleVariable.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/RuntimeModuleVariable.java @@ -5,7 +5,7 @@ import org.intocps.maestro.ast.node.PStateDesignator; import org.intocps.maestro.ast.node.PStm; import org.intocps.maestro.ast.node.PType; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.BuilderUtil; import org.intocps.maestro.framework.fmi2.api.mabl.MablApiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.IMablScope; @@ -15,16 +15,16 @@ import static org.intocps.maestro.ast.MableAstFactory.*; -public class RuntimeModuleVariable extends VariableFmi2Api> implements Fmi2Builder.RuntimeModule { +public class RuntimeModuleVariable extends VariableFmi2Api> implements FmiBuilder.RuntimeModule { private final MablApiBuilder builder; private boolean external = false; - public RuntimeModuleVariable(PStm declaration, PType type, IMablScope declaredScope, Fmi2Builder.DynamicActiveScope dynamicScope, + public RuntimeModuleVariable(PStm declaration, PType type, IMablScope declaredScope, FmiBuilder.DynamicActiveScope dynamicScope, MablApiBuilder builder, PStateDesignator designator, PExp referenceExp) { this(declaration, type, declaredScope, dynamicScope, builder, designator, referenceExp, false); } - public RuntimeModuleVariable(PStm declaration, PType type, IMablScope declaredScope, Fmi2Builder.DynamicActiveScope dynamicScope, + public RuntimeModuleVariable(PStm declaration, PType type, IMablScope declaredScope, FmiBuilder.DynamicActiveScope dynamicScope, MablApiBuilder builder, PStateDesignator designator, PExp referenceExp, boolean external) { super(declaration, type, declaredScope, dynamicScope, designator, referenceExp); this.builder = builder; @@ -32,31 +32,31 @@ public RuntimeModuleVariable(PStm declaration, PType type, IMablScope declaredSc } @Override - public void initialize(List declaredFuncs) { + public void initialize(List declaredFuncs) { } @Override - public void initialize(Fmi2Builder.RuntimeFunction... declaredFuncs) { + public void initialize(FmiBuilder.RuntimeFunction... declaredFuncs) { } @Override - public void callVoid(Fmi2Builder.RuntimeFunction functionId, Object... args) { + public void callVoid(FmiBuilder.RuntimeFunction functionId, Object... args) { callVoid(dynamicScope, functionId, args); } @Override - public void callVoid(Fmi2Builder.Scope scope, Fmi2Builder.RuntimeFunction functionId, Object... args) { + public void callVoid(FmiBuilder.Scope scope, FmiBuilder.RuntimeFunction functionId, Object... args) { PStm stm = newExpressionStm(MableBuilder.call(this.getReferenceExp().clone(), functionId.getName(), BuilderUtil.toExp(args).stream().map(PExp::clone).collect(Collectors.toList()))); scope.add(stm); } @Override - public Fmi2Builder.Variable call(Fmi2Builder.Scope scope, Fmi2Builder.RuntimeFunction functionId, Object... args) { + public FmiBuilder.Variable call(FmiBuilder.Scope scope, FmiBuilder.RuntimeFunction functionId, Object... args) { if (functionId.getReturnType().isNative() && - functionId.getReturnType().getNativeType() == Fmi2Builder.RuntimeFunction.FunctionType.Type.Void) { + functionId.getReturnType().getNativeType() == FmiBuilder.RuntimeFunction.FunctionType.Type.Void) { callVoid(scope, functionId, args); return null; } @@ -76,16 +76,16 @@ public Fmi2Builder.Variable call(Fmi2Builder.Scope scope, Fmi return null; case Int: case UInt: - return (Fmi2Builder.Variable) new IntVariableFmi2Api(stm, (IMablScope) scope, dynamicScope, + return (FmiBuilder.Variable) new IntVariableFmi2Api(stm, (IMablScope) scope, dynamicScope, newAIdentifierStateDesignator(name), newAIdentifierExp(name)); case Double: - return (Fmi2Builder.Variable) new DoubleVariableFmi2Api(stm, (IMablScope) scope, dynamicScope, + return (FmiBuilder.Variable) new DoubleVariableFmi2Api(stm, (IMablScope) scope, dynamicScope, newAIdentifierStateDesignator(name), newAIdentifierExp(name)); case String: - return (Fmi2Builder.Variable) new StringVariableFmi2Api(stm, (IMablScope) scope, dynamicScope, + return (FmiBuilder.Variable) new StringVariableFmi2Api(stm, (IMablScope) scope, dynamicScope, newAIdentifierStateDesignator(name), newAIdentifierExp(name)); case Boolean: - return (Fmi2Builder.Variable) new BooleanVariableFmi2Api(stm, (IMablScope) scope, dynamicScope, + return (FmiBuilder.Variable) new BooleanVariableFmi2Api(stm, (IMablScope) scope, dynamicScope, newAIdentifierStateDesignator(name), newAIdentifierExp(name)); } } @@ -93,7 +93,7 @@ public Fmi2Builder.Variable call(Fmi2Builder.Scope scope, Fmi newAIdentifierExp(name)); } - private PType getMablType(Fmi2Builder.RuntimeFunction.FunctionType type) { + private PType getMablType(FmiBuilder.RuntimeFunction.FunctionType type) { if (!type.isNative()) { return newANameType(type.getNamedType()); } @@ -116,7 +116,7 @@ private PType getMablType(Fmi2Builder.RuntimeFunction.FunctionType type) { } @Override - public Fmi2Builder.Variable call(Fmi2Builder.RuntimeFunction functionId, Object... args) { + public FmiBuilder.Variable call(FmiBuilder.RuntimeFunction functionId, Object... args) { return call(dynamicScope, functionId, args); } diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/StateMablVariableFmi2Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/StateMablVariableFmi2Api.java index 1dea8288d..03ae74b68 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/StateMablVariableFmi2Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/StateMablVariableFmi2Api.java @@ -1,7 +1,7 @@ package org.intocps.maestro.framework.fmi2.api.mabl.variables; import org.intocps.maestro.ast.node.*; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.MablApiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.IMablScope; @@ -10,12 +10,12 @@ import static org.intocps.maestro.ast.MableAstFactory.newAAssignmentStm; import static org.intocps.maestro.ast.MableBuilder.call; -public class StateMablVariableFmi2Api extends VariableFmi2Api implements Fmi2Builder.StateVariable { +public class StateMablVariableFmi2Api extends VariableFmi2Api implements FmiBuilder.StateVariable { private final ComponentVariableFmi2Api owner; private final MablApiBuilder builder; private boolean valid = true; - public StateMablVariableFmi2Api(PStm declaration, PType type, IMablScope declaredScope, Fmi2Builder.DynamicActiveScope dynamicScope, + public StateMablVariableFmi2Api(PStm declaration, PType type, IMablScope declaredScope, FmiBuilder.DynamicActiveScope dynamicScope, PStateDesignator designator, PExp referenceExp, MablApiBuilder builder, ComponentVariableFmi2Api owner) { super(declaration, type, declaredScope, dynamicScope, designator, referenceExp); this.owner = owner; @@ -29,9 +29,8 @@ public void set() throws IllegalStateException { } - @Override - public void set(Fmi2Builder.Scope scope) throws IllegalStateException { + public void set(FmiBuilder.Scope scope) throws IllegalStateException { if (!valid) { throw new IllegalStateException(); } @@ -39,9 +38,8 @@ public void set(Fmi2Builder.Scope scope) throws IllegalStateException { call(owner.getReferenceExp().clone(), "setState", Collections.singletonList(this.getReferenceExp().clone()))); scope.add(stm); if (builder.getSettings().fmiErrorHandlingEnabled) { - ComponentVariableFmi2Api.FmiStatusErrorHandlingBuilder - .generate(builder, "setState", this.owner, (IMablScope) scope, MablApiBuilder.FmiStatus.FMI_ERROR, - MablApiBuilder.FmiStatus.FMI_FATAL); + ComponentVariableFmi2Api.FmiStatusErrorHandlingBuilder.generate(builder, "setState", this.owner, (IMablScope) scope, + MablApiBuilder.FmiStatus.FMI_ERROR, MablApiBuilder.FmiStatus.FMI_FATAL); } } @@ -51,7 +49,7 @@ public void destroy() throws IllegalStateException { } @Override - public void destroy(Fmi2Builder.Scope scope) throws IllegalStateException { + public void destroy(FmiBuilder.Scope scope) throws IllegalStateException { if (!valid) { throw new IllegalStateException(); } @@ -60,16 +58,15 @@ public void destroy(Fmi2Builder.Scope scope) throws IllegalStateException call(owner.getReferenceExp().clone(), "freeState", Collections.singletonList(this.getReferenceExp().clone()))); scope.add(stm); if (builder.getSettings().fmiErrorHandlingEnabled) { - ComponentVariableFmi2Api.FmiStatusErrorHandlingBuilder - .generate(builder, "freeState", this.owner, (IMablScope) scope, MablApiBuilder.FmiStatus.FMI_ERROR, - MablApiBuilder.FmiStatus.FMI_FATAL); + ComponentVariableFmi2Api.FmiStatusErrorHandlingBuilder.generate(builder, "freeState", this.owner, (IMablScope) scope, + MablApiBuilder.FmiStatus.FMI_ERROR, MablApiBuilder.FmiStatus.FMI_FATAL); } valid = false; } @Override - public void setValue(Fmi2Builder.Scope scope, Object value) { + public void setValue(FmiBuilder.Scope scope, Object value) { throw new IllegalStateException(); } diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/StateMablVariableFmi3Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/StateMablVariableFmi3Api.java index 826610ad2..6cc2b25cd 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/StateMablVariableFmi3Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/StateMablVariableFmi3Api.java @@ -1,7 +1,7 @@ package org.intocps.maestro.framework.fmi2.api.mabl.variables; import org.intocps.maestro.ast.node.*; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.MablApiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.IMablScope; @@ -10,12 +10,12 @@ import static org.intocps.maestro.ast.MableAstFactory.newAAssignmentStm; import static org.intocps.maestro.ast.MableBuilder.call; -public class StateMablVariableFmi3Api extends VariableFmi2Api implements Fmi2Builder.StateVariable { +public class StateMablVariableFmi3Api extends VariableFmi2Api implements FmiBuilder.StateVariable { private final InstanceVariableFmi3Api owner; private final MablApiBuilder builder; private boolean valid = true; - public StateMablVariableFmi3Api(PStm declaration, PType type, IMablScope declaredScope, Fmi2Builder.DynamicActiveScope dynamicScope, + public StateMablVariableFmi3Api(PStm declaration, PType type, IMablScope declaredScope, FmiBuilder.DynamicActiveScope dynamicScope, PStateDesignator designator, PExp referenceExp, MablApiBuilder builder, InstanceVariableFmi3Api owner) { super(declaration, type, declaredScope, dynamicScope, designator, referenceExp); this.owner = owner; @@ -29,7 +29,7 @@ public void set() throws IllegalStateException { } @Override - public void set(Fmi2Builder.Scope scope) throws IllegalStateException { + public void set(FmiBuilder.Scope scope) throws IllegalStateException { if (!valid) { throw new IllegalStateException(); } @@ -37,9 +37,8 @@ public void set(Fmi2Builder.Scope scope) throws IllegalStateException { call(owner.getReferenceExp().clone(), "setState", Collections.singletonList(this.getReferenceExp().clone()))); scope.add(stm); if (builder.getSettings().fmiErrorHandlingEnabled) { - InstanceVariableFmi3Api.FmiStatusErrorHandlingBuilder - .generate(builder, "setState", this.owner, (IMablScope) scope, MablApiBuilder.FmiStatus.FMI_ERROR, - MablApiBuilder.FmiStatus.FMI_FATAL); + InstanceVariableFmi3Api.FmiStatusErrorHandlingBuilder.generate(builder, "setState", this.owner, (IMablScope) scope, + MablApiBuilder.FmiStatus.FMI_ERROR, MablApiBuilder.FmiStatus.FMI_FATAL); } } @@ -49,7 +48,7 @@ public void destroy() throws IllegalStateException { } @Override - public void destroy(Fmi2Builder.Scope scope) throws IllegalStateException { + public void destroy(FmiBuilder.Scope scope) throws IllegalStateException { if (!valid) { throw new IllegalStateException(); } @@ -58,16 +57,15 @@ public void destroy(Fmi2Builder.Scope scope) throws IllegalStateException call(owner.getReferenceExp().clone(), "freeState", Collections.singletonList(this.getReferenceExp().clone()))); scope.add(stm); if (builder.getSettings().fmiErrorHandlingEnabled) { - InstanceVariableFmi3Api.FmiStatusErrorHandlingBuilder - .generate(builder, "freeState", this.owner, (IMablScope) scope, MablApiBuilder.FmiStatus.FMI_ERROR, - MablApiBuilder.FmiStatus.FMI_FATAL); + InstanceVariableFmi3Api.FmiStatusErrorHandlingBuilder.generate(builder, "freeState", this.owner, (IMablScope) scope, + MablApiBuilder.FmiStatus.FMI_ERROR, MablApiBuilder.FmiStatus.FMI_FATAL); } valid = false; } @Override - public void setValue(Fmi2Builder.Scope scope, Object value) { + public void setValue(FmiBuilder.Scope scope, Object value) { throw new IllegalStateException(); } diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/StringVariableFmi2Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/StringVariableFmi2Api.java index 46a798b17..35503c009 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/StringVariableFmi2Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/StringVariableFmi2Api.java @@ -3,13 +3,13 @@ import org.intocps.maestro.ast.node.PExp; import org.intocps.maestro.ast.node.PStateDesignator; import org.intocps.maestro.ast.node.PStm; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.IMablScope; import static org.intocps.maestro.ast.MableAstFactory.newAStringPrimitiveType; -public class StringVariableFmi2Api extends VariableFmi2Api implements Fmi2Builder.StringVariable { - public StringVariableFmi2Api(PStm declaration, IMablScope declaredScope, Fmi2Builder.DynamicActiveScope dynamicScope, +public class StringVariableFmi2Api extends VariableFmi2Api implements FmiBuilder.StringVariable { + public StringVariableFmi2Api(PStm declaration, IMablScope declaredScope, FmiBuilder.DynamicActiveScope dynamicScope, PStateDesignator designator, PExp referenceExp) { super(declaration, newAStringPrimitiveType(), declaredScope, dynamicScope, designator, referenceExp); } diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/VariableCreatorFmi2Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/VariableCreatorFmi2Api.java index 5346e6bdf..0ed50e495 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/VariableCreatorFmi2Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/VariableCreatorFmi2Api.java @@ -9,7 +9,7 @@ import org.intocps.maestro.ast.node.PType; import org.intocps.maestro.fmi.Fmi2ModelDescription; import org.intocps.maestro.framework.fmi2.FmuFactory; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.*; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.DynamicActiveBuilderScope; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.IMablScope; @@ -54,7 +54,7 @@ public static PType fmitypetomabltype(Fmi2ModelDescription.Types type) { } public static VariableFmi2Api createVariableForPort(TagNameGenerator nameGenerator, PortFmi2Api port, IMablScope scope, - Fmi2Builder.DynamicActiveScope dynamicScope) { + FmiBuilder.DynamicActiveScope dynamicScope) { var name = nameGenerator.getName(port.toLexName()); var type = MableAstFactory.newAArrayType(fmitypetomabltype(port.scalarVariable.type.type)); var size = 1; diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/VariableCreatorFmi3Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/VariableCreatorFmi3Api.java index b6db8eaa4..154b44e1c 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/VariableCreatorFmi3Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/VariableCreatorFmi3Api.java @@ -2,7 +2,6 @@ import org.intocps.fmi.IFmu; import org.intocps.maestro.ast.MableAstFactory; -import org.intocps.maestro.ast.MableBuilder; import org.intocps.maestro.ast.node.AErrorStm; import org.intocps.maestro.ast.node.ALoadExp; import org.intocps.maestro.ast.node.PStm; @@ -10,7 +9,6 @@ import org.intocps.maestro.fmi.Fmi2ModelDescription; import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; import org.intocps.maestro.framework.fmi2.FmuFactory; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; import org.intocps.maestro.framework.fmi2.api.mabl.*; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.DynamicActiveBuilderScope; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.IMablScope; @@ -54,18 +52,18 @@ public static PType fmitypetomabltype(Fmi2ModelDescription.Types type) { } } -// public static VariableFmi2Api createVariableForPort(TagNameGenerator nameGenerator, PortFmi2Api port, IMablScope scope, -// Fmi2Builder.DynamicActiveScope dynamicScope) { -// var name = nameGenerator.getName(port.toLexName()); -// var type = MableAstFactory.newAArrayType(fmitypetomabltype(port.scalarVariable.type.type)); -// var size = 1; -// PStm stm = MableBuilder.newVariable(name, type, size); -// scope.add(stm); -// VariableFmi2Api variable = new VariableFmi2Api(stm, type, scope, dynamicScope, -// newAArayStateDesignator(newAIdentifierStateDesignator(newAIdentifier(name)), newAIntLiteralExp(0)), -// newAArrayIndexExp(newAIdentifierExp(name), Arrays.asList(newAIntLiteralExp(0)))); -// return variable; -// } + // public static VariableFmi2Api createVariableForPort(TagNameGenerator nameGenerator, PortFmi2Api port, IMablScope scope, + // Fmi2Builder.DynamicActiveScope dynamicScope) { + // var name = nameGenerator.getName(port.toLexName()); + // var type = MableAstFactory.newAArrayType(fmitypetomabltype(port.scalarVariable.type.type)); + // var size = 1; + // PStm stm = MableBuilder.newVariable(name, type, size); + // scope.add(stm); + // VariableFmi2Api variable = new VariableFmi2Api(stm, type, scope, dynamicScope, + // newAArayStateDesignator(newAIdentifierStateDesignator(newAIdentifier(name)), newAIntLiteralExp(0)), + // newAArrayIndexExp(newAIdentifierExp(name), Arrays.asList(newAIntLiteralExp(0)))); + // return variable; + // } public static FmuVariableFmi3Api createFMU(MablApiBuilder builder, TagNameGenerator nameGenerator, DynamicActiveBuilderScope dynamicScope, String name, URI uriPath, IMablScope scope) throws Exception { @@ -112,8 +110,8 @@ public static FmuVariableFmi3Api createFMU(MablApiBuilder builder, TagNameGenera path = uriPath.getPath(); } - ALoadExp loadExp = newALoadExp( - Arrays.asList(newAStringLiteralExp("FMI3"), newAStringLiteralExp(modelDescription.getInstantiationToken()), newAStringLiteralExp(path))); + ALoadExp loadExp = newALoadExp(Arrays.asList(newAStringLiteralExp("FMI3"), newAStringLiteralExp(modelDescription.getInstantiationToken()), + newAStringLiteralExp(path))); final ModelDescriptionContext3 ctxt = new ModelDescriptionContext3(modelDescription); diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/VariableFmi2Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/VariableFmi2Api.java index c624a8131..fac538054 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/VariableFmi2Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/VariableFmi2Api.java @@ -5,7 +5,7 @@ import org.intocps.maestro.ast.node.PStateDesignator; import org.intocps.maestro.ast.node.PStm; import org.intocps.maestro.ast.node.PType; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.BuilderUtil; import org.intocps.maestro.framework.fmi2.api.mabl.NumericExpressionValueFmi2Api; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.IMablScope; @@ -14,7 +14,7 @@ import static org.intocps.maestro.ast.MableAstFactory.newAAssignmentStm; -public class VariableFmi2Api implements Fmi2Builder.Variable, IndexedVariableFmi2Api, Fmi2Builder.ProvidesTypedReferenceExp { +public class VariableFmi2Api implements FmiBuilder.Variable, IndexedVariableFmi2Api, FmiBuilder.ProvidesTypedReferenceExp { private final PStateDesignator designator; private final PExp referenceExp; @@ -23,10 +23,10 @@ public class VariableFmi2Api implements Fmi2Builder.Variable, Indexe */ private final PStm declaration; protected PType type; - protected Fmi2Builder.DynamicActiveScope dynamicScope; + protected FmiBuilder.DynamicActiveScope dynamicScope; IMablScope declaredScope; - public VariableFmi2Api(PStm declaration, PType type, IMablScope declaredScope, Fmi2Builder.DynamicActiveScope dynamicScope, + public VariableFmi2Api(PStm declaration, PType type, IMablScope declaredScope, FmiBuilder.DynamicActiveScope dynamicScope, PStateDesignator designator, PExp referenceExp) { if (declaration != null && (declaredScope == null || declaredScope.indexOf(declaration) == -1)) { throw new IllegalArgumentException("Declared scope is illegal it does not declare the declaration"); @@ -63,18 +63,18 @@ public void setValue(V value) { } @Override - public void setValue(Fmi2Builder.Variable variable) { + public void setValue(FmiBuilder.Variable variable) { setValue(dynamicScope, variable); } @Override - public void setValue(Fmi2Builder.Scope scope, Fmi2Builder.Variable variable) { + public void setValue(FmiBuilder.Scope scope, FmiBuilder.Variable variable) { //TODO use BuilderUtil.createTypeConvertingAssignment(bui) scope.add(newAAssignmentStm(this.designator.clone(), ((VariableFmi2Api) variable).getReferenceExp().clone())); } @Override - public void setValue(Fmi2Builder.Scope scope, V value) { + public void setValue(FmiBuilder.Scope scope, V value) { if (!(value instanceof DoubleExpressionValue)) { throw new IllegalArgumentException(); } @@ -104,7 +104,7 @@ public PExp getExp() { return this.referenceExp.clone(); } - protected void setValue(Fmi2Builder.Scope scope, PExp exp) { + protected void setValue(FmiBuilder.Scope scope, PExp exp) { scope.add(MableAstFactory.newAAssignmentStm(this.designator.clone(), exp)); } @@ -127,11 +127,11 @@ public NumericExpressionValueFmi2Api toMath() { } } - public void setValue(Fmi2Builder.ExpressionValue value) { + public void setValue(FmiBuilder.ExpressionValue value) { this.setValue(dynamicScope, value); } - private void setValue(Fmi2Builder.DynamicActiveScope dynamicScope, Fmi2Builder.ExpressionValue value) { + private void setValue(FmiBuilder.DynamicActiveScope dynamicScope, FmiBuilder.ExpressionValue value) { this.dynamicScope.addAll(BuilderUtil.createTypeConvertingAssignment(this.designator, value.getExp(), value.getType(), this.getType())); } } \ No newline at end of file diff --git a/frameworks/fmi2api/src/main/kotlin/DerivativeEstimator.kt b/frameworks/fmi2api/src/main/kotlin/DerivativeEstimator.kt index a21c6a3c7..560809b0a 100644 --- a/frameworks/fmi2api/src/main/kotlin/DerivativeEstimator.kt +++ b/frameworks/fmi2api/src/main/kotlin/DerivativeEstimator.kt @@ -11,7 +11,7 @@ import org.intocps.maestro.framework.fmi2.api.mabl.variables.DoubleVariableFmi2A class DerivativeEstimator( private val dynamicScope: DynamicActiveBuilderScope, private val mablApiBuilder: MablApiBuilder, - private val runtimeModule: Fmi2Builder.RuntimeModule? + private val runtimeModule: FmiBuilder.RuntimeModule? ) { private val moduleIdentifier: String = runtimeModule?.name ?: "derivativeEstimator" @@ -42,7 +42,7 @@ class DerivativeEstimator( private val dynamicScope: DynamicActiveBuilderScope, private val mablApiBuilder: MablApiBuilder, private val derivativeEstimator: DerivativeEstimator, - private val runtimeModule: Fmi2Builder.RuntimeModule? + private val runtimeModule: FmiBuilder.RuntimeModule? ) { private val TYPE_DERIVATIVEESTIMATORINSTANCE = "DerivativeEstimatorInstance" diff --git a/frameworks/fmi2api/src/test/java/org/intocps/maestro/framework/fmi2/api/mabl/SetPortsTest.java b/frameworks/fmi2api/src/test/java/org/intocps/maestro/framework/fmi2/api/mabl/SetPortsTest.java index 5c0b6bcaa..2651f7f30 100644 --- a/frameworks/fmi2api/src/test/java/org/intocps/maestro/framework/fmi2/api/mabl/SetPortsTest.java +++ b/frameworks/fmi2api/src/test/java/org/intocps/maestro/framework/fmi2/api/mabl/SetPortsTest.java @@ -1,7 +1,7 @@ package org.intocps.maestro.framework.fmi2.api.mabl; import org.intocps.maestro.fmi.Fmi2ModelDescription; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.DynamicActiveBuilderScope; import org.intocps.maestro.framework.fmi2.api.mabl.values.PortValueMapImpl; import org.intocps.maestro.framework.fmi2.api.mabl.variables.ComponentVariableFmi2Api; @@ -37,7 +37,7 @@ public void undeclaredPortsTest() throws Exception { controllerInstance.get(controllerInstance.getPorts().stream().map(PortFmi2Api::getName).toArray(String[]::new)); controllerInstance.share(controllerPortMap); - Fmi2Builder.Fmi2ComponentVariable.PortValueMap portsToSet = + FmiBuilder.Fmi2ComponentVariable.PortValueMap portsToSet = new PortValueMapImpl(controllerPortMap); // ASSERT diff --git a/maestro/src/main/java/org/intocps/maestro/BuilderHelper.java b/maestro/src/main/java/org/intocps/maestro/BuilderHelper.java index 6e3dafab1..cc58232f0 100644 --- a/maestro/src/main/java/org/intocps/maestro/BuilderHelper.java +++ b/maestro/src/main/java/org/intocps/maestro/BuilderHelper.java @@ -10,7 +10,7 @@ import org.intocps.maestro.framework.fmi2.ComponentInfo; import org.intocps.maestro.framework.fmi2.Fmi2SimulationEnvironment; import org.intocps.maestro.framework.fmi2.InstanceInfo; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.FromMaBLToMaBLAPI; import org.intocps.maestro.framework.fmi2.api.mabl.MablApiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.ModelDescriptionContext; @@ -35,10 +35,10 @@ public class BuilderHelper { static final TypeComparator typeComparator = new TypeComparator(); private final MablApiBuilder builder; - List> variables; + List> variables; public BuilderHelper(ACallExp callToBeReplaced, Map typesMap, - ISimulationEnvironment simulationEnvironment) throws Fmi2Builder.Port.PortLinkException, AnalysisException { + ISimulationEnvironment simulationEnvironment) throws FmiBuilder.Port.PortLinkException, AnalysisException { MablApiBuilder.MablSettings settings = new MablApiBuilder.MablSettings(); settings.fmiErrorHandlingEnabled = true; @@ -95,7 +95,7 @@ public void caseAInstanceMappingStm(AInstanceMappingStm node, return graph; } - private static Fmi2Builder.Variable wrapAsVariable(MablApiBuilder builder, Map typesMap, + private static FmiBuilder.Variable wrapAsVariable(MablApiBuilder builder, Map typesMap, ISimulationEnvironment simulationEnvironment, PType type, PExp exp, Map instances, Map fmi3Instances, DefaultDirectedGraph graph) { @@ -200,20 +200,19 @@ public void caseAInstanceMappingStm(AInstanceMappingStm node, List initializerExps = initializer.getExp().stream().filter(AIdentifierExp.class::isInstance).map(AIdentifierExp.class::cast) .collect(Collectors.toList()); - return new ArrayVariableFmi2Api(null, type.clone(), null, null, null, exp, - initializerExps.stream().map(e -> wrapAsVariable(builder, typesMap, simulationEnvironment, typesMap.get(e), e, instances, - fmi3Instances, graph)) - .collect(Collectors.toList())); + return new ArrayVariableFmi2Api(null, type.clone(), null, null, null, exp, initializerExps.stream() + .map(e -> wrapAsVariable(builder, typesMap, simulationEnvironment, typesMap.get(e), e, instances, fmi3Instances, graph)) + .collect(Collectors.toList())); } return null; } - public Fmi2Builder getBuilder() { + public FmiBuilder getBuilder() { return this.builder; } - public List> getArgumentVariables() { + public List> getArgumentVariables() { return this.variables; } } diff --git a/maestro/src/test/java/org/intocps/maestro/BuilderFmi3Test.java b/maestro/src/test/java/org/intocps/maestro/BuilderFmi3Test.java index ff099d9cd..6aa031ad6 100644 --- a/maestro/src/test/java/org/intocps/maestro/BuilderFmi3Test.java +++ b/maestro/src/test/java/org/intocps/maestro/BuilderFmi3Test.java @@ -14,7 +14,7 @@ import org.intocps.maestro.fmi3.Fmi3ModuleReferenceFmusTest; import org.intocps.maestro.framework.fmi2.Fmi2SimulationEnvironment; import org.intocps.maestro.framework.fmi2.Fmi2SimulationEnvironmentConfiguration; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.LoggerFmi2Api; import org.intocps.maestro.framework.fmi2.api.mabl.MablApiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.PortFmi2Api; @@ -72,13 +72,13 @@ public void wt() throws Exception { LoggerFmi2Api logger = builder.getLogger(); - Fmi2Builder.IntVariable v8 = builder.getDynamicScope().enterTry().enter().store(6); + FmiBuilder.IntVariable v8 = builder.getDynamicScope().enterTry().enter().store(6); // Fmi2Builder.Variable logReturnValue = logger.call(func2, "ddd", 6, v8); URI ballUri = new File("target/Fmi3ModuleReferenceFmusTest/cache/BouncingBall.fmu").getAbsoluteFile().toURI(); Fmu3 ball = new Fmu3(new File(ballUri)); - ArrayVariableFmi2Api varArray = builder.getDynamicScope().store("varArray", new Long[] {1L}); + ArrayVariableFmi2Api varArray = builder.getDynamicScope().store("varArray", new Long[]{1L}); Fmi3ModelDescription md3Ball = new Fmi3ModelDescription(ball.getModelDescription()); @@ -129,9 +129,9 @@ public void wt() throws Exception { tank.setLinked(); // tank.set(); - Fmi2Builder.DoubleVariable var = dynamicScope.store(123.123); - Fmi2Builder.DoubleVariable current_time_point = dynamicScope.store(0.0); - Fmi2Builder.DoubleVariable step = dynamicScope.store(0.1); + FmiBuilder.DoubleVariable var = dynamicScope.store(123.123); + FmiBuilder.DoubleVariable current_time_point = dynamicScope.store(0.0); + FmiBuilder.DoubleVariable step = dynamicScope.store(0.1); tank.step(current_time_point, step); //Fmi2Builder.StateVariable s = tank.getState(); @@ -202,7 +202,7 @@ public interface ExtFunc { static class Logger extends ExternalVariable { final ExtFunc logFunc = null; - void log(Level level, String message, Fmi2Builder.IntVariable errorCode) { + void log(Level level, String message, FmiBuilder.IntVariable errorCode) { this.callVoid(logFunc, level == Level.Debug ? 1 : 0, message, errorCode); } diff --git a/maestro/src/test/java/org/intocps/maestro/BuilderTest.java b/maestro/src/test/java/org/intocps/maestro/BuilderTest.java index d4f99f6ab..41f12d077 100644 --- a/maestro/src/test/java/org/intocps/maestro/BuilderTest.java +++ b/maestro/src/test/java/org/intocps/maestro/BuilderTest.java @@ -11,7 +11,7 @@ import org.intocps.maestro.fmi.Fmi2ModelDescription; import org.intocps.maestro.framework.fmi2.Fmi2SimulationEnvironment; import org.intocps.maestro.framework.fmi2.Fmi2SimulationEnvironmentConfiguration; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.LoggerFmi2Api; import org.intocps.maestro.framework.fmi2.api.mabl.MablApiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.PortFmi2Api; @@ -39,8 +39,8 @@ public class BuilderTest { public void wt() throws Exception { InputStream is = this.getClass().getClassLoader().getResourceAsStream("buildertester/buildertester.json"); - Fmi2SimulationEnvironmentConfiguration simulationEnvironmentConfiguration = Fmi2SimulationEnvironmentConfiguration.createFromJsonString( - new String(Objects.requireNonNull(is).readAllBytes())); + Fmi2SimulationEnvironmentConfiguration simulationEnvironmentConfiguration = + Fmi2SimulationEnvironmentConfiguration.createFromJsonString(new String(Objects.requireNonNull(is).readAllBytes())); Fmi2SimulationEnvironment env = Fmi2SimulationEnvironment.of(simulationEnvironmentConfiguration, new IErrorReporter.SilentReporter()); @@ -62,14 +62,15 @@ public void wt() throws Exception { LoggerFmi2Api logger = builder.getLogger(); - Fmi2Builder.IntVariable v8 = builder.getDynamicScope().enterTry().enter().store(6); + FmiBuilder.IntVariable v8 = builder.getDynamicScope().enterTry().enter().store(6); // Fmi2Builder.Variable logReturnValue = logger.call(func2, "ddd", 6, v8); // Create the two FMUs FmuVariableFmi2Api controllerFMU = builder.getDynamicScope() - .createFMU("controllerFMU",(Fmi2ModelDescription) env.getModelDescription("{controllerFMU}"), env.getUriFromFMUName("{controllerFMU}")); + .createFMU("controllerFMU", (Fmi2ModelDescription) env.getModelDescription("{controllerFMU}"), + env.getUriFromFMUName("{controllerFMU}")); FmuVariableFmi2Api tankFMU = builder.getDynamicScope() - .createFMU("tankFMU", (Fmi2ModelDescription)env.getModelDescription("{tankFMU}"), env.getUriFromFMUName("{tankFMU}")); + .createFMU("tankFMU", (Fmi2ModelDescription) env.getModelDescription("{tankFMU}"), env.getUriFromFMUName("{tankFMU}")); // Create the controller and tank instanes ComponentVariableFmi2Api controller = controllerFMU.instantiate("controller"); @@ -106,9 +107,9 @@ public void wt() throws Exception { tank.setLinked(); // tank.set(); - Fmi2Builder.DoubleVariable var = dynamicScope.store(123.123); - Fmi2Builder.DoubleVariable current_time_point = dynamicScope.store(0.0); - Fmi2Builder.DoubleVariable step = dynamicScope.store(0.1); + FmiBuilder.DoubleVariable var = dynamicScope.store(123.123); + FmiBuilder.DoubleVariable current_time_point = dynamicScope.store(0.0); + FmiBuilder.DoubleVariable step = dynamicScope.store(0.1); tank.step(current_time_point, step); //Fmi2Builder.StateVariable s = tank.getState(); @@ -179,7 +180,7 @@ public interface ExtFunc { static class Logger extends ExternalVariable { final ExtFunc logFunc = null; - void log(Level level, String message, Fmi2Builder.IntVariable errorCode) { + void log(Level level, String message, FmiBuilder.IntVariable errorCode) { this.callVoid(logFunc, level == Level.Debug ? 1 : 0, message, errorCode); } diff --git a/maestro/src/test/java/org/intocps/maestro/ImportCliTest.java b/maestro/src/test/java/org/intocps/maestro/ImportCliTest.java index 38d500b1e..3a16e3c8a 100644 --- a/maestro/src/test/java/org/intocps/maestro/ImportCliTest.java +++ b/maestro/src/test/java/org/intocps/maestro/ImportCliTest.java @@ -46,8 +46,9 @@ public void importTestRelativeExistingFmus() { @Test public void importTestExistingFmu3Mix() { - String arguments = String.format(Locale.US, "import sg1 --inline-framework-config -output %s %s %s", getOutputPath().toAbsolutePath(), - simulationConfigPath.getAbsolutePath(), new File(resourcesConfigPrefix, "config-fmi3.json").toPath()); + String arguments = String.format(Locale.US, "import sg1 --interpret --dump-intermediate --inline-framework-config -output %s %s %s", + getOutputPath().toAbsolutePath(), simulationConfigPath.getAbsolutePath(), + new File(resourcesConfigPrefix, "config-fmi3.json").toPath()); String[] s = arguments.split(" "); int exitCode = new CommandLine(new Main()).setCaseInsensitiveEnumValuesAllowed(true).execute(s); diff --git a/maestro/src/test/java/org/intocps/maestro/fmi3/Fmi3ModuleTest.java b/maestro/src/test/java/org/intocps/maestro/fmi3/Fmi3ModuleTest.java index 8591e80e6..cd87ec595 100644 --- a/maestro/src/test/java/org/intocps/maestro/fmi3/Fmi3ModuleTest.java +++ b/maestro/src/test/java/org/intocps/maestro/fmi3/Fmi3ModuleTest.java @@ -1,7 +1,6 @@ package org.intocps.maestro.fmi3; import org.intocps.maestro.FullSpecTest; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; import org.junit.jupiter.params.provider.Arguments; import java.io.File; @@ -20,11 +19,11 @@ public class Fmi3ModuleTest extends FullSpecTest { - public static final Predicate hasMablSpec= - path-> path.isDirectory()&& Arrays.stream(Objects.requireNonNull(path.listFiles())).anyMatch(f->f.getName().endsWith(".mabl")); + public static final Predicate hasMablSpec = + path -> path.isDirectory() && Arrays.stream(Objects.requireNonNull(path.listFiles())).anyMatch(f -> f.getName().endsWith(".mabl")); private static Stream data() { - return Arrays.stream(Objects.requireNonNull(Paths.get("src", "test", "resources", "fmi3","basic").toFile().listFiles())) + return Arrays.stream(Objects.requireNonNull(Paths.get("src", "test", "resources", "fmi3", "basic").toFile().listFiles())) .filter(n -> !n.getName().startsWith(".")).filter(hasMablSpec).map(f -> Arguments.arguments(f.getName(), f)); } @@ -41,8 +40,7 @@ protected List getSpecificationFiles(File specFolder) { String content = null; try { content = Files.readString(path, charset); - content = content.replace("file:", - Paths.get("src","test","resources","fmi3","basic").toAbsolutePath().toUri().toString()); + content = content.replace("file:", Paths.get("src", "test", "resources", "fmi3", "basic").toAbsolutePath().toUri().toString()); Files.write(path, content.getBytes(charset)); } catch (IOException e) { throw new RuntimeException(e); diff --git a/plugins/api/src/main/java/org/intocps/maestro/plugin/BasicMaestroExpansionPlugin.java b/plugins/api/src/main/java/org/intocps/maestro/plugin/BasicMaestroExpansionPlugin.java index bf139591a..538e04ca7 100644 --- a/plugins/api/src/main/java/org/intocps/maestro/plugin/BasicMaestroExpansionPlugin.java +++ b/plugins/api/src/main/java/org/intocps/maestro/plugin/BasicMaestroExpansionPlugin.java @@ -5,7 +5,7 @@ import org.intocps.maestro.ast.node.*; import org.intocps.maestro.core.messages.IErrorReporter; import org.intocps.maestro.framework.core.ISimulationEnvironment; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import java.io.IOException; import java.io.InputStream; @@ -100,7 +100,7 @@ public List expand(AFunctionDeclaration declaredFunction, List forma */ @Override public RuntimeConfigAddition expandWithRuntimeAddition(AFunctionDeclaration declaredFunction, - Fmi2Builder builder, List> formalArguments, + FmiBuilder builder, List> formalArguments, IPluginConfiguration config, ISimulationEnvironment env, IErrorReporter errorReporter) throws ExpandException { return new EmptyRuntimeConfig<>(); } diff --git a/plugins/api/src/main/java/org/intocps/maestro/plugin/IMaestroExpansionPlugin.java b/plugins/api/src/main/java/org/intocps/maestro/plugin/IMaestroExpansionPlugin.java index 34cff71df..0808b4ad5 100644 --- a/plugins/api/src/main/java/org/intocps/maestro/plugin/IMaestroExpansionPlugin.java +++ b/plugins/api/src/main/java/org/intocps/maestro/plugin/IMaestroExpansionPlugin.java @@ -7,7 +7,7 @@ import org.intocps.maestro.ast.node.PStm; import org.intocps.maestro.core.messages.IErrorReporter; import org.intocps.maestro.framework.core.ISimulationEnvironment; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import java.io.IOException; import java.io.InputStream; @@ -57,7 +57,7 @@ Map.Entry, RuntimeConfigAddition> expandWithRuntimeAddition(AF * @throws ExpandException if generation fails */ RuntimeConfigAddition expandWithRuntimeAddition(AFunctionDeclaration declaredFunction, - Fmi2Builder builder, List> formalArguments, + FmiBuilder builder, List> formalArguments, IPluginConfiguration config, ISimulationEnvironment env, IErrorReporter errorReporter) throws ExpandException; diff --git a/plugins/demo/src/main/java/org/intocps/maestro/plugin/DemoBuilderPlugin.java b/plugins/demo/src/main/java/org/intocps/maestro/plugin/DemoBuilderPlugin.java index 87665c375..fa1d0823b 100644 --- a/plugins/demo/src/main/java/org/intocps/maestro/plugin/DemoBuilderPlugin.java +++ b/plugins/demo/src/main/java/org/intocps/maestro/plugin/DemoBuilderPlugin.java @@ -6,7 +6,7 @@ import org.intocps.maestro.core.Framework; import org.intocps.maestro.core.messages.IErrorReporter; import org.intocps.maestro.framework.core.ISimulationEnvironment; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.MablApiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.DynamicActiveBuilderScope; @@ -46,7 +46,7 @@ public ConfigOption getConfigRequirement() { @Override public RuntimeConfigAddition expandWithRuntimeAddition(AFunctionDeclaration declaredFunction, - Fmi2Builder builder, List> formalArguments, + FmiBuilder builder, List> formalArguments, IPluginConfiguration config, ISimulationEnvironment env, IErrorReporter errorReporter) throws ExpandException { diff --git a/plugins/initializer/src/main/kotlin/Initializer.kt b/plugins/initializer/src/main/kotlin/Initializer.kt index 188b546e6..78c6ae7bc 100644 --- a/plugins/initializer/src/main/kotlin/Initializer.kt +++ b/plugins/initializer/src/main/kotlin/Initializer.kt @@ -15,8 +15,8 @@ import org.intocps.maestro.framework.core.RelationVariable import org.intocps.maestro.framework.fmi2.Fmi2SimulationEnvironment import org.intocps.maestro.framework.fmi2.InvalidVariableStringException import org.intocps.maestro.framework.fmi2.ModelConnection -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder.ArrayVariable +import org.intocps.maestro.framework.fmi2.api.FmiBuilder +import org.intocps.maestro.framework.fmi2.api.FmiBuilder.ArrayVariable import org.intocps.maestro.framework.fmi2.api.mabl.* import org.intocps.maestro.framework.fmi2.api.mabl.scoping.DynamicActiveBuilderScope import org.intocps.maestro.framework.fmi2.api.mabl.scoping.ScopeFmi2Api @@ -106,9 +106,9 @@ class Initializer : BasicMaestroExpansionPlugin { var compilationUnit: AImportedModuleCompilationUnit? = null // Convergence related variables - var absoluteTolerance: Fmi2Builder.DoubleVariable? = null - var relativeTolerance: Fmi2Builder.DoubleVariable? = null - var maxConvergeAttempts: Fmi2Builder.IntVariable? = null + var absoluteTolerance: FmiBuilder.DoubleVariable? = null + var relativeTolerance: FmiBuilder.DoubleVariable? = null + var maxConvergeAttempts: FmiBuilder.IntVariable? = null constructor() { initializationPrologQuery = InitializationPrologQuery() @@ -144,9 +144,9 @@ class Initializer : BasicMaestroExpansionPlugin { */ fun getArg( declaredFunction: AFunctionDeclaration?, - formalArguments: MutableList>?, + formalArguments: MutableList>?, index: ARG_INDEX - ): Fmi2Builder.Variable? { + ): FmiBuilder.Variable? { when (declaredFunction) { f1 -> { return when (index) { @@ -193,7 +193,7 @@ class Initializer : BasicMaestroExpansionPlugin { env: Fmi2SimulationEnvironment, formalArguments: List, index: ARG_INDEX - ): Fmi2Builder.Variable? { + ): FmiBuilder.Variable? { when (declaredFunction) { f1 -> { return when (index) { @@ -205,7 +205,7 @@ class Initializer : BasicMaestroExpansionPlugin { null, null, FromMaBLToMaBLAPI.getComponentVariablesFrom(builder, formalArguments[0], env).values.stream() - .collect(Collectors.toList()) as List>>? + .collect(Collectors.toList()) as List>>? ); ARG_INDEX.START_TIME -> DoubleVariableFmi2Api(null, null, null, null, formalArguments[1].clone()); ARG_INDEX.END_TIME -> DoubleVariableFmi2Api(null, null, null, null, formalArguments[2].clone()); @@ -226,7 +226,7 @@ class Initializer : BasicMaestroExpansionPlugin { null, null, FromMaBLToMaBLAPI.getComponentVariablesFrom(builder, formalArguments[0], env).values.stream() - .collect(Collectors.toList()) as List>>? + .collect(Collectors.toList()) as List>>? ); ARG_INDEX.TRANSFER_INSTANCES -> ArrayVariableFmi2Api( null, @@ -236,7 +236,7 @@ class Initializer : BasicMaestroExpansionPlugin { null, null, FromMaBLToMaBLAPI.getComponentVariablesFrom(builder, formalArguments[1], env).values.stream() - .collect(Collectors.toList()) as List>>? + .collect(Collectors.toList()) as List>>? ); ARG_INDEX.START_TIME -> DoubleVariableFmi2Api(null, null, null, null, formalArguments[2].clone()); ARG_INDEX.END_TIME -> DoubleVariableFmi2Api(null, null, null, null, formalArguments[3].clone()); @@ -257,7 +257,7 @@ class Initializer : BasicMaestroExpansionPlugin { null, null, FromMaBLToMaBLAPI.getComponentVariablesFrom(builder, formalArguments[0], env).values.stream() - .collect(Collectors.toList()) as List>>? + .collect(Collectors.toList()) as List>>? ); ARG_INDEX.FMI3_INSTANCES -> null; ARG_INDEX.START_TIME -> DoubleVariableFmi2Api(null, null, null, null, formalArguments[2].clone()); @@ -289,8 +289,8 @@ class Initializer : BasicMaestroExpansionPlugin { override fun expandWithRuntimeAddition( declaredFunction: AFunctionDeclaration?, - builder: Fmi2Builder?, - formalArguments: MutableList>?, + builder: FmiBuilder?, + formalArguments: MutableList>?, config: IPluginConfiguration?, envIn: ISimulationEnvironment?, errorReporter: IErrorReporter? diff --git a/plugins/initializer/src/main/kotlin/instructions/ComplexCoSimInstruction.kt b/plugins/initializer/src/main/kotlin/instructions/ComplexCoSimInstruction.kt index 08a9f2f08..ca0699d3e 100644 --- a/plugins/initializer/src/main/kotlin/instructions/ComplexCoSimInstruction.kt +++ b/plugins/initializer/src/main/kotlin/instructions/ComplexCoSimInstruction.kt @@ -1,9 +1,11 @@ package org.intocps.maestro.plugin.initializer.instructions -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder +import org.intocps.maestro.framework.fmi2.api.FmiBuilder -abstract class ComplexCoSimInstruction(protected var simulationActions: List, - protected var scope: Fmi2Builder.Scope<*>) : CoSimInstruction { +abstract class ComplexCoSimInstruction( + protected var simulationActions: List, + protected var scope: FmiBuilder.Scope<*> +) : CoSimInstruction { override val isSimple: Boolean get() = false } \ No newline at end of file diff --git a/plugins/initializer/src/main/kotlin/instructions/LoopSimInstruction.kt b/plugins/initializer/src/main/kotlin/instructions/LoopSimInstruction.kt index 8804518f2..03d1822f5 100644 --- a/plugins/initializer/src/main/kotlin/instructions/LoopSimInstruction.kt +++ b/plugins/initializer/src/main/kotlin/instructions/LoopSimInstruction.kt @@ -2,7 +2,7 @@ package org.intocps.maestro.plugin.initializer.instructions import org.intocps.maestro.ast.node.PStm import org.intocps.maestro.fmi.Fmi2ModelDescription -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder +import org.intocps.maestro.framework.fmi2.api.FmiBuilder import org.intocps.maestro.framework.fmi2.api.mabl.BooleanBuilderFmi2Api import org.intocps.maestro.framework.fmi2.api.mabl.MathBuilderFmi2Api import org.intocps.maestro.framework.fmi2.api.mabl.PortFmi2Api @@ -11,32 +11,36 @@ import org.intocps.maestro.framework.fmi2.api.mabl.variables.ComponentVariableFm import org.intocps.maestro.framework.fmi2.api.mabl.variables.IntVariableFmi2Api import org.intocps.maestro.framework.fmi2.api.mabl.variables.VariableFmi2Api -class LoopSimInstruction(scope: Fmi2Builder.Scope<*>, private val maxStepAcceptAttempts: Fmi2Builder.IntVariable, - private val absoluteTolerance: Fmi2Builder.DoubleVariable, private val relativeTolerance: Fmi2Builder.DoubleVariable, - simulationActions: List, - private val convergencePorts: Map>>, - private val booleanLogic: BooleanBuilderFmi2Api, - private val math: MathBuilderFmi2Api) : ComplexCoSimInstruction(simulationActions, scope) { +class LoopSimInstruction( + scope: FmiBuilder.Scope<*>, + private val maxStepAcceptAttempts: FmiBuilder.IntVariable, + private val absoluteTolerance: FmiBuilder.DoubleVariable, + private val relativeTolerance: FmiBuilder.DoubleVariable, + simulationActions: List, + private val convergencePorts: Map>>, + private val booleanLogic: BooleanBuilderFmi2Api, + private val math: MathBuilderFmi2Api +) : ComplexCoSimInstruction(simulationActions, scope) { override fun perform() { - val algebraicLoop = scope.store( 5) as IntVariableFmi2Api; + val algebraicLoop = scope.store(5) as IntVariableFmi2Api; val basis = scope.store(0) as IntVariableFmi2Api; - val convergenceReached : BooleanVariableFmi2Api = scope.store("hasConverged", false) as BooleanVariableFmi2Api; + val convergenceReached: BooleanVariableFmi2Api = scope.store("hasConverged", false) as BooleanVariableFmi2Api; val stabilisationScope = scope - .enterWhile(convergenceReached.toPredicate().and(algebraicLoop.toMath().greaterThan(basis.toMath()))); + .enterWhile(convergenceReached.toPredicate().and(algebraicLoop.toMath().greaterThan(basis.toMath()))); run { simulationActions.forEach { action: CoSimInstruction -> action.perform() } val convergenceVariables: List = convergencePorts.entries.flatMap { (fmu, ports) -> ports.entries.filter { (p, _) -> p.scalarVariable.type.type == Fmi2ModelDescription.Types.Real } - .map { (port, v) -> - val oldVariable: VariableFmi2Api = port.sharedAsVariable - val newVariable: VariableFmi2Api = v - math.checkConvergence(oldVariable, newVariable, absoluteTolerance, relativeTolerance) - } + .map { (port, v) -> + val oldVariable: VariableFmi2Api = port.sharedAsVariable + val newVariable: VariableFmi2Api = v + math.checkConvergence(oldVariable, newVariable, absoluteTolerance, relativeTolerance) + } } convergenceReached.setValue(booleanLogic.allTrue("convergence", convergenceVariables)); diff --git a/plugins/jacobianstepbuilder/src/main/java/org/intocps/maestro/plugin/JacobianStepBuilder.java b/plugins/jacobianstepbuilder/src/main/java/org/intocps/maestro/plugin/JacobianStepBuilder.java index 4168084e4..f010b1a4b 100644 --- a/plugins/jacobianstepbuilder/src/main/java/org/intocps/maestro/plugin/JacobianStepBuilder.java +++ b/plugins/jacobianstepbuilder/src/main/java/org/intocps/maestro/plugin/JacobianStepBuilder.java @@ -20,7 +20,7 @@ import org.intocps.maestro.framework.fmi2.ComponentInfo; import org.intocps.maestro.framework.fmi2.Fmi2SimulationEnvironment; import org.intocps.maestro.framework.fmi2.ModelSwapInfo; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.*; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.DynamicActiveBuilderScope; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.IfMaBlScope; @@ -87,7 +87,7 @@ public class JacobianStepBuilder extends BasicMaestroExpansionPlugin { break; } - } catch (Fmi2Builder.Port.PortLinkException e) { + } catch (FmiBuilder.Port.PortLinkException e) { e.printStackTrace(); } }; @@ -98,7 +98,7 @@ public Set getDeclaredUnfoldFunctions() { @Override public RuntimeConfigAddition expandWithRuntimeAddition(AFunctionDeclaration declaredFunction, - Fmi2Builder parentBuilder, List> formalArguments, + FmiBuilder parentBuilder, List> formalArguments, IPluginConfiguration config, ISimulationEnvironment envIn, IErrorReporter errorReporter) throws ExpandException { @@ -183,7 +183,7 @@ public RuntimeConfigAddition expandWithRuntimeAddition(AFunctionDeclarati // Get FMU instances - use LinkedHashMap to preserve added order Map fmuInstances = - ((List) ((Fmi2Builder.ArrayVariable) formalArguments.get(0)).items()).stream() + ((List) ((FmiBuilder.ArrayVariable) formalArguments.get(0)).items()).stream() .collect(Collectors.toMap(ComponentVariableFmi2Api::getName, Function.identity(), (u, v) -> u, LinkedHashMap::new)); // Create the logging @@ -284,7 +284,7 @@ public RuntimeConfigAddition expandWithRuntimeAddition(AFunctionDeclarati realStartTime.setValue(Objects.requireNonNull(realTimeModule).getRealTime()); } - List> fmuStates = new ArrayList<>(); + List> fmuStates = new ArrayList<>(); BooleanVariableFmi2Api anyDiscards = dynamicScope.store("any_discards", false); // Initialise swap and step condition variables @@ -464,7 +464,7 @@ public RuntimeConfigAddition expandWithRuntimeAddition(AFunctionDeclarati dynamicScope.enterIf(stepPredicate); } - Map.Entry, Fmi2Builder.DoubleVariable> discard = + Map.Entry, FmiBuilder.DoubleVariable> discard = instance.step(communicationTime, currentStepSize); communicationPoint.setValue(new DoubleExpressionValue(discard.getValue().getExp())); @@ -534,7 +534,7 @@ public RuntimeConfigAddition expandWithRuntimeAddition(AFunctionDeclarati // Rollback dynamicScope.enterIf(convergenceReached.toPredicate().not()).enterThen(); { - fmuStates.forEach(Fmi2Builder.StateVariable::set); + fmuStates.forEach(FmiBuilder.StateVariable::set); stabilisation_loop.decrement(); dynamicScope.leave(); } @@ -552,7 +552,7 @@ public RuntimeConfigAddition expandWithRuntimeAddition(AFunctionDeclarati IfMaBlScope discardScope = dynamicScope.enterIf(anyDiscards.toPredicate()); { // Rollback FMUs - fmuStates.forEach(Fmi2Builder.StateVariable::set); + fmuStates.forEach(FmiBuilder.StateVariable::set); // Set step-size to lowest currentStepSize.setValue(math.minRealFromArray(fmuCommunicationPoints).toMath().subtraction(currentCommunicationTime)); @@ -580,7 +580,7 @@ public RuntimeConfigAddition expandWithRuntimeAddition(AFunctionDeclarati IfMaBlScope reducedStepSizeScope = dynamicScope.enterIf(hasReducedStepSize.toPredicate()); { // Rollback FMUs - fmuStates.forEach(Fmi2Builder.StateVariable::set); + fmuStates.forEach(FmiBuilder.StateVariable::set); // Set step-size to suggested size currentStepSize.setValue(Objects.requireNonNull(variableStepInstance).getReducedStepSize()); diff --git a/plugins/sigver/src/main/java/org/intocps/maestro/plugin/Sigver.java b/plugins/sigver/src/main/java/org/intocps/maestro/plugin/Sigver.java index d6e5b955c..47d55bc82 100644 --- a/plugins/sigver/src/main/java/org/intocps/maestro/plugin/Sigver.java +++ b/plugins/sigver/src/main/java/org/intocps/maestro/plugin/Sigver.java @@ -13,7 +13,7 @@ import org.intocps.maestro.core.messages.IErrorReporter; import org.intocps.maestro.fmi.Fmi2ModelDescription; import org.intocps.maestro.framework.core.ISimulationEnvironment; -import org.intocps.maestro.framework.fmi2.api.Fmi2Builder; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.*; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.DynamicActiveBuilderScope; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.ScopeFmi2Api; @@ -65,7 +65,7 @@ public Set getDeclaredUnfoldFunctions() { @Override public RuntimeConfigAddition expandWithRuntimeAddition(AFunctionDeclaration declaredFunction, - Fmi2Builder providedBuilder, List> formalArguments, + FmiBuilder providedBuilder, List> formalArguments, IPluginConfiguration config, ISimulationEnvironment envIn, IErrorReporter errorReporter) throws ExpandException { //TODO: A Scenario and a multi-model does not agree on the format of identifying a FMU/instance. @@ -121,7 +121,7 @@ public RuntimeConfigAddition expandWithRuntimeAddition(AFunctionDeclarati // Get FMU instances // use LinkedHashMap to preserve added order Map fmuInstances = - ((List) ((Fmi2Builder.ArrayVariable) formalArguments.get(0)).items()).stream().collect( + ((List) ((FmiBuilder.ArrayVariable) formalArguments.get(0)).items()).stream().collect( Collectors.toMap(ComponentVariableFmi2Api::getEnvironmentName, Function.identity(), (u, v) -> u, LinkedHashMap::new)); // Rename FMU instance-name keys to master model format: _ @@ -236,7 +236,7 @@ private void setSEA(Map fmuInstances, Map PortToExpressionValue = + Map PortToExpressionValue = portNameToValueMap.entrySet().stream().filter(e -> { PortFmi2Api port = fmuInstance.getPort(e.getKey()); boolean isTunableParameter = port.scalarVariable.variability.equals(Fmi2ModelDescription.Variability.Tunable) && @@ -291,12 +291,12 @@ private List>> mapInitializationA return sharedPortVars; } - private Map, Fmi2Builder.DoubleVariable>> mapCoSimStepInstructionsToMaBL( + private Map, FmiBuilder.DoubleVariable>> mapCoSimStepInstructionsToMaBL( Map> coSimStepInstructionsMap, Map fmuInstances, - DoubleVariableFmi2Api currentCommunicationPoint, Set> fmuStates, List connections, + DoubleVariableFmi2Api currentCommunicationPoint, Set> fmuStates, List connections, List>> sharedPortVars, DoubleVariableFmi2Api currentStepSize) { - Map, Fmi2Builder.DoubleVariable>> fmuInstanceWithStepVar = + Map, FmiBuilder.DoubleVariable>> fmuInstanceWithStepVar = new HashMap<>(); List>> tentativePortVars = new ArrayList<>(); @@ -318,7 +318,7 @@ private Map, .ifPresentOrElse(item -> { }, () -> sharedPortVars.add(Map.entry(key, value)))); } else if (instruction instanceof Step) { - Map.Entry, Fmi2Builder.DoubleVariable>> instanceWithStep = + Map.Entry, FmiBuilder.DoubleVariable>> instanceWithStep = mapStepInstruction((Step) instruction, fmuInstances, fmuInstanceWithStepVar, currentCommunicationPoint, currentStepSize); fmuInstanceWithStepVar.put(instanceWithStep.getKey(), instanceWithStep.getValue()); } else if (instruction instanceof SaveState) { @@ -331,7 +331,7 @@ private Map, } else if (instruction instanceof RestoreState) { fmuStates.stream().filter(state -> state.getName() .contains(((RestoreState) instruction).fmu().toLowerCase(Locale.ROOT).split(MASTER_MODEL_FMU_INSTANCE_DELIMITER)[1])) - .findAny().ifPresent(Fmi2Builder.StateVariable::set); + .findAny().ifPresent(FmiBuilder.StateVariable::set); } else if (instruction instanceof AlgebraicLoop) { mapAlgebraicLoopCoSimStepInstruction(algorithmIdentifier, (AlgebraicLoop) instruction, fmuInstances, currentCommunicationPoint, fmuStates, connections, sharedPortVars, currentStepSize).forEach(fmuInstanceWithStepVar::putIfAbsent); @@ -367,7 +367,7 @@ private Map, private void mapStepLoopCoSimStepInstruction(String parentAlgorithmIdentifier, StepLoop instruction, Map fmuInstances, DoubleVariableFmi2Api currentCommunicationPoint, - Set> fmuStates, List connections, + Set> fmuStates, List connections, List>> portsWithGet, DoubleVariableFmi2Api currentStepSize) { ArrayVariableFmi2Api fmuCommunicationPoints = @@ -377,12 +377,12 @@ private void mapStepLoopCoSimStepInstruction(String parentAlgorithmIdentifier, S ScopeFmi2Api stepAcceptedScope = dynamicScope.enterWhile(stepAcceptedPredicate.toPredicate().not()); // Map iterate instructions to MaBL - Map, Fmi2Builder.DoubleVariable>> fmuInstanceWithStepVar = + Map, FmiBuilder.DoubleVariable>> fmuInstanceWithStepVar = mapCoSimStepInstructionsToMaBL(Map.of(parentAlgorithmIdentifier, CollectionConverters.asJava(instruction.iterate())), fmuInstances, currentCommunicationPoint, fmuStates, connections, portsWithGet, currentStepSize); // Get step accepted boolean from each fmu instance of interest. - List> acceptedStepVariables = new ArrayList<>(); + List> acceptedStepVariables = new ArrayList<>(); List acceptFmuRefs = CollectionConverters.asJava(instruction.untilStepAccept()); fmuInstanceWithStepVar.forEach((fmuInstance, stepWithAccept) -> { if (acceptFmuRefs.stream().anyMatch(name -> name.toLowerCase(Locale.ROOT).contains(fmuInstance.getName()))) { @@ -407,7 +407,7 @@ private void mapStepLoopCoSimStepInstruction(String parentAlgorithmIdentifier, S currentCommunicationPoint, fmuStates, connections, portsWithGet, currentStepSize); // Set the step size to the lowest accepted step-size - List> stepSizes = + List> stepSizes = fmuInstanceWithStepVar.values().stream().map(Map.Entry::getValue).collect(Collectors.toList()); for (int i = 0; i < stepSizes.size(); i++) { fmuCommunicationPoints.items().get(i).setValue(new DoubleExpressionValue(stepSizes.get(i).getExp())); @@ -421,12 +421,12 @@ private void mapStepLoopCoSimStepInstruction(String parentAlgorithmIdentifier, S stepAcceptedScope.leave(); } - private Map, Fmi2Builder.DoubleVariable>> mapAlgebraicLoopCoSimStepInstruction( + private Map, FmiBuilder.DoubleVariable>> mapAlgebraicLoopCoSimStepInstruction( String parentAlgorithmIdentifier, AlgebraicLoop algebraicLoopInstruction, Map fmuInstances, - DoubleVariableFmi2Api currentCommunicationPoint, Set> fmuStates, List connections, + DoubleVariableFmi2Api currentCommunicationPoint, Set> fmuStates, List connections, List>> portMapVars, DoubleVariableFmi2Api currentStepSize) { - Map, Fmi2Builder.DoubleVariable>> fmuWithStep = new HashMap<>(); + Map, FmiBuilder.DoubleVariable>> fmuWithStep = new HashMap<>(); List>> tentativePortMapVars = new ArrayList<>(); List convergedPortRefs = CollectionConverters.asJava(algebraicLoopInstruction.untilConverged()); List convergedVariables = new ArrayList<>(); @@ -543,13 +543,13 @@ private BooleanVariableFmi2Api createCheckConvergenceSection(Map.Entry, Fmi2Builder.DoubleVariable>> mapStepInstruction( + private Map.Entry, FmiBuilder.DoubleVariable>> mapStepInstruction( Step instruction, Map fmuInstances, - Map, Fmi2Builder.DoubleVariable>> fmuWithStep, + Map, FmiBuilder.DoubleVariable>> fmuWithStep, DoubleVariableFmi2Api currentCommunicationPoint, DoubleVariableFmi2Api defaultCommunicationStepSize) { ComponentVariableFmi2Api instance = fmuInstances.get(instruction.fmu()); - Map.Entry, Fmi2Builder.DoubleVariable> step; + Map.Entry, FmiBuilder.DoubleVariable> step; // Step with the proper step size according to the instruction if (instruction.by() instanceof AbsoluteStepSize) { From b0a39fc54d5a806ca8cc781fcd72a1387104c954 Mon Sep 17 00:00:00 2001 From: Nestor Date: Thu, 5 Oct 2023 11:30:48 +0200 Subject: [PATCH 26/54] getter/setters work in progress, but for merge Signed-off-by: Nestor --- .../framework/fmi2/api/Fmi2Builder.java | 13 +-- .../values/PortValueExpresssionMapImpl.java | 2 +- .../api/mabl/values/PortValueMapImpl.java | 2 +- .../variables/InstanceVariableFmi3Api.java | 91 +++++++++---------- .../mabl/variables/PortVariableMapImpl.java | 2 +- .../org/intocps/maestro/BuilderFmi3Test.java | 18 ++-- 6 files changed, 67 insertions(+), 61 deletions(-) diff --git a/frameworks/builder/src/main/java/org/intocps/maestro/framework/fmi2/api/Fmi2Builder.java b/frameworks/builder/src/main/java/org/intocps/maestro/framework/fmi2/api/Fmi2Builder.java index fb3270d91..2cc56ecc9 100644 --- a/frameworks/builder/src/main/java/org/intocps/maestro/framework/fmi2/api/Fmi2Builder.java +++ b/frameworks/builder/src/main/java/org/intocps/maestro/framework/fmi2/api/Fmi2Builder.java @@ -768,28 +768,29 @@ interface Fmi3InstanceVariable extends Variable> { void setupExperiment(double startTime, Double endTime, Double tolerance); - int enterInitializationMode(boolean toleranceDefined, double tolerance, double startTime, boolean stopTimeDefined, double stopTime); + void enterInitializationMode(boolean toleranceDefined, double tolerance, double startTime, boolean stopTimeDefined, double stopTime); - int exitInitializationMode(); + void exitInitializationMode(); void setupExperiment(Scope scope, DoubleVariable startTime, DoubleVariable endTime, BoolVariable endTimeDefined, Double tolerance); void setupExperiment(Scope scope, double startTime, Double endTime, Double tolerance); - int enterInitializationMode(Scope scope,boolean toleranceDefined, double tolerance, double startTime, boolean stopTimeDefined, + void enterInitializationMode(Scope scope,boolean toleranceDefined, double tolerance, double startTime, boolean stopTimeDefined, double stopTime); - int exitInitializationMode(Scope scope); + void exitInitializationMode(Scope scope); - int terminate(Scope scope); + void terminate(Scope scope); - int terminate(); + void terminate(); void freeInstance(); void freeInstance(Scope scope); + /** * @param scope * @param currentCommunicationPoint diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/PortValueExpresssionMapImpl.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/PortValueExpresssionMapImpl.java index 24738ec65..18a3a5123 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/PortValueExpresssionMapImpl.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/PortValueExpresssionMapImpl.java @@ -5,7 +5,7 @@ import java.util.HashMap; import java.util.Map; -public class PortValueExpresssionMapImpl extends HashMap implements Fmi2Builder.Fmi2ComponentVariable.PortExpressionValueMap { +public class PortValueExpresssionMapImpl extends HashMap implements Fmi2Builder.Fmi2ComponentVariable.PortExpressionValueMap, Fmi2Builder.Fmi3InstanceVariable.PortExpressionValueMap { public PortValueExpresssionMapImpl(int initialCapacity, float loadFactor) { super(initialCapacity, loadFactor); } diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/PortValueMapImpl.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/PortValueMapImpl.java index 03852dbda..9f6c80c92 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/PortValueMapImpl.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/PortValueMapImpl.java @@ -5,7 +5,7 @@ import java.util.HashMap; import java.util.Map; -public class PortValueMapImpl extends HashMap> implements Fmi2Builder.Fmi2ComponentVariable.PortValueMap { +public class PortValueMapImpl extends HashMap> implements Fmi2Builder.Fmi2ComponentVariable.PortValueMap, Fmi2Builder.Fmi3InstanceVariable.PortValueMap { public PortValueMapImpl(int initialCapacity, float loadFactor) { super(initialCapacity, loadFactor); } diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/InstanceVariableFmi3Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/InstanceVariableFmi3Api.java index b0e16ee32..b93bf05f5 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/InstanceVariableFmi3Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/InstanceVariableFmi3Api.java @@ -7,7 +7,6 @@ import org.intocps.maestro.ast.analysis.AnalysisException; import org.intocps.maestro.ast.analysis.DepthFirstAnalysisAdaptor; import org.intocps.maestro.ast.node.*; -import org.intocps.maestro.fmi.Fmi2ModelDescription; import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3Causality; import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3TypeEnum; @@ -22,7 +21,6 @@ import org.slf4j.LoggerFactory; import javax.xml.xpath.XPathExpressionException; -import java.lang.reflect.InvocationTargetException; import java.util.*; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Function; @@ -39,12 +37,6 @@ @SuppressWarnings("rawtypes") public class InstanceVariableFmi3Api extends VariableFmi2Api> implements Fmi2Builder.Fmi3InstanceVariable { final static Logger logger = LoggerFactory.getLogger(InstanceVariableFmi3Api.class); - private final static int FMI_OK = 0; - private final static int FMI_WARNING = 1; - private final static int FMI_DISCARD = 2; - private final static int FMI_ERROR = 3; - private final static int FMI_FATAL = 4; - private final static int FMI_PENDING = 5; private final static int FMI_STATUS_LAST_SUCCESSFUL = 2; private static final String LOGLEVELS_POSTFIX = "_log_levels"; private final static String CATEGORY_STATUS = "category_status"; @@ -95,7 +87,6 @@ public InstanceVariableFmi3Api(PStm declaration, FmuVariableFmi3Api parent, Stri this.environmentName = environmentName; } - // TODO fmi3 model description. public Fmi3ModelDescription getModelDescription() { return modelDescriptionContext.getModelDescription(); } @@ -292,13 +283,13 @@ private void setupExperiment(Fmi2Builder.Scope scope, PExp startTime, PExp } @Override - public int enterInitializationMode(boolean toleranceDefined, double tolerance, double startTime, boolean stopTimeDefined, double stopTime) { - return this.enterInitializationMode(builder.getDynamicScope(), toleranceDefined, tolerance, startTime, stopTimeDefined, stopTime); + public void enterInitializationMode(boolean toleranceDefined, double tolerance, double startTime, boolean stopTimeDefined, double stopTime) { + this.enterInitializationMode(builder.getDynamicScope(), toleranceDefined, tolerance, startTime, stopTimeDefined, stopTime); } @Override - public int exitInitializationMode() { - return this.exitInitializationMode(builder.getDynamicScope()); + public void exitInitializationMode() { + this.exitInitializationMode(builder.getDynamicScope()); } @Override @@ -315,29 +306,25 @@ public void setupExperiment(Fmi2Builder.Scope scope, double startTime, Dou // TODO: probably should return other things than ok also @Override - public int enterInitializationMode(Fmi2Builder.Scope scope, boolean toleranceDefined, double tolerance, double startTime, + public void enterInitializationMode(Fmi2Builder.Scope scope, boolean toleranceDefined, double tolerance, double startTime, boolean stopTimeDefined, double stopTime) { PStm stm = stateTransitionFunction(FmiFunctionType.ENTERINITIALIZATIONMODE, toleranceDefined, tolerance, startTime, stopTimeDefined, stopTime ); - scope.add(stm); if (builder.getSettings().fmiErrorHandlingEnabled) { FmiStatusErrorHandlingBuilder.generate(builder, "enterInitializationMode", this, (IMablScope) scope, MablApiBuilder.Fmi3Status.FMI_ERROR, MablApiBuilder.Fmi3Status.FMI_FATAL); } - return Fmi3Status.OK.value; } - // TODO: Probably return other things than just ok. @Override - public int exitInitializationMode(Fmi2Builder.Scope scope) { + public void exitInitializationMode(Fmi2Builder.Scope scope) { PStm stm = stateTransitionFunction(FmiFunctionType.EXITINITIALIZATIONMODE); scope.add(stm); if (builder.getSettings().fmiErrorHandlingEnabled) { FmiStatusErrorHandlingBuilder.generate(builder, "exitInitializationMode", this, (IMablScope) scope, MablApiBuilder.Fmi3Status.FMI_ERROR, MablApiBuilder.Fmi3Status.FMI_FATAL); } - return Fmi3Status.OK.value; } @Override @@ -541,6 +528,27 @@ public Map> get(Fmi2Builder.Scope scop PType type; switch (e.getKey()) { + case Float64Type: + type = new ARealNumericPrimitiveType(); + break; + case Float32Type: + type = new AFloatNumericPrimitiveType(); + break; + case Int8Type: + type = new AByteNumericPrimitiveType(); + break; + case Int16Type: + type = new AShortNumericPrimitiveType(); + break; + case Int32Type: + type = new AIntNumericPrimitiveType(); + break; + case Int64Type: + type = new ALongNumericPrimitiveType(); + break; + + // TODO add the rest + // case Boolean: // type = new ABooleanPrimitiveType(); // break; @@ -555,10 +563,8 @@ public Map> get(Fmi2Builder.Scope scop // break; // case Enumeration: // throw new RuntimeException("Cannot assign enumeration port type."); -// default: -// throw new RuntimeException("Cannot match port types."); default: - type = new AIntNumericPrimitiveType(); // TODO For now for testing + throw new RuntimeException("Cannot match port types."); } ArrayVariableFmi2Api valBuf = getIOBuffer(type); @@ -774,14 +780,15 @@ public VariableFmi2Api getSingle(String name) { + + + public void set(Fmi2Builder.Port p, Fmi2Builder.ExpressionValue v) { - ; -// this.set(new PortValueExpresssionMapImpl(Map.of(p, v))); + this.set(new PortValueExpresssionMapImpl(Map.of(p, v))); } public void set(Fmi2Builder.Scope scope, Fmi2Builder.Port p, Fmi2Builder.ExpressionValue v) { - ; - // this.set(scope, new PortValueMapImpl(Map.of(p, v))); + this.set(scope, new PortValueMapImpl(Map.of(p, v))); } public void set(PortExpressionValueMap value) { @@ -803,8 +810,6 @@ public void set(Fmi2Builder.Scope scope, PortExpressionValueMap value) { @Override public void set(Fmi2Builder.Scope scope, PortValueMap value) { - - if (value == null || value.isEmpty()) { return; } @@ -814,6 +819,7 @@ public void set(Fmi2Builder.Scope scope, PortValueMap value) { set(scope, selectedPorts, port -> { Object val = (value.get(port)).get(); + // TODO: Add the rest if (val instanceof Double) { return Map.entry(newARealLiteralExp((Double) val), newRealType()); } @@ -849,7 +855,6 @@ public void set(Fmi2Builder.Scope scope, PortVariableMap valu } public void set(Fmi2Builder.Scope scope, List selectedPorts, Function> portToValue) { - Set selectedPortsAsStrings = selectedPorts.stream() .map(p -> p.getName() + "-" + p.aMablFmi3InstanceAPI.getName() + "-" + p.aMablFmi3InstanceAPI.getOwner().getName()) .collect(toSet()); @@ -905,7 +910,7 @@ public void set(Fmi2Builder.Scope scope, List selectedPorts, // } }); } -// + // /** // * @param ports The ports for which derivative should be set from SHARED derivative ports // * @param scope The builder scope @@ -931,7 +936,7 @@ public void set(Fmi2Builder.Scope scope, List selectedPorts, // } // // return null; -// } catch (XPathExpressionException | IllegalAccessException | InvocationTargetException e) { +// } catch (XPathExpressionException | IllegalAccessException e) { // TODO: InvocationTargetException??? // throw new RuntimeException("Exception occurred when accessing modeldescription: ", e); // } // }).filter(Objects::nonNull).collect(LinkedHashMap::new, (map, item) -> map.put(item.getKey(), item.getValue()), // Accumulator @@ -1007,22 +1012,19 @@ public void set(PortValueMap value) { @Override public void set(Fmi2Builder.Port port, Fmi2Builder.Variable value) { - ; - // this.set(new PortVariableMapImpl(Map.of(port, value))); + this.set(new PortVariableMapImpl(Map.of(port, value))); } @Override public void set(Fmi2Builder.Scope scope, Fmi2Builder.Port port, Fmi2Builder.Variable value) { - ; -// this.set(scope, new PortVariableMapImpl(Map.of(port, value))); + this.set(scope, new PortVariableMapImpl(Map.of(port, value))); } @Override public void set(Fmi2Builder.Port port, Fmi2Builder.Value value) { - ; - // PortValueMap map = new PortValueMapImpl(); - // map.put(port, value); - // set(map); + PortValueMap map = new PortValueMapImpl(); + map.put(port, value); + set(map); } @@ -1107,28 +1109,25 @@ public void setString(Map> } @Override - public int terminate() { - return this.terminate(builder.getDynamicScope()); + public void terminate() { + this.terminate(builder.getDynamicScope()); } - // TODO: Return other values but ok? @Override - public int terminate(Fmi2Builder.Scope scope) { + public void terminate(Fmi2Builder.Scope scope) { PStm stm = stateTransitionFunction(FmiFunctionType.TERMINATE); scope.add(stm); if (builder.getSettings().fmiErrorHandlingEnabled) { FmiStatusErrorHandlingBuilder.generate(builder, "terminate", this, (IMablScope) scope, MablApiBuilder.Fmi3Status.FMI_ERROR, MablApiBuilder.Fmi3Status.FMI_FATAL); } - return Fmi3Status.OK.value; } + // TODO: these are work in progress public void freeInstance() { this.freeInstance(builder.getDynamicScope()); } - public void freeInstance(Fmi2Builder.Scope scope) { - // TODO: add fault checks??? scope.add(MableAstFactory.newExpressionStm(call(getReferenceExp().clone(), "freeInstance"))); } diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/PortVariableMapImpl.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/PortVariableMapImpl.java index 27c0cca9a..ca4643378 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/PortVariableMapImpl.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/PortVariableMapImpl.java @@ -6,7 +6,7 @@ import java.util.HashMap; import java.util.Map; -public class PortVariableMapImpl extends HashMap> implements Fmi2Builder.Fmi2ComponentVariable.PortVariableMap { +public class PortVariableMapImpl extends HashMap> implements Fmi2Builder.Fmi2ComponentVariable.PortVariableMap, Fmi2Builder.Fmi3InstanceVariable.PortVariableMap { public PortVariableMapImpl(int initialCapacity, float loadFactor) { super(initialCapacity, loadFactor); } diff --git a/maestro/src/test/java/org/intocps/maestro/BuilderFmi3Test.java b/maestro/src/test/java/org/intocps/maestro/BuilderFmi3Test.java index 0204077dc..7d46ff097 100644 --- a/maestro/src/test/java/org/intocps/maestro/BuilderFmi3Test.java +++ b/maestro/src/test/java/org/intocps/maestro/BuilderFmi3Test.java @@ -31,6 +31,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; +import java.lang.reflect.Array; import java.net.URI; import java.nio.charset.StandardCharsets; import java.util.Collections; @@ -78,7 +79,7 @@ public void wt() throws Exception { URI ballUri = new File("target/Fmi3ModuleReferenceFmusTest/cache/BouncingBall.fmu").getAbsoluteFile().toURI(); Fmu3 ball = new Fmu3(new File(ballUri)); - ArrayVariableFmi2Api varArray = builder.getDynamicScope().store("varArray", new Long[] {1L}); + ArrayVariableFmi2Api requiredIntermediateVariables = builder.getDynamicScope().store("requiredIntermediateVariables", new Long[] {1L}); Fmi3ModelDescription md3Ball = new Fmi3ModelDescription(ball.getModelDescription()); @@ -89,15 +90,20 @@ public void wt() throws Exception { boolean eventModeUsed = true; boolean earlyReturnAllowed = true; InstanceVariableFmi3Api ballInstance = ballFmu.instantiate("ballInstance", visible, loggingOn, eventModeUsed, earlyReturnAllowed, - varArray); + requiredIntermediateVariables); - int res = ballInstance.enterInitializationMode(false, 0.0, 0.0, true,10.0); - res = ballInstance.exitInitializationMode(); - res = ballInstance.terminate(); - ballInstance.freeInstance(); + ballInstance.enterInitializationMode(false, 0.0, 0.0, true,10.0); + ballInstance.exitInitializationMode(); +// ArrayVariableFmi2Api svs = builder.getDynamicScope().store("svs", new Long[] {5L, 6L}); +// ArrayVariableFmi2Api values_r = builder.getDynamicScope().store("values_r", new Double[] {-9.81, 0.7}); + ballInstance.terminate(); + + +// ballInstance.freeInstance(); + From de6d77277595b5c9b3d0c59d26bed06974081385 Mon Sep 17 00:00:00 2001 From: Kenneth Lausdahl Date: Thu, 5 Oct 2023 22:29:02 +0200 Subject: [PATCH 27/54] cleanup --- .../framework/fmi2/api/FmiBuilder.java | 4 + .../variables/InstanceVariableFmi3Api.java | 218 ++++++++---------- .../fmi2/api/mabl/variables/VarWrap.java | 22 ++ .../src/main/kotlin/Initializer.kt | 11 +- 4 files changed, 132 insertions(+), 123 deletions(-) create mode 100644 frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/VarWrap.java diff --git a/frameworks/builder/src/main/java/org/intocps/maestro/framework/fmi2/api/FmiBuilder.java b/frameworks/builder/src/main/java/org/intocps/maestro/framework/fmi2/api/FmiBuilder.java index 563015fcd..239a660cf 100644 --- a/frameworks/builder/src/main/java/org/intocps/maestro/framework/fmi2/api/FmiBuilder.java +++ b/frameworks/builder/src/main/java/org/intocps/maestro/framework/fmi2/api/FmiBuilder.java @@ -771,6 +771,10 @@ interface Fmi3InstanceVariable extends FmiSimulationInstance { void enterInitializationMode(boolean toleranceDefined, double tolerance, double startTime, boolean stopTimeDefined, double stopTime); + void enterInitializationMode(Scope scope,FmiBuilder.BoolVariable toleranceDefined, FmiBuilder.DoubleVariable tolerance, FmiBuilder.DoubleVariable startTime, + FmiBuilder.BoolVariable stopTimeDefined, FmiBuilder.DoubleVariable stopTime); + void enterInitializationMode(FmiBuilder.BoolVariable toleranceDefined, FmiBuilder.DoubleVariable tolerance, FmiBuilder.DoubleVariable startTime, + FmiBuilder.BoolVariable stopTimeDefined, FmiBuilder.DoubleVariable stopTime); void exitInitializationMode(); void setupExperiment(Scope scope, DoubleVariable startTime, DoubleVariable endTime, BoolVariable endTimeDefined, diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/InstanceVariableFmi3Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/InstanceVariableFmi3Api.java index dd5dbf5af..f040c2b06 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/InstanceVariableFmi3Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/InstanceVariableFmi3Api.java @@ -151,6 +151,7 @@ private ArrayVariableFmi2Api getIOBuffer(PType type) { return getBuffer(this.ioBuffer, type, "IO", modelDescriptionContext.valRefToSv.size(), getDeclaredScope()); } + @SuppressWarnings("unchecked") private ArrayVariableFmi2Api getSharedDerBuffer() { if (this.derSharedBuffer == null) { try { @@ -167,6 +168,7 @@ private ArrayVariableFmi2Api getSharedBuffer(PType type) { return this.getBuffer(this.sharedBuffer, type, "Share", 0, getDeclaredScope()); } + @SuppressWarnings("unchecked") private ArrayVariableFmi2Api createMDArrayRecursively(List arraySizes, PStm declaringStm, PStateDesignatorBase stateDesignator, PExpBase indexExp) { @@ -224,6 +226,8 @@ private ArrayVariableFmi2Api createBuffer(PType type, String prefix, int @Override public void setDebugLogging(List categories, boolean enableLogging) { + final String method = "setDebugLogging"; + AArrayInitializer loglevelsArrayInitializer = null; String arrayName = name + LOGLEVELS_POSTFIX; IMablScope scope = builder.getDynamicScope().getActiveScope(); @@ -238,16 +242,13 @@ public void setDebugLogging(List categories, boolean enableLogging) { LexIdentifier statusIdentifier = newAIdentifier(getEnvironmentName() + "_" + CATEGORY_STATUS); ALocalVariableStm callStm = newALocalVariableStm(newAVariableDeclaration(statusIdentifier, newAIntNumericPrimitiveType(), newAExpInitializer( - newACallExp(newAIdentifierExp(name), newAIdentifier("setDebugLogging"), + newACallExp(newAIdentifierExp(name), newAIdentifier(method), Arrays.asList(newABoolLiteralExp(enableLogging), MableAstFactory.newAIntLiteralExp(categories.size()), MableAstFactory.newAIdentifierExp(arrayName)))))); scope.add(arrayContent, callStm); - if (builder.getSettings().fmiErrorHandlingEnabled) { - FmiStatusErrorHandlingBuilder.generate(builder, "setDebugLogging", this, (IMablScope) scope, MablApiBuilder.Fmi3Status.FMI_ERROR, - MablApiBuilder.Fmi3Status.FMI_FATAL); - } + handleError(scope, method); } @Override @@ -269,15 +270,14 @@ private void setupExperiment(PExp startTime, PExp endTime, PExp endTimeDefined, } private void setupExperiment(FmiBuilder.Scope scope, PExp startTime, PExp endTime, PExp endTimeDefined, Double tolerance) { + final String method = "setupExperiment"; + AAssigmentStm stm = newAAssignmentStm(((IMablScope) scope).getFmiStatusVariable().getDesignator().clone(), - call(this.getReferenceExp().clone(), createFunctionName(FmiFunctionType.SETUPEXPERIMENT), new ArrayList<>( + call(this.getReferenceExp().clone(), method, new ArrayList<>( Arrays.asList(newABoolLiteralExp(tolerance != null), newARealLiteralExp(tolerance != null ? tolerance : 0d), startTime.clone(), endTimeDefined, endTime != null ? endTime.clone() : newARealLiteralExp(0d))))); scope.add(stm); - if (builder.getSettings().fmiErrorHandlingEnabled) { - FmiStatusErrorHandlingBuilder.generate(builder, "setupExperiment", this, (IMablScope) scope, MablApiBuilder.Fmi3Status.FMI_ERROR, - MablApiBuilder.Fmi3Status.FMI_FATAL); - } + handleError(scope, method); } @Override @@ -286,6 +286,46 @@ public void enterInitializationMode(boolean toleranceDefined, double tolerance, } + @Override + public void enterInitializationMode(FmiBuilder.Scope scope, boolean toleranceDefined, double tolerance, double startTime, + boolean stopTimeDefined, double stopTime) { + this.enterInitializationMode(builder.getDynamicScope(), VarWrap.wrap(toleranceDefined), VarWrap.wrap(tolerance), VarWrap.wrap(startTime), + VarWrap.wrap(stopTimeDefined), VarWrap.wrap(stopTime)); + + } + + @Override + public void enterInitializationMode(FmiBuilder.BoolVariable toleranceDefined, FmiBuilder.DoubleVariable tolerance, + FmiBuilder.DoubleVariable startTime, FmiBuilder.BoolVariable stopTimeDefined, FmiBuilder.DoubleVariable stopTime) { + enterInitializationMode(builder.getDynamicScope(), toleranceDefined, tolerance, startTime, stopTimeDefined, stopTime); + } + + @Override + public void enterInitializationMode(FmiBuilder.Scope scope, FmiBuilder.BoolVariable toleranceDefined, + FmiBuilder.DoubleVariable tolerance, FmiBuilder.DoubleVariable startTime, FmiBuilder.BoolVariable stopTimeDefined, + FmiBuilder.DoubleVariable stopTime) { + + final String method = "enterInitializationMode"; + + AAssigmentStm stm = newAAssignmentStm(((IMablScope) scope).getFmiStatusVariable().getDesignator().clone(), + call(this.getReferenceExp().clone(), method, toleranceDefined.getExp().clone(), tolerance.getExp().clone(), + startTime.getExp().clone(), stopTimeDefined.getExp().clone(), stopTime.getExp().clone())); + + scope.add(stm); + + handleError(scope, method); + } + + private void handleError(FmiBuilder.Scope scope, String method) { + handleError(scope, method, MablApiBuilder.Fmi3Status.FMI_ERROR, MablApiBuilder.Fmi3Status.FMI_FATAL); + } + + private void handleError(FmiBuilder.Scope scope, String method, MablApiBuilder.Fmi3Status... statusesToFail) { + if (builder.getSettings().fmiErrorHandlingEnabled) { + FmiStatusErrorHandlingBuilder.generate(builder, method, this, (IMablScope) scope, statusesToFail); + } + } + @Override public void exitInitializationMode() { this.exitInitializationMode(builder.getDynamicScope()); @@ -303,28 +343,18 @@ public void setupExperiment(FmiBuilder.Scope scope, double startTime, Doub this.setupExperiment(scope, newARealLiteralExp(startTime), newARealLiteralExp(endTime), newABoolLiteralExp(true), tolerance); } - // TODO: probably should return other things than ok also - @Override - public void enterInitializationMode(FmiBuilder.Scope scope, boolean toleranceDefined, double tolerance, double startTime, - boolean stopTimeDefined, double stopTime) { - PStm stm = - stateTransitionFunction(FmiFunctionType.ENTERINITIALIZATIONMODE, toleranceDefined, tolerance, startTime, stopTimeDefined, stopTime); - - scope.add(stm); - if (builder.getSettings().fmiErrorHandlingEnabled) { - FmiStatusErrorHandlingBuilder.generate(builder, "enterInitializationMode", this, (IMablScope) scope, MablApiBuilder.Fmi3Status.FMI_ERROR, - MablApiBuilder.Fmi3Status.FMI_FATAL); - } - } @Override public void exitInitializationMode(FmiBuilder.Scope scope) { - PStm stm = stateTransitionFunction(FmiFunctionType.EXITINITIALIZATIONMODE); + + final String method = "exitInitializationMode"; + + AAssigmentStm stm = + newAAssignmentStm(((IMablScope) scope).getFmiStatusVariable().getDesignator().clone(), call(this.getReferenceExp().clone(), method)); + scope.add(stm); - if (builder.getSettings().fmiErrorHandlingEnabled) { - FmiStatusErrorHandlingBuilder.generate(builder, "exitInitializationMode", this, (IMablScope) scope, MablApiBuilder.Fmi3Status.FMI_ERROR, - MablApiBuilder.Fmi3Status.FMI_FATAL); - } + + handleError(scope, method); } @Override @@ -384,44 +414,6 @@ private Map.Entry, FmiBuilder.DoubleVariable return Map.entry(getCurrentTimeFullStepVar(), getCurrentTimeVar()); } - private PStm stateTransitionFunction(FmiFunctionType type, boolean toleranceDefined, double tolerance, double startTime, boolean stopTimeDefined, - double stopTime) { - switch (type) { - case ENTERINITIALIZATIONMODE: - AAssigmentStm stm = newAAssignmentStm(((IMablScope) this.dynamicScope).getFmiStatusVariable().getDesignator().clone(), - call(this.getReferenceExp().clone(), createFunctionName(type), newABoolLiteralExp(toleranceDefined), - newARealLiteralExp(tolerance), newARealLiteralExp(startTime), newABoolLiteralExp(stopTimeDefined), - newARealLiteralExp(stopTime))); - return stm; - case EXITINITIALIZATIONMODE: - break; - case TERMINATE: - break; - default: - throw new RuntimeException("Attempting to call state transition function with non-state transition function type: " + type); - } - - - AAssigmentStm stm = newAAssignmentStm(((IMablScope) this.dynamicScope).getFmiStatusVariable().getDesignator().clone(), - call(this.getReferenceExp().clone(), createFunctionName(type))); - return stm; - } - - - private PStm stateTransitionFunction(FmiFunctionType type) { - switch (type) { - case EXITINITIALIZATIONMODE: - break; - case TERMINATE: - break; - default: - throw new RuntimeException("Attempting to call state transition function with non-state transition function type: " + type); - } - AAssigmentStm stm = newAAssignmentStm(((IMablScope) this.dynamicScope).getFmiStatusVariable().getDesignator().clone(), - call(this.getReferenceExp().clone(), createFunctionName(type))); - return stm; - } - @Override public List getPorts() { return ports; @@ -441,15 +433,16 @@ public List getPorts(int... valueReferences) { @Override public PortFmi3Api getPort(String name) { - return (PortFmi3Api) this.getPorts(name).get(0); + return this.getPorts(name).get(0); } @Override public PortFmi3Api getPort(int valueReference) { - return (PortFmi3Api) this.getPorts(valueReference).get(0); + return this.getPorts(valueReference).get(0); } //TODO: Move tentative buffer and global share buffer logic to its own module so that it is not coupled with the component logic? + @SuppressWarnings("unchecked") public Map> getTentative(IMablScope scope, String... names) { // Get filtered port values FmiBuilder.Port[] filteredPorts = this.ports.stream() @@ -498,6 +491,7 @@ public Map> get(FmiBuilder.Port Map> get(FmiBuilder.Scope scope, FmiBuilder.Port... ports) { @@ -575,10 +569,7 @@ public Map> get(FmiBuilder.Scope scope vrefBuf.getReferenceExp().clone(), newAUIntLiteralExp((long) e.getValue().size()), valBuf.getReferenceExp().clone())); scope.add(stm); - if (builder.getSettings().fmiErrorHandlingEnabled) { - FmiStatusErrorHandlingBuilder.generate(builder, createFunctionName(FmiFunctionType.GET, e.getValue().get(0)), this, - (IMablScope) scope, MablApiBuilder.Fmi3Status.FMI_ERROR, MablApiBuilder.Fmi3Status.FMI_FATAL); - } + handleError(scope, createFunctionName(FmiFunctionType.GET, e.getValue().get(0))); if (builder.getSettings().setGetDerivatives && type.equals(new ARealNumericPrimitiveType())) { derivativePortsToShare = getDerivatives(e.getValue(), scope); @@ -674,11 +665,13 @@ public Map>> getDerivatives(List Map> get() { return get(builder.getDynamicScope(), outputPorts.toArray(FmiBuilder.Port[]::new)); } + @SuppressWarnings("unchecked") @Override public Map> get(int... valueReferences) { List accept = Arrays.stream(valueReferences).boxed().collect(Collectors.toList()); @@ -686,6 +679,7 @@ public Map> get(int... valueReferences) { outputPorts.stream().filter(p -> accept.contains(p.getPortReferenceValue().intValue())).toArray(FmiBuilder.Port[]::new)); } + @SuppressWarnings("unchecked") @Override public Map> get(String... names) { List accept = Arrays.asList(names); @@ -720,41 +714,24 @@ public Map> getAndShare(String... names) { return values; } + @SuppressWarnings("unchecked") @Override public VariableFmi2Api getShared(String name) { return this.getPort(name).getSharedAsVariable(); } + @SuppressWarnings("unchecked") @Override public VariableFmi2Api getShared(FmiBuilder.Port port) { return ((PortFmi3Api) port).getSharedAsVariable(); } + @SuppressWarnings("unchecked") @Override public VariableFmi2Api getSingle(FmiBuilder.Port port) { return (VariableFmi2Api) this.get(port).entrySet().iterator().next().getValue(); } - private String createFunctionName(FmiFunctionType fun) { - switch (fun) { - case ENTERINITIALIZATIONMODE: - return "enterInitializationMode"; - case EXITINITIALIZATIONMODE: - return "exitInitializationMode"; - case SETUPEXPERIMENT: - return "setupExperiment"; - case GETREALOUTPUTDERIVATIVES: - return "getRealOutputDerivatives"; - case SETREALINPUTDERIVATIVES: - return "setRealInputDerivatives"; - case TERMINATE: - return "terminate"; - default: - throw new RuntimeException("Attempting to call function that is type dependant without specifying type: " + fun); - } - - } - private String createFunctionName(FmiFunctionType fun, PortFmi3Api p) { return createFunctionName(fun, p.scalarVariable.getVariable().getTypeIdentifier()); } @@ -775,16 +752,18 @@ private String createFunctionName(FmiFunctionType f, Fmi3TypeEnum type) { return functionName; } + @SuppressWarnings("unchecked") @Override public VariableFmi2Api getSingle(String name) { return this.get(name).entrySet().iterator().next().getValue(); } - + @SuppressWarnings("unchecked") public void set(FmiBuilder.Port p, FmiBuilder.ExpressionValue v) { this.set(new PortValueExpresssionMapImpl(Map.of(p, v))); } + @SuppressWarnings("unchecked") public void set(FmiBuilder.Scope scope, FmiBuilder.Port p, FmiBuilder.ExpressionValue v) { this.set(scope, new PortValueMapImpl(Map.of(p, v))); } @@ -861,7 +840,7 @@ public void set(FmiBuilder.Scope scope, List selectedPorts, F selectedPortsAsStrings.removeAll( ports.stream().map(p -> p.getName() + "-" + p.aMablFmi3InstanceAPI.getName() + "-" + p.aMablFmi3InstanceAPI.getOwner().getName()) .collect(toSet())); - if (selectedPortsAsStrings.size() > 0) { + if (!selectedPortsAsStrings.isEmpty()) { throw new RuntimeException("Unable to set port(s) that is not declared in the FMU: " + selectedPortsAsStrings.stream().map(name -> name.split("-")[0]).collect(Collectors.joining(", "))); } @@ -893,10 +872,7 @@ public void set(FmiBuilder.Scope scope, List selectedPorts, F newAUIntLiteralExp((long) value.size()), valBuf.getReferenceExp().clone())); scope.add(stm); - if (builder.getSettings().fmiErrorHandlingEnabled) { - FmiStatusErrorHandlingBuilder.generate(builder, createFunctionName(FmiFunctionType.SET, sortedPorts.get(0)), this, (IMablScope) scope, - MablApiBuilder.Fmi3Status.FMI_ERROR, MablApiBuilder.Fmi3Status.FMI_FATAL); - } + handleError(scope, createFunctionName(FmiFunctionType.SET, sortedPorts.get(0))); // TODO: IntermediateUpdateMode instead of CanInterpolateInputs? // TODO: commented out for no so it compiles @@ -988,21 +964,17 @@ public void set(FmiBuilder.Scope scope, List selectedPorts, F */ public void setDerivatives(ArrayVariableFmi2Api derValInBuf, ArrayVariableFmi2Api derOrderInBuf, ArrayVariableFmi2Api derRefInBuf, FmiBuilder.Scope scope) { + final String method = "setRealInputDerivatives"; int arraySize = derValInBuf.size(); // Create set derivatives statement which calls setRealOutputDerivatives with derRefInBuf, arraySize, derOrderInBuf and // derValInBuf. PStm ifStm = newAAssignmentStm(builder.getGlobalFmiStatus().getDesignator().clone(), - call(this.getReferenceExp().clone(), createFunctionName(FmiFunctionType.SETREALINPUTDERIVATIVES), - derRefInBuf.getReferenceExp().clone(), newAUIntLiteralExp((long) arraySize), derOrderInBuf.getReferenceExp().clone(), - derValInBuf.getReferenceExp().clone())); + call(this.getReferenceExp().clone(), method, derRefInBuf.getReferenceExp().clone(), newAUIntLiteralExp((long) arraySize), + derOrderInBuf.getReferenceExp().clone(), derValInBuf.getReferenceExp().clone())); scope.add(ifStm); - // If enabled handle potential errors from calling setRealInputDerivatives - if (builder.getSettings().fmiErrorHandlingEnabled) { - FmiStatusErrorHandlingBuilder.generate(builder, createFunctionName(FmiFunctionType.SETREALINPUTDERIVATIVES), this, (IMablScope) scope, - MablApiBuilder.Fmi3Status.FMI_ERROR, MablApiBuilder.Fmi3Status.FMI_FATAL); - } + handleError(scope, method); } @Override @@ -1010,18 +982,20 @@ public void set(PortValueMap val set(builder.getDynamicScope(), value); } - + @SuppressWarnings("unchecked") @Override public void set(FmiBuilder.Port port, FmiBuilder.Variable value) { this.set(new PortVariableMapImpl(Map.of(port, value))); } + @SuppressWarnings("unchecked") @Override public void set(FmiBuilder.Scope scope, FmiBuilder.Port port, FmiBuilder.Variable value) { this.set(scope, new PortVariableMapImpl(Map.of(port, value))); } + @SuppressWarnings("unchecked") @Override public void set(FmiBuilder.Port port, FmiBuilder.Value value) { PortValueMap map = new PortValueMapImpl(); @@ -1034,6 +1008,7 @@ public void set(PortVariableMap scope, FmiBuilder.Port... filterPorts) { @@ -1050,7 +1025,7 @@ public void setLinked(FmiBuilder.Scope scope, FmiBuilder.Port[]) null); } + @SuppressWarnings("unchecked") @Override public void setLinked(FmiBuilder.Port... filterPorts) { this.setLinked(dynamicScope, filterPorts); } + @SuppressWarnings("unchecked") @Override public void setLinked(String... filterNames) { List accept = Arrays.asList(filterNames); @@ -1092,6 +1069,7 @@ public void setLinked(String... filterNames) { } + @SuppressWarnings("unchecked") @Override public void setLinked(long... filterValueReferences) { List accept = Arrays.stream(filterValueReferences).boxed().collect(Collectors.toList()); @@ -1116,12 +1094,14 @@ public void terminate() { @Override public void terminate(FmiBuilder.Scope scope) { - PStm stm = stateTransitionFunction(FmiFunctionType.TERMINATE); + final String method = "terminate"; + + AAssigmentStm stm = + newAAssignmentStm(((IMablScope) scope).getFmiStatusVariable().getDesignator().clone(), call(this.getReferenceExp().clone(), method)); + scope.add(stm); - if (builder.getSettings().fmiErrorHandlingEnabled) { - FmiStatusErrorHandlingBuilder.generate(builder, "terminate", this, (IMablScope) scope, MablApiBuilder.Fmi3Status.FMI_ERROR, - MablApiBuilder.Fmi3Status.FMI_FATAL); - } + + handleError(scope, method); } // TODO: these are work in progress @@ -1209,6 +1189,7 @@ public void share(Map[originalSize+increaseByCount][maxDerivativeOrder] */ + @SuppressWarnings("unchecked") private ArrayVariableFmi2Api growSharedDerBuf(int increaseByCount) { // Get shared buffer creates the buffer with one element. @@ -1351,13 +1332,7 @@ public String getEnvironmentName() { public enum FmiFunctionType { GET, - SET, - ENTERINITIALIZATIONMODE, - EXITINITIALIZATIONMODE, - SETUPEXPERIMENT, - GETREALOUTPUTDERIVATIVES, - SETREALINPUTDERIVATIVES, - TERMINATE + SET } /** @@ -1371,8 +1346,7 @@ static void generate(MablApiBuilder builder, String method, InstanceVariableFmi3 } Function checkStatusEq = - s -> newEqual(((IMablScope) scope).getFmiStatusVariable().getReferenceExp().clone(), - builder.getFmiStatusConstant(s).getReferenceExp().clone()); + s -> newEqual(scope.getFmiStatusVariable().getReferenceExp().clone(), builder.getFmiStatusConstant(s).getReferenceExp().clone()); PExp exp = checkStatusEq.apply(statusesToFail[0]); diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/VarWrap.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/VarWrap.java new file mode 100644 index 000000000..a714dbef1 --- /dev/null +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/VarWrap.java @@ -0,0 +1,22 @@ +package org.intocps.maestro.framework.fmi2.api.mabl.variables; + +import static org.intocps.maestro.ast.MableAstFactory.*; + +/** + * Utility class to help wrap literals as variables to better reuse code + *

+ * Note that the only method that is valid to call on these objects is getExp + */ +public class VarWrap { + public static BooleanVariableFmi2Api wrap(boolean bool) { + return new BooleanVariableFmi2Api(null, null, null, null, newABoolLiteralExp(bool)); + } + + public static DoubleVariableFmi2Api wrap(double v) { + return new DoubleVariableFmi2Api(null, null, null, null, newARealLiteralExp(v)); + } + + public static IntVariableFmi2Api wrap(int v) { + return new IntVariableFmi2Api(null, null, null, null, newAIntLiteralExp(v)); + } +} diff --git a/plugins/initializer/src/main/kotlin/Initializer.kt b/plugins/initializer/src/main/kotlin/Initializer.kt index 78c6ae7bc..6aceca8ee 100644 --- a/plugins/initializer/src/main/kotlin/Initializer.kt +++ b/plugins/initializer/src/main/kotlin/Initializer.kt @@ -427,7 +427,16 @@ class Initializer : BasicMaestroExpansionPlugin { logger.debug("Enter initialization Mode") fmuInstances.values.forEach(Consumer { fmu: ComponentVariableFmi2Api -> fmu.enterInitializationMode() }) //FIXME: missing parameters -// fmu3Instances.values.forEach(Consumer { fmu: InstanceVariableFmi3Api -> fmu.enterInitializationMode() }) + val fmi3ToloranceDefined = dynamicScope.store("absoluteTolerance", this.config!!.absoluteTolerance) + fmu3Instances.values.forEach(Consumer { fmu: InstanceVariableFmi3Api -> + fmu.enterInitializationMode( + VarWrap.wrap(false), + VarWrap.wrap(0.0), + externalStartTime, + externalEndTimeDefined, + externalEndTime + ) + }) val instructions = instantiationOrder.map { i -> createInitInstructions( From f0e24dd7cb26a908f4c9346e962d16b3dc1b8db2 Mon Sep 17 00:00:00 2001 From: Kenneth Lausdahl Date: Thu, 2 Nov 2023 09:26:07 +0100 Subject: [PATCH 28/54] updated fmi3 with new types in the builder --- .../maestro/fmi/Fmi2ModelDescription.java | 2 +- .../fmi/fmi2/Fmi2ModelDescriptionUnit.kt | 1 - .../org/intocps/maestro/fmi/fmi2/Fmi2Unit.kt | 2 +- .../maestro/fmi/fmi3/Fmi3ModelDescription.kt | 8 +- .../maestro/fmi/fmi3/Fmi3ModelStructure.kt | 2 +- .../maestro/fmi/fmi3/Fmi3TypeDefinitions.kt | 2 +- .../org/intocps/maestro/fmi/fmi3/Fmi3Unit.kt | 2 +- .../intocps/maestro/fmi/fmi3/Fmi3Variables.kt | 90 +++-- .../framework/fmi2/api/FmiBuilder.java | 310 +++++++++--------- .../maestro/framework/core/IRelation.java | 4 +- .../maestro/framework/core/IVariable.java | 8 +- .../framework/core/RelationVariable.java | 62 +++- .../fmi2/Fmi2SimulationEnvironment.java | 231 +++++++++---- .../maestro/framework/fmi2/InstanceInfo.java | 2 +- .../framework/fmi2/RelationVariable.java | 285 +++++++++++++++- .../framework/fmi2/RelationVariable3.java | 108 +++--- .../framework/fmi2/api/mabl/BuilderUtil.java | 12 +- .../fmi2/api/mabl/FromMaBLToMaBLAPI.java | 21 +- .../api/mabl/ModelDescriptionContext.java | 3 +- .../api/mabl/ModelDescriptionContext3.java | 5 +- .../framework/fmi2/api/mabl/PortFmi2Api.java | 12 +- .../framework/fmi2/api/mabl/PortFmi3Api.java | 75 ++++- .../scoping/DynamicActiveBuilderScope.java | 2 +- .../fmi2/api/mabl/scoping/IMablScope.java | 2 +- .../fmi2/api/mabl/scoping/ScopeFmi2Api.java | 3 +- .../values/PortValueExpresssionMapImpl.java | 5 +- .../api/mabl/values/PortValueMapImpl.java | 5 +- .../variables/ComponentVariableFmi2Api.java | 38 ++- .../variables/InstanceVariableFmi3Api.java | 179 +++++----- .../mabl/variables/PortVariableMapImpl.java | 4 +- .../variables/VariableCreatorFmi3Api.java | 7 +- .../framework/fmi2/api/mabl/SetPortsTest.java | 3 +- .../webapi/maestro2/Maestro2Broker.java | 44 +-- .../maestro/MablSpecificationGenerator.java | 28 +- .../template/MaBLTemplateGenerator.java | 18 +- .../org/intocps/maestro/BuilderFmi3Test.java | 22 +- .../test/resources/cli-test/config-fmi3.json | 2 +- .../fmi3/basic/basic1/fmi3_basic.mabl | 2 +- .../fmi3/reference/bounchingball/fmi3_bb.mabl | 2 +- .../maestro/plugin/DataExchangeHandler.java | 58 ++-- .../maestro/plugin/DataWriterHandler.java | 25 +- .../maestro/plugin/DerivativesHandler.java | 52 ++- .../plugin/initializer/PhasePredicates.java | 9 +- .../plugin/initializer/PhasePredicates3.java | 23 ++ .../initializer/RelationsPredicates.java | 4 +- .../plugin/initializer/TopologicalPlugin.java | 20 +- .../spec/StatementGeneratorContainer.java | 64 ++-- .../src/main/kotlin/Initializer.kt | 244 ++++++++------ .../maestro/plugin/JacobianStepBuilder.java | 6 +- .../verificationsuite/graph/GraphDrawer.java | 5 +- .../InitializationPrologQuery.java | 4 +- .../prologverifier/PrologGenerator.java | 33 +- .../src/test/java/GraphPlotterTest.java | 24 +- .../src/test/java/PrologVerifierTest.java | 4 +- pom.xml | 2 +- .../org/intocps/maestro/typechecker/FMI3.mabl | 24 +- 56 files changed, 1420 insertions(+), 794 deletions(-) create mode 100644 plugins/initializer/src/main/java/org/intocps/maestro/plugin/initializer/PhasePredicates3.java diff --git a/fmi/src/main/java/org/intocps/maestro/fmi/Fmi2ModelDescription.java b/fmi/src/main/java/org/intocps/maestro/fmi/Fmi2ModelDescription.java index 1f6a0e21e..c353e69dd 100644 --- a/fmi/src/main/java/org/intocps/maestro/fmi/Fmi2ModelDescription.java +++ b/fmi/src/main/java/org/intocps/maestro/fmi/Fmi2ModelDescription.java @@ -38,7 +38,7 @@ import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.intocps.maestro.fmi.fmi2.Fmi2ModelDescriptionUnit; -import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi2.Fmi2Unit; +import org.intocps.maestro.fmi.fmi2.Fmi2Unit; import org.intocps.maestro.fmi.xml.NodeIterator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi2/Fmi2ModelDescriptionUnit.kt b/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi2/Fmi2ModelDescriptionUnit.kt index 3ccc1cca1..1c48529b7 100644 --- a/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi2/Fmi2ModelDescriptionUnit.kt +++ b/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi2/Fmi2ModelDescriptionUnit.kt @@ -2,7 +2,6 @@ package org.intocps.maestro.fmi.fmi2 import org.intocps.fmi.jnifmuapi.fmi2.schemas.Fmi2Schema import org.intocps.maestro.fmi.ModelDescription -import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi2.Fmi2Unit import org.intocps.maestro.fmi.xml.NodeIterator import org.xml.sax.SAXException import java.io.IOException diff --git a/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi2/Fmi2Unit.kt b/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi2/Fmi2Unit.kt index 179a69a87..4b0c1a446 100644 --- a/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi2/Fmi2Unit.kt +++ b/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi2/Fmi2Unit.kt @@ -1,4 +1,4 @@ -package org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi2 +package org.intocps.maestro.fmi.fmi2 import org.intocps.maestro.fmi.ModelDescription diff --git a/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi3/Fmi3ModelDescription.kt b/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi3/Fmi3ModelDescription.kt index 72fe09eac..a2b5cc837 100644 --- a/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi3/Fmi3ModelDescription.kt +++ b/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi3/Fmi3ModelDescription.kt @@ -1,4 +1,4 @@ -package org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3 +package org.intocps.maestro.fmi.fmi3 import org.apache.commons.io.IOUtils import org.intocps.fmi.jnifmuapi.fmi3.schemas.Fmi3Schema @@ -491,6 +491,9 @@ class Fmi3ModelDescription : ModelDescription { node.attributes.getNamedItem("previous")?.nodeValue?.toUInt(), node.attributes.getNamedItem("clocks")?.nodeValue?.split(" ")?.map { value -> value.toUInt() }, Fmi3TypeEnum.StringType, + (node.attributes.getNamedItem("initial")?.nodeValue ?: "").let { + if (it.isEmpty()) null else valueOf(it) + }, node.attributes.let { att -> val startValues: MutableList = mutableListOf() for (i in 0 until att.length) { @@ -571,6 +574,9 @@ class Fmi3ModelDescription : ModelDescription { node.attributes.getNamedItem("quantity")?.nodeValue ?: typeDefinition?.quantity, node.attributes.getNamedItem("min")?.nodeValue?.toLong(), node.attributes.getNamedItem("max")?.nodeValue?.toLong(), + (node.attributes.getNamedItem("initial")?.nodeValue ?: "").let { + if (it.isEmpty()) null else valueOf(it) + }, node.attributes.getNamedItem("start")?.nodeValue?.split(" ")?.map { value -> value.toLong() }, getDimensionsFromVariableNode(node) ) diff --git a/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi3/Fmi3ModelStructure.kt b/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi3/Fmi3ModelStructure.kt index 7a2cabbaf..431bcd3d7 100644 --- a/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi3/Fmi3ModelStructure.kt +++ b/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi3/Fmi3ModelStructure.kt @@ -1,4 +1,4 @@ -package org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3 +package org.intocps.maestro.fmi.fmi3 data class Fmi3ModelStructureElement(val elementType: Fmi3ModelStructureElementEnum, val valueReference: UInt, val dependencies: List?, val dependenciesKind: List?) diff --git a/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi3/Fmi3TypeDefinitions.kt b/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi3/Fmi3TypeDefinitions.kt index 1f33a9ffa..122f4d5fa 100644 --- a/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi3/Fmi3TypeDefinitions.kt +++ b/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi3/Fmi3TypeDefinitions.kt @@ -1,4 +1,4 @@ -package org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3 +package org.intocps.maestro.fmi.fmi3 data class FloatTypeDefinition( override val name: String, diff --git a/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi3/Fmi3Unit.kt b/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi3/Fmi3Unit.kt index 84a7cf83c..e5a8b5b0d 100644 --- a/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi3/Fmi3Unit.kt +++ b/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi3/Fmi3Unit.kt @@ -1,4 +1,4 @@ -package org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3 +package org.intocps.maestro.fmi.fmi3 import org.intocps.maestro.fmi.ModelDescription diff --git a/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi3/Fmi3Variables.kt b/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi3/Fmi3Variables.kt index f0b774653..5a91d5910 100644 --- a/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi3/Fmi3Variables.kt +++ b/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi3/Fmi3Variables.kt @@ -1,6 +1,5 @@ -package org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3 +package org.intocps.maestro.fmi.fmi3 -import org.intocps.maestro.fmi.Fmi2ModelDescription import org.intocps.maestro.fmi.ModelDescription abstract class Fmi3Variable protected constructor( @@ -13,9 +12,20 @@ abstract class Fmi3Variable protected constructor( val intermediateUpdate: Boolean? = false, val previous: UInt? = null, val clocks: List? = null, - val typeIdentifier: Fmi3TypeEnum // This is for easier type identification and is not part of the official spec + val typeIdentifier: Fmi3TypeEnum, // This is for easier type identification and is not part of the official spec + val initial: ModelDescription.Initial? = null //this is not present for all but added for convenience ) { - fun getValueReferenceAsLong():Long { return valueReference.toLong() } + fun getValueReferenceAsLong(): Long { + return valueReference.toLong() + } + + override fun toString(): String { + return "$name: ${typeIdentifier.name}" + } + + abstract fun isScalar(): Boolean; + + } data class Dimension(val valueReference: UInt?, val start: List?) @@ -32,7 +42,7 @@ class FloatVariable( clocks: List? = null, typeIdentifier: Fmi3TypeEnum, val declaredType: String? = null, - val initial: ModelDescription.Initial? = null, + initial: ModelDescription.Initial? = null, val quantity: String? = null, val unit: String? = null, val displayUnit: String? = null, @@ -44,7 +54,7 @@ class FloatVariable( val start: Collection? = null, val derivative: UInt? = null, val reinit: Boolean? = false, - val dimensions: List? = null + val dimensions: List? = null ) : Fmi3Variable( name, valueReference, @@ -55,8 +65,13 @@ class FloatVariable( intermediateUpdate, previous, clocks, - typeIdentifier -) + typeIdentifier, + initial +) { + override fun isScalar(): Boolean { + return dimensions.isNullOrEmpty() + } +} class Int64Variable( name: String, @@ -70,7 +85,7 @@ class Int64Variable( clocks: List? = null, typeIdentifier: Fmi3TypeEnum, val declaredType: String? = null, - val initial: ModelDescription.Initial? = null, + initial: ModelDescription.Initial? = null, val quantity: String? = null, val min: Long? = null, val max: Long? = null, @@ -86,8 +101,11 @@ class Int64Variable( intermediateUpdate, previous, clocks, - typeIdentifier -) + typeIdentifier, + initial +){ override fun isScalar(): Boolean { + return dimensions.isNullOrEmpty() +}} class IntVariable( name: String, @@ -101,7 +119,7 @@ class IntVariable( clocks: List? = null, typeIdentifier: Fmi3TypeEnum, val declaredType: String? = null, - val initial: ModelDescription.Initial? = null, + initial: ModelDescription.Initial? = null, val quantity: String? = null, val min: Int? = null, val max: Int? = null, @@ -117,8 +135,11 @@ class IntVariable( intermediateUpdate, previous, clocks, - typeIdentifier -) + typeIdentifier, + initial +){ override fun isScalar(): Boolean { + return dimensions.isNullOrEmpty() +}} class BooleanVariable( name: String, @@ -132,7 +153,7 @@ class BooleanVariable( clocks: List? = null, typeIdentifier: Fmi3TypeEnum, val declaredType: String? = null, - val initial: ModelDescription.Initial? = null, + initial: ModelDescription.Initial? = null, val start: List? = null, val dimensions: List? = null ) : Fmi3Variable( @@ -145,8 +166,11 @@ class BooleanVariable( intermediateUpdate, previous, clocks, - typeIdentifier -) + typeIdentifier, + initial +){ override fun isScalar(): Boolean { + return dimensions.isNullOrEmpty() +}} class StringVariable( name: String, @@ -159,6 +183,7 @@ class StringVariable( previous: UInt? = null, clocks: List? = null, typeIdentifier: Fmi3TypeEnum, + initial: ModelDescription.Initial? = null, val start: List? = null, val dimensions: List? = null ) : Fmi3Variable( @@ -171,8 +196,11 @@ class StringVariable( intermediateUpdate, previous, clocks, - typeIdentifier -) + typeIdentifier, + initial +){ override fun isScalar(): Boolean { + return dimensions.isNullOrEmpty() +}} class BinaryVariable( name: String, @@ -186,7 +214,7 @@ class BinaryVariable( clocks: List? = null, typeIdentifier: Fmi3TypeEnum, val declaredType: String? = null, - val initial: ModelDescription.Initial? = null, + initial: ModelDescription.Initial? = null, val mimeType: String? = null, val maxSize: UInt? = null, val start: List? = null, @@ -201,8 +229,11 @@ class BinaryVariable( intermediateUpdate, previous, clocks, - typeIdentifier -) + typeIdentifier, + initial +){ override fun isScalar(): Boolean { + return dimensions.isNullOrEmpty() +}} class EnumerationVariable( name: String, @@ -219,6 +250,7 @@ class EnumerationVariable( val quantity: String? = null, val min: Long? = null, val max: Long? = null, + initial: ModelDescription.Initial? = null, val start: List? = null, val dimensions: List? = null ) : Fmi3Variable( @@ -231,8 +263,11 @@ class EnumerationVariable( intermediateUpdate, previous, clocks, - typeIdentifier -) + typeIdentifier, + initial +){ override fun isScalar(): Boolean { + return dimensions.isNullOrEmpty() +}} class ClockVariable( name: String, @@ -266,8 +301,11 @@ class ClockVariable( intermediateUpdate, previous, clocks, - typeIdentifier -) + typeIdentifier, + null +){ override fun isScalar(): Boolean { + return dimensions.isNullOrEmpty() +}} enum class Fmi3Causality { StructuralParameter, diff --git a/frameworks/builder/src/main/java/org/intocps/maestro/framework/fmi2/api/FmiBuilder.java b/frameworks/builder/src/main/java/org/intocps/maestro/framework/fmi2/api/FmiBuilder.java index 239a660cf..09378386e 100644 --- a/frameworks/builder/src/main/java/org/intocps/maestro/framework/fmi2/api/FmiBuilder.java +++ b/frameworks/builder/src/main/java/org/intocps/maestro/framework/fmi2/api/FmiBuilder.java @@ -10,7 +10,7 @@ import java.util.Map; @SuppressWarnings("unused") -public interface FmiBuilder { +public interface FmiBuilder { B build() throws Exception; SETTINGS getSettings(); @@ -31,18 +31,18 @@ public interface FmiBuilder { PStm buildRaw() throws Exception; - RuntimeModule loadRuntimeModule(String name, Object... args); + RuntimeModule loadRuntimeModule(String name, Object... args); - RuntimeModule loadRuntimeModule(TryScope scope, String name, Object... args); + RuntimeModule loadRuntimeModule(TryScope scope, String name, Object... args); /** * Gets the default scope * * @return */ - Scope getRootScope(); + Scope getRootScope(); - DynamicActiveScope getDynamicScope(); + DynamicActiveScope getDynamicScope(); /** * Gets a tag to the last value obtained for the given port @@ -52,18 +52,18 @@ public interface FmiBuilder { */ Variable getCurrentLinkedValue(Port port); - DoubleVariable getDoubleVariableFrom(E exp); + DoubleVariable getDoubleVariableFrom(E exp); - IntVariable getIntVariableFrom(E exp); + IntVariable getIntVariableFrom(E exp); - StringVariable getStringVariableFrom(E exp); + StringVariable getStringVariableFrom(E exp); - BoolVariable getBooleanVariableFrom(E exp); + BoolVariable getBooleanVariableFrom(E exp); Variable getFmuVariableFrom(E exp); - interface RuntimeModule extends FmiBuilder.Variable> { + interface RuntimeModule extends FmiBuilder.Variable> { void initialize(List declaredFuncs); void initialize(RuntimeFunction... declaredFuncs); @@ -71,11 +71,11 @@ interface RuntimeModule extends FmiBuilder.Variable> { //not sure how to allow a mix of double, int and var except for object void callVoid(RuntimeFunction functionId, Object... args); - void callVoid(Scope scope, RuntimeFunction functionId, Object... args); + void callVoid(Scope scope, RuntimeFunction functionId, Object... args); - Variable call(Scope scope, RuntimeFunction functionId, Object... args); + Variable call(Scope scope, RuntimeFunction functionId, Object... args); - Variable call(RuntimeFunction functionId, Object... args); + Variable call(RuntimeFunction functionId, Object... args); // void destroy(); // @@ -116,7 +116,7 @@ interface RuntimeFunction { boolean usingVargs(); - static public class FunctionType { + class FunctionType { final Type nativeType; final String namedType; @@ -160,23 +160,23 @@ static public enum Type { /** * Scoping element which defines a scope like a block, if, while etc. * - * @param the type the scoping element encloses + * @param the type the scoping element encloses */ - interface ScopeElement { + interface ScopeElement { /** * The parent element of this element or null if root * * @return the parent */ - ScopeElement parent(); + ScopeElement parent(); /** * The declaration node that defined the underlying scope * * @return the scope */ - T getDeclaration(); + AST getDeclaration(); /** * Find a prent element of a specific type @@ -185,36 +185,36 @@ interface ScopeElement { * @param

the type of class * @return the parent of the specified type or null */ -

> P findParent(Class

clz); +

> P findParent(Class

clz); } /** * Scoping functions */ - interface Scoping extends ScopeElement { - WhileScope enterWhile(Predicate predicate); + interface Scoping extends ScopeElement { + WhileScope enterWhile(Predicate predicate); - IfScope enterIf(Predicate predicate); + IfScope enterIf(Predicate predicate); - TryScope enterTry(); + TryScope enterTry(); - Scoping parallel(); + Scoping parallel(); - Scoping enterScope(); + Scoping enterScope(); - Scope leave(); + Scope leave(); - void add(T... commands); + void add(AST... commands); - void addAll(Collection commands); + void addAll(Collection commands); - void addBefore(T item, T... commands); + void addBefore(AST item, AST... commands); - void addAfter(T item, T... commands); + void addAfter(AST item, AST... commands); - Scoping activate(); + Scoping activate(); } @@ -222,9 +222,9 @@ interface Scoping extends ScopeElement { /** * Basic scope. Allows a value to be stored or override a tag */ - interface Scope extends Scoping { + interface Scope extends Scoping { @Override - Scope activate(); + Scope activate(); /** * Store a given value @@ -232,13 +232,13 @@ interface Scope extends Scoping { * @param value * @return */ - DoubleVariable store(double value); + DoubleVariable store(double value); - StringVariable store(String value); + StringVariable store(String value); - BoolVariable store(boolean value); + BoolVariable store(boolean value); - IntVariable store(int value); + IntVariable store(int value); /** * Store a given value with a prefix name @@ -246,15 +246,15 @@ interface Scope extends Scoping { * @param value * @return */ - DoubleVariable store(String name, double value); + DoubleVariable store(String name, double value); - StringVariable store(String name, String value); + StringVariable store(String name, String value); - BoolVariable store(String name, boolean value); + BoolVariable store(String name, boolean value); - IntVariable store(String name, int value); + IntVariable store(String name, int value); - ArrayVariable store(String name, CV value[]); + ArrayVariable store(String name, CV value[]); /** * Store the given value and get a tag for it. Copy @@ -263,11 +263,11 @@ interface Scope extends Scoping { * @return */ @Deprecated - Variable store(Value tag); + Variable store(Value tag); - Fmu2Variable createFMU(String name, String loaderName, String... args) throws Exception; + Fmu2Variable createFMU(String name, String loaderName, String... args) throws Exception; - Fmu3Variable createFMU3(String name, String loaderName, String... args) throws Exception; + Fmu3Variable createFMU3(String name, String loaderName, String... args) throws Exception; void markTransferPoint(String... names); @@ -278,61 +278,61 @@ interface Scope extends Scoping { /** * Dynamic scope which always reflects the current active scope of the builder */ - interface DynamicActiveScope extends Scope { + interface DynamicActiveScope extends Scope { } /** * If scope, default scope is then */ - interface IfScope extends ScopeElement { + interface IfScope extends ScopeElement { /** * Switch to then scope * * @return */ - Scope enterThen(); + Scope enterThen(); /** * Switch to else scope * * @return */ - Scope enterElse(); + Scope enterElse(); - Scope leave(); + Scope leave(); } /** * Try finally scope, default scope is body */ - interface TryScope extends ScopeElement { + interface TryScope extends ScopeElement { /** * Switch to body scope * * @return */ - Scope enter(); + Scope enter(); /** * Switch to finally scope * * @return */ - Scope enterFinally(); + Scope enterFinally(); - Scope leave(); + Scope leave(); - Scope getBody(); + Scope getBody(); - Scope getFinallyBody(); + Scope getFinallyBody(); } /** * While */ - interface WhileScope extends Scope, ScopeElement { + interface WhileScope extends Scope, ScopeElement { } @@ -356,7 +356,7 @@ interface Numeric extends Value, Type { } - interface Port { + interface Port { /** * Gets the fully qualified port name including its source reference. Often on the form source.name @@ -365,12 +365,20 @@ interface Port { */ String getQualifiedName(); + + /** + * Get the owner of this port. This is the object that should be used to get/set its values + * + * @return the instance owning the port + */ + FmiSimulationInstance getOwner(); + /** * Gets the underlying objects from which the port is created * * @return */ - T getSourceObject(); + PORT_SCALAR_TYPE getSourceObject(); /** * Get the port name @@ -391,7 +399,7 @@ interface Port { * * @param receiver */ - void linkTo(Port... receiver) throws PortLinkException; + void linkTo(Port< PORT_SCALAR_TYPE,AST>... receiver) throws PortLinkException; /** * Break the source link @@ -439,7 +447,7 @@ interface NamedValue extends Value { } - interface IntVariable extends Variable, ProvidesTypedReferenceExp, NumericTypedReferenceExp { + interface IntVariable extends Variable, ProvidesTypedReferenceExp, NumericTypedReferenceExp { void decrement(); void increment(); @@ -456,12 +464,12 @@ interface ProvidesTypedReferenceExp { interface NumericTypedReferenceExp extends ProvidesTypedReferenceExp { } - interface DoubleVariable extends Variable, ProvidesTypedReferenceExp, NumericTypedReferenceExp { + interface DoubleVariable extends Variable, ProvidesTypedReferenceExp, NumericTypedReferenceExp { void set(Double value); } - interface BoolVariable extends Variable, ProvidesTypedReferenceExp { + interface BoolVariable extends Variable, ProvidesTypedReferenceExp { Predicate toPredicate(); } @@ -470,10 +478,10 @@ interface StringVariable extends Variable, Provides } - interface NamedVariable extends Variable { + interface NamedVariable extends Variable { } - interface StateVariable extends Variable { + interface StateVariable extends Variable { /** * Sets this state on the owning component in the active scope */ @@ -482,7 +490,7 @@ interface StateVariable extends Variable { /** * Sets this state on the owning component in the given scope */ - void set(Scope scope) throws IllegalStateException; + void set(Scope scope) throws IllegalStateException; /** * Destroys the state in the active scope. After this no other operation on the state is allowed @@ -492,17 +500,17 @@ interface StateVariable extends Variable { /** * Destroys the state in the active scope. After this no other operation on the state is allowed */ - void destroy(Scope scope) throws IllegalStateException; + void destroy(Scope scope) throws IllegalStateException; } /** * Handle for an fmu for the creation of component */ - interface Fmu2Variable extends Variable> { - Fmi2ComponentVariable instantiate(String name, String environmentname); + interface Fmu2Variable extends Variable> { + Fmi2ComponentVariable instantiate(String name, String environmentname); - Fmi2ComponentVariable instantiate(String name); + Fmi2ComponentVariable instantiate(String name); // /** // * Performs null check and frees the instance @@ -520,12 +528,13 @@ interface Fmu2Variable extends Variable> { // throw new RuntimeException("Argument is not an FMU instance - it is not an instance of ComponentVariableFmi2API"); // } // } - Fmi2ComponentVariable instantiate(String namePrefix, TryScope enclosingTryScope, Scope scope, String environmentName); + Fmi2ComponentVariable instantiate(String namePrefix, TryScope enclosingTryScope, Scope scope, + String environmentName); - Fmi2ComponentVariable instantiate(String namePrefix, FmiBuilder.TryScope enclosingTryScope, FmiBuilder.Scope scope, - String environmentName, boolean loggingOn); + Fmi2ComponentVariable instantiate(String namePrefix, FmiBuilder.TryScope enclosingTryScope, + FmiBuilder.Scope scope, String environmentName, boolean loggingOn); - Fmi2ComponentVariable instantiate(String name, TryScope enclosingTryScope, Scope scope); + Fmi2ComponentVariable instantiate(String name, TryScope enclosingTryScope, Scope scope); //void freeInstance(Fmi2ComponentVariable comp); @@ -539,7 +548,7 @@ Fmi2ComponentVariable instantiate(String namePrefix, FmiBuilder.TryScope< /** * Handle for an fmu for the creation of component */ - interface Fmu3Variable extends Variable> { + interface Fmu3Variable extends Variable> { } @@ -547,18 +556,18 @@ interface Fmu3Variable extends Variable> { /** * Generic type for all simulation instances * - * @param + * @param */ - interface SimulationInstance extends Variable> { + interface SimulationInstance extends Variable> { } /** * Type that represents common FMI functions accross versions for now 2 and 3 * - * @param the construction type. Often a kind of AST statement - * @param the port internal reference type. Often a kind of scalar variable from FMI + * @param the construction type. Often a kind of AST statement + * @param the port internal reference type. Often a kind of scalar variable from FMI */ - interface FmiSimulationInstance extends SimulationInstance { + interface FmiSimulationInstance extends SimulationInstance { void setDebugLogging(List categories, boolean enableLogging); @@ -570,19 +579,20 @@ interface FmiSimulationInstance extends SimulationInstance { * @param noSetFMUStatePriorToCurrentPoint a pair representing (full step completed, current time after step) * @return */ - Map.Entry, DoubleVariable> step(Scope scope, DoubleVariable currentCommunicationPoint, - DoubleVariable communicationStepSize, BoolVariable noSetFMUStatePriorToCurrentPoint); + Map.Entry, DoubleVariable> step(Scope scope, DoubleVariable currentCommunicationPoint, + DoubleVariable communicationStepSize, BoolVariable noSetFMUStatePriorToCurrentPoint); - Map.Entry, DoubleVariable> step(Scope scope, DoubleVariable currentCommunicationPoint, - DoubleVariable communicationStepSize); + Map.Entry, DoubleVariable> step(Scope scope, DoubleVariable currentCommunicationPoint, + DoubleVariable communicationStepSize); - Map.Entry, DoubleVariable> step(DoubleVariable currentCommunicationPoint, DoubleVariable communicationStepSize, - BoolVariable noSetFMUStatePriorToCurrentPoint); + Map.Entry, DoubleVariable> step(DoubleVariable currentCommunicationPoint, + DoubleVariable communicationStepSize, BoolVariable noSetFMUStatePriorToCurrentPoint); - Map.Entry, DoubleVariable> step(DoubleVariable currentCommunicationPoint, DoubleVariable communicationStepSize); + Map.Entry, DoubleVariable> step(DoubleVariable currentCommunicationPoint, + DoubleVariable communicationStepSize); - List> getPorts(); + List> getPorts(); /** * Get ports by name @@ -590,7 +600,7 @@ Map.Entry, DoubleVariable> step(DoubleVariable currentComm * @param names * @return */ - List> getPorts(String... names); + List> getPorts(String... names); /** * Get ports by ref val @@ -598,7 +608,7 @@ Map.Entry, DoubleVariable> step(DoubleVariable currentComm * @param valueReferences * @return */ - List> getPorts(int... valueReferences); + List> getPorts(int... valueReferences); /** * Get port by name @@ -606,7 +616,7 @@ Map.Entry, DoubleVariable> step(DoubleVariable currentComm * @param name * @return */ - Port getPort(String name); + Port getPort(String name); /** * Get port by ref val @@ -614,7 +624,7 @@ Map.Entry, DoubleVariable> step(DoubleVariable currentComm * @param valueReference * @return */ - Port getPort(int valueReference); + Port getPort(int valueReference); /** * Get port values aka fmiGet @@ -622,16 +632,16 @@ Map.Entry, DoubleVariable> step(DoubleVariable currentComm * @param ports * @return */ - Map, ? extends Variable> get(Port... ports); + Map, ? extends Variable> get(Port... ports); - Map, ? extends Variable> get(Scope scope, Port... ports); + Map, ? extends Variable> get(Scope scope, Port... ports); /** * Get all (linked) port values * * @return */ - Map, ? extends Variable> get(); + Map, ? extends Variable> get(); /** * get filter by value reference @@ -639,7 +649,7 @@ Map.Entry, DoubleVariable> step(DoubleVariable currentComm * @param valueReferences * @return */ - Map, ? extends Variable> get(int... valueReferences); + Map, ? extends Variable> get(int... valueReferences); /** * Get filter by names @@ -647,17 +657,17 @@ Map.Entry, DoubleVariable> step(DoubleVariable currentComm * @param names * @return */ - Map, ? extends Variable> get(String... names); + Map, ? extends Variable> get(String... names); - Map, ? extends Variable> getAndShare(String... names); + Map, ? extends Variable> getAndShare(String... names); - Map, ? extends Variable> getAndShare(Port... ports); + Map, ? extends Variable> getAndShare(Port... ports); - Map, ? extends Variable> getAndShare(); + Map, ? extends Variable> getAndShare(); - Variable getShared(String name); + Variable getShared(String name); - Variable getShared(Port port); + Variable getShared(Port port); /** * Get the value of a single port @@ -665,38 +675,38 @@ Map.Entry, DoubleVariable> step(DoubleVariable currentComm * @param name * @return */ - Variable getSingle(String name); + Variable getSingle(String name); - Variable getSingle(Port port); + Variable getSingle(Port port); - void set(Scope scope, PortValueMap value); + void set(Scope scope, PortValueMap value); - void set(Scope scope, PortVariableMap value); + void set(Scope scope, PortVariableMap< V, PORT_SCALAR_TYPE, AST> value); /** * Set port values (if ports is not from this fmu then the links are used to remap) * * @param value */ - void set(PortValueMap value); + void set(PortValueMap value); - void set(Port port, Value value); + void set(Port port, Value value); - void set(Port port, Variable value); + void set(Port port, Variable value); - void set(Scope scope, Port port, Variable value); + void set(Scope scope, Port port, Variable value); - void set(PortVariableMap value); + void set(PortVariableMap< V, PORT_SCALAR_TYPE, AST> value); /** * Set this fmu port by name and link */ - void setLinked(Scope scope, Port... filterPorts); + void setLinked(Scope scope, Port... filterPorts); void setLinked(); - void setLinked(Port... filterPorts); + void setLinked(Port... filterPorts); void setLinked(String... filterNames); @@ -722,7 +732,7 @@ Map.Entry, DoubleVariable> step(DoubleVariable currentComm * * @param values */ - void share(Map, ? extends Variable> values); + void share(Map, ? extends Variable> values); /** * Makes the value publicly available to all linked connections. On next set these ports will be resolved to the values given for @@ -730,64 +740,66 @@ Map.Entry, DoubleVariable> step(DoubleVariable currentComm * * @param value */ - void share(Port port, Variable value); + void share(Port port, Variable value); /** * Get the current state * * @return */ - StateVariable getState() throws XPathExpressionException; + StateVariable getState() throws XPathExpressionException; /** * Get the current state * * @return */ - StateVariable getState(Scope scope) throws XPathExpressionException; + StateVariable getState(Scope scope) throws XPathExpressionException; - interface PortVariableMap extends Map, Variable> { + interface PortVariableMap< V, PORT_SCALAR_TYPE, AST> extends Map, Variable> { } - interface PortValueMap extends Map, Value> { + interface PortValueMap extends Map, Value> { } - interface PortExpressionValueMap extends Map, ExpressionValue> { + interface PortExpressionValueMap extends Map, ExpressionValue> { } } /** * Simulation instance for FMI3 * - * @param building block - * @param fmi3 scalar variable type + * @param building block + * @param fmi3 scalar variable type */ - interface Fmi3InstanceVariable extends FmiSimulationInstance { + interface Fmi3InstanceVariable extends FmiSimulationInstance { - void setupExperiment(DoubleVariable startTime, DoubleVariable endTime, BoolVariable endTimeDefined, Double tolerance); + void setupExperiment(DoubleVariable startTime, DoubleVariable endTime, BoolVariable endTimeDefined, Double tolerance); void setupExperiment(double startTime, Double endTime, Double tolerance); void enterInitializationMode(boolean toleranceDefined, double tolerance, double startTime, boolean stopTimeDefined, double stopTime); - void enterInitializationMode(Scope scope,FmiBuilder.BoolVariable toleranceDefined, FmiBuilder.DoubleVariable tolerance, FmiBuilder.DoubleVariable startTime, - FmiBuilder.BoolVariable stopTimeDefined, FmiBuilder.DoubleVariable stopTime); - void enterInitializationMode(FmiBuilder.BoolVariable toleranceDefined, FmiBuilder.DoubleVariable tolerance, FmiBuilder.DoubleVariable startTime, - FmiBuilder.BoolVariable stopTimeDefined, FmiBuilder.DoubleVariable stopTime); + void enterInitializationMode(Scope scope, FmiBuilder.BoolVariable toleranceDefined, FmiBuilder.DoubleVariable tolerance, + FmiBuilder.DoubleVariable startTime, FmiBuilder.BoolVariable stopTimeDefined, FmiBuilder.DoubleVariable stopTime); + + void enterInitializationMode(FmiBuilder.BoolVariable toleranceDefined, FmiBuilder.DoubleVariable tolerance, + FmiBuilder.DoubleVariable startTime, FmiBuilder.BoolVariable stopTimeDefined, FmiBuilder.DoubleVariable stopTime); + void exitInitializationMode(); - void setupExperiment(Scope scope, DoubleVariable startTime, DoubleVariable endTime, BoolVariable endTimeDefined, + void setupExperiment(Scope scope, DoubleVariable startTime, DoubleVariable endTime, BoolVariable endTimeDefined, Double tolerance); - void setupExperiment(Scope scope, double startTime, Double endTime, Double tolerance); + void setupExperiment(Scope scope, double startTime, Double endTime, Double tolerance); - void enterInitializationMode(Scope scope,boolean toleranceDefined, double tolerance, double startTime, boolean stopTimeDefined, + void enterInitializationMode(Scope scope, boolean toleranceDefined, double tolerance, double startTime, boolean stopTimeDefined, double stopTime); - void exitInitializationMode(Scope scope); + void exitInitializationMode(Scope scope); - void terminate(Scope scope); + void terminate(Scope scope); void terminate(); @@ -799,14 +811,14 @@ void enterInitializationMode(Scope scope,boolean toleranceDefined, double tol *

* Note that all methods that do not take a scope uses the builders dynamic scope and adds the underlying instructions int he active scope. * - * @param building block - * @param fmi2 scalar variable type + * @param building block + * @param fmi2 scalar variable type */ - interface Fmi2ComponentVariable extends FmiSimulationInstance { + interface Fmi2ComponentVariable extends FmiSimulationInstance { void setDebugLogging(List categories, boolean enableLogging); - void setupExperiment(DoubleVariable startTime, DoubleVariable endTime, BoolVariable endTimeDefined, Double tolerance); + void setupExperiment(DoubleVariable startTime, DoubleVariable endTime, BoolVariable endTimeDefined, Double tolerance); void setupExperiment(double startTime, Double endTime, Double tolerance); @@ -814,39 +826,39 @@ interface Fmi2ComponentVariable extends FmiSimulationInstance { void exitInitializationMode(); - void setupExperiment(Scope scope, DoubleVariable startTime, DoubleVariable endTime, BoolVariable endTimeDefined, + void setupExperiment(Scope scope, DoubleVariable startTime, DoubleVariable endTime, BoolVariable endTimeDefined, Double tolerance); - void setupExperiment(Scope scope, double startTime, Double endTime, Double tolerance); + void setupExperiment(Scope scope, double startTime, Double endTime, Double tolerance); - void enterInitializationMode(Scope scope); + void enterInitializationMode(Scope scope); - void exitInitializationMode(Scope scope); + void exitInitializationMode(Scope scope); - void terminate(Scope scope); + void terminate(Scope scope); void terminate(); } - interface Variable { + interface Variable { String getName(); void setValue(V value); - void setValue(Variable variable); + void setValue(Variable variable); - void setValue(Scope scope, Variable variable); + void setValue(Scope scope, Variable variable); - void setValue(Scope scope, V value); + void setValue(Scope scope, V value); - Scope getDeclaredScope(); + Scope getDeclaredScope(); } - interface ArrayVariable extends Variable> { + interface ArrayVariable extends Variable> { int size(); - List> items(); + List> items(); void setValue(IntExpressionValue index, ExpressionValue value); } diff --git a/frameworks/core/src/main/java/org/intocps/maestro/framework/core/IRelation.java b/frameworks/core/src/main/java/org/intocps/maestro/framework/core/IRelation.java index ee7407125..1e69de09b 100644 --- a/frameworks/core/src/main/java/org/intocps/maestro/framework/core/IRelation.java +++ b/frameworks/core/src/main/java/org/intocps/maestro/framework/core/IRelation.java @@ -7,11 +7,11 @@ public interface IRelation { InternalOrExternal getOrigin(); - IVariable getSource(); + RelationVariable getSource(); Direction getDirection(); - Map getTargets(); + Map getTargets(); public enum InternalOrExternal { Internal, diff --git a/frameworks/core/src/main/java/org/intocps/maestro/framework/core/IVariable.java b/frameworks/core/src/main/java/org/intocps/maestro/framework/core/IVariable.java index e1e2bfb7e..3d4ddbf84 100644 --- a/frameworks/core/src/main/java/org/intocps/maestro/framework/core/IVariable.java +++ b/frameworks/core/src/main/java/org/intocps/maestro/framework/core/IVariable.java @@ -1,6 +1,6 @@ package org.intocps.maestro.framework.core; -public interface IVariable { - - RelationVariable getScalarVariable(); -} +//public interface IVariable { +// +// RelationVariable getScalarVariable(); +//} diff --git a/frameworks/core/src/main/java/org/intocps/maestro/framework/core/RelationVariable.java b/frameworks/core/src/main/java/org/intocps/maestro/framework/core/RelationVariable.java index a1755c759..f57482474 100644 --- a/frameworks/core/src/main/java/org/intocps/maestro/framework/core/RelationVariable.java +++ b/frameworks/core/src/main/java/org/intocps/maestro/framework/core/RelationVariable.java @@ -1,12 +1,72 @@ package org.intocps.maestro.framework.core; import org.intocps.maestro.ast.LexIdentifier; +import org.intocps.maestro.ast.node.PExp; +import org.intocps.maestro.ast.node.PType; import org.intocps.maestro.fmi.Fmi2ModelDescription; public interface RelationVariable { + /** + * Get the instance reference aka the lex name for the instance + * + * @return the lex identifier + */ LexIdentifier getInstance(); + /** + * Get the scalar variable name as in the model description this name will not be changed due to slashes + * + * @return the name + */ String getName(); - T getScalarVariable(Class clz); + /** + * Get the underlying scalar variable object as is or null is not matching the requested type + * + * @param clz the underlying type to filter by + * @param the filter type + * @return the underlying scalar variable object of the requested type + */ + T getScalarVariable(Class clz); + + /** + * Checks if any of the scalar variable enums apply for i.e. causality, Variability etc. + * + * @param scalarAttributeType object to check + * @return true if present + */ + boolean has(Object scalarAttributeType); + + + Type getType(); + +// Type getType(Class clz); + + /** + * The value reference of the scalar variable + * + * @return the value reference + */ + long getValueReference(); + + interface Type { + +// TP as(Class clz); + + /** + * Check if the scala variable holds the requested type enum + * + * @param type type enum to check for + * @return true if of the specified type + */ + boolean hasType(TypeEnum type); + + T get(); + + PType getLexType(); + + PExp getLexDefaultValue(); + + boolean isAssignableFrom(T other, boolean autoConvert); + } } diff --git a/frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/Fmi2SimulationEnvironment.java b/frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/Fmi2SimulationEnvironment.java index 968987edb..650cf633c 100644 --- a/frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/Fmi2SimulationEnvironment.java +++ b/frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/Fmi2SimulationEnvironment.java @@ -11,7 +11,8 @@ import org.intocps.maestro.core.messages.IErrorReporter; import org.intocps.maestro.fmi.Fmi2ModelDescription; import org.intocps.maestro.fmi.ModelDescription; -import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; +import org.intocps.maestro.fmi.fmi3.Fmi3Causality; +import org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; import org.intocps.maestro.framework.core.*; import org.intocps.maestro.parser.template.MablSwapConditionParserUtil; import org.slf4j.Logger; @@ -35,6 +36,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +@SuppressWarnings("rawtypes") public class Fmi2SimulationEnvironment implements ISimulationEnvironment, ISimulationEnvironmentTransfer { final static Logger logger = LoggerFactory.getLogger(Fmi2SimulationEnvironment.class); private final Map instanceLexToInstanceName = new HashMap<>(); @@ -43,8 +45,8 @@ public class Fmi2SimulationEnvironment implements ISimulationEnvironment, ISimul Map instanceNameToInstanceComponentInfo = new HashMap<>(); HashMap fmuKeyToModelDescription = new HashMap<>(); Map fmuToUri = null; - Map variables = new HashMap<>(); - Map> globalVariablesToLogForInstance = new HashMap<>(); + Map variables = new HashMap<>(); + Map> globalVariablesToLogForInstance = new HashMap<>(); Map instanceToModelTransfer = new HashMap<>(); Map instanceToModelSwap = new HashMap<>(); private String faultInjectionConfigurationPath; @@ -95,7 +97,7 @@ private static Map> t = variablesToLogMap.entrySet().stream().collect( Collectors.toMap(entry -> extractInstance.apply(entry.getKey()), entry -> globalVariablesToLogForInstance.get(extractInstance.apply(entry.getKey())).stream() - .filter(x -> entry.getValue().contains(x.scalarVariable.name)).collect(Collectors.toList()))); + .filter(x -> entry.getValue().contains(x.getName())).collect(Collectors.toList()))); return t; } @@ -103,9 +105,8 @@ private static Map getConnectedOutputs() { return getInstances().stream().flatMap(instance -> this.getRelations(new LexIdentifier(instance.getKey(), null)).stream() - .filter(relation -> (relation.getOrigin() == Relation.InternalOrExternal.External) && - (relation.getDirection() == Relation.Direction.OutputToInput)).map(x -> x.getSource().scalarVariable)) - .collect(Collectors.toList()); + .filter(relation -> (relation.getOrigin() == Relation.InternalOrExternal.External) && + (relation.getDirection() == Relation.Direction.OutputToInput)).map(x -> x.getSource())).collect(Collectors.toList()); } @@ -150,8 +151,8 @@ public FrameworkUnitInfo getInstanceByLexName(String lexName) { * @return */ @Override - public List getVariablesToLog(String instanceName) { - List vars = this.globalVariablesToLogForInstance.get(instanceName); + public List getVariablesToLog(String instanceName) { + List vars = this.globalVariablesToLogForInstance.get(instanceName); if (vars == null) { return new ArrayList<>(); } else { @@ -222,7 +223,7 @@ private void initialize(Fmi2SimulationEnvironmentConfiguration msg, ModelDescrip HashMap fmuKeyToModelDescription = buildFmuKeyToFmuMD(fmuToURI, resolver); this.fmuKeyToModelDescription = fmuKeyToModelDescription; - if (msg.faultInjectConfigurationPath != null && msg.faultInjectConfigurationPath.length() > 0) { + if (msg.faultInjectConfigurationPath != null && !msg.faultInjectConfigurationPath.isEmpty()) { if ((new File(msg.faultInjectConfigurationPath).exists())) { this.faultInjectionConfigurationPath = msg.faultInjectConfigurationPath; } else { @@ -264,7 +265,7 @@ private Map> buildRelations(Fmi2SimulationEnvironme // Add the instance to the globalVariablesToLogForInstance map. - List globalVariablesToLogForGivenInstance; + List globalVariablesToLogForGivenInstance; if (this.globalVariablesToLogForInstance.containsKey(instance.instanceName)) { globalVariablesToLogForGivenInstance = this.globalVariablesToLogForInstance.get(instance.instanceName); } else { @@ -278,7 +279,8 @@ private Map> buildRelations(Fmi2SimulationEnvironme buildFmi2Relation((Fmi2ModelDescription) md, instance, instanceLexIdentifier, idToRelations, connections, globalVariablesToLogForGivenInstance); } else if (md instanceof Fmi3ModelDescription) { - + buildFmi3Relation((Fmi3ModelDescription) md, instance, instanceLexIdentifier, idToRelations, connections, + globalVariablesToLogForGivenInstance); } } @@ -296,22 +298,26 @@ private Map> buildRelations(Fmi2SimulationEnvironme } - List variablesToLogForInstance = new ArrayList<>(); + List variablesToLogForInstance = new ArrayList<>(); String logVariablesKey = instance.key + "." + instance.instanceName; if (globalLogVariablesMaps.containsKey(logVariablesKey)) { for (String s : globalLogVariablesMaps.get(logVariablesKey)) { ModelDescription md = this.fmuKeyToModelDescription.get(instance.key); - org.intocps.maestro.framework.core.RelationVariable rvar = null; + RelationVariable rvar = null; if (md instanceof Fmi2ModelDescription) { - rvar = new RelationVariable( - ((Fmi2ModelDescription) md).getScalarVariables().stream().filter(x -> x.name.equals(s)).findFirst().get(), - instanceLexIdentifier); + Fmi2ModelDescription.ScalarVariable sv = + ((Fmi2ModelDescription) md).getScalarVariables().stream().filter(x -> x.name.equals(s)).findFirst().get(); + rvar = new RelationVariable<>(sv, sv.getName(), instanceLexIdentifier, sv.getValueReference(), + new RelationVariable.RelationFmi2Type(sv.getType())); } else if (md instanceof Fmi3ModelDescription) { - rvar = new RelationVariable3( + Fmi3ModelDescription.Fmi3ScalarVariable sv = ((Fmi3ModelDescription) md).getScalarVariables().stream().filter(x -> x.getVariable().getName().equals(s)).findFirst() - .get(), instanceLexIdentifier); + .get(); + rvar = new RelationVariable<>(sv, sv.getVariable().getName(), instanceLexIdentifier, + sv.getVariable().getValueReferenceAsLong(), + new RelationVariable.RelationFmi3Type(sv.getVariable().getTypeIdentifier())); } @@ -320,9 +326,8 @@ private Map> buildRelations(Fmi2SimulationEnvironme } if (this.globalVariablesToLogForInstance.containsKey(instance.instanceName)) { - List existingRVs = - this.globalVariablesToLogForInstance.get(instance.instanceName); - for (org.intocps.maestro.framework.core.RelationVariable rv : variablesToLogForInstance) { + List existingRVs = this.globalVariablesToLogForInstance.get(instance.instanceName); + for (RelationVariable rv : variablesToLogForInstance) { if (!existingRVs.contains(rv)) { existingRVs.add(rv); } @@ -338,25 +343,31 @@ private Map> buildRelations(Fmi2SimulationEnvironme private void buildFmi2Relation(Fmi2ModelDescription md2, ModelConnection.ModelInstance instance, LexIdentifier instanceLexIdentifier, Map> idToRelations, List connections, - List globalVariablesToLogForGivenInstance) throws XPathExpressionException, InvocationTargetException, IllegalAccessException, EnvironmentException { + List globalVariablesToLogForGivenInstance) throws XPathExpressionException, InvocationTargetException, IllegalAccessException, EnvironmentException { + + List instanceOutputScalarVariablesPorts = md2.getScalarVariables().stream().filter(x -> x.causality == Fmi2ModelDescription.Causality.Output).collect(Collectors.toList()); Set instanceRelations = idToRelations.computeIfAbsent(instanceLexIdentifier, key -> new HashSet<>()); for (Fmi2ModelDescription.ScalarVariable outputScalarVariable : instanceOutputScalarVariablesPorts) { - Variable outputVariable = getOrCreateVariable(outputScalarVariable, instanceLexIdentifier); + RelationVariable outputVariable = getOrCreateVariable( + new org.intocps.maestro.framework.fmi2.RelationVariable<>(outputScalarVariable, outputScalarVariable.getName(), + instanceLexIdentifier), instanceLexIdentifier); // dependantInputs are the inputs on which the current output depends on internally - Map dependantInputs = new HashMap<>(); + Map dependantInputs = new HashMap<>(); for (Fmi2ModelDescription.ScalarVariable inputScalarVariable : outputScalarVariable.outputDependencies.keySet()) { if (inputScalarVariable.causality == Fmi2ModelDescription.Causality.Input) { - Variable inputVariable = getOrCreateVariable(inputScalarVariable, instanceLexIdentifier); + RelationVariable inputVariable = getOrCreateVariable( + new org.intocps.maestro.framework.fmi2.RelationVariable<>(outputScalarVariable, outputScalarVariable.getName(), + instanceLexIdentifier), instanceLexIdentifier); dependantInputs.put(instanceLexIdentifier, inputVariable); } // TODO: Add relation from each input to the given output? } - if (dependantInputs.size() != 0) { + if (!dependantInputs.isEmpty()) { Relation r = new Relation(); r.source = outputVariable; r.targets = dependantInputs; @@ -369,11 +380,11 @@ private void buildFmi2Relation(Fmi2ModelDescription md2, ModelConnection.ModelIn List externalInputTargets = connections.stream().filter(conn -> conn.from.instance.equals(instance) && conn.from.variable.equals(outputScalarVariable.name)) .map(conn -> conn.to).collect(Collectors.toList()); - if (externalInputTargets.size() != 0) { + if (!externalInputTargets.isEmpty()) { // Log the current output as there is an input depending on it. - globalVariablesToLogForGivenInstance.add(outputVariable.scalarVariable); + globalVariablesToLogForGivenInstance.add(outputVariable); // externalInputs are all the external Inputs that depends on the current output - Map externalInputs = new HashMap<>(); + Map externalInputs = new HashMap<>(); for (ModelConnection.Variable modelConnToVar : externalInputTargets) { FrameworkUnitInfo frameworkUnitInfo = instanceNameToInstanceComponentInfo.get(modelConnToVar.instance.instanceName); @@ -385,7 +396,97 @@ private void buildFmi2Relation(Fmi2ModelDescription md2, ModelConnection.ModelIn .filter(sv -> sv.name.equals(modelConnToVar.variable)).findFirst(); if (toScalarVariable.isPresent()) { LexIdentifier inputInstanceLexIdentifier = new LexIdentifier(modelConnToVar.instance.instanceName, null); - Variable inputVariable = getOrCreateVariable(toScalarVariable.get(), inputInstanceLexIdentifier); + RelationVariable inputVariable = getOrCreateVariable( + new org.intocps.maestro.framework.fmi2.RelationVariable<>(toScalarVariable.get(), + toScalarVariable.get().getName(), inputInstanceLexIdentifier), inputInstanceLexIdentifier); + externalInputs.put(inputInstanceLexIdentifier, inputVariable); + + //Add relation from the input to the given output + Set inputInstanceRelations = idToRelations.computeIfAbsent(inputInstanceLexIdentifier, key -> new HashSet<>()); + Relation r = new Relation(); + r.source = inputVariable; + r.targets = new HashMap<>() {{ + put(instanceLexIdentifier, outputVariable); + }}; + r.origin = Relation.InternalOrExternal.External; + r.direction = Relation.Direction.InputToOutput; + inputInstanceRelations.add(r); + } else { + throw new EnvironmentException( + "Failed to find the scalar variable " + modelConnToVar.variable + " at " + modelConnToVar.instance + + " when building the dependencies tree"); + } + } else { + logger.warn("Framework unit is not a component: {}", frameworkUnitInfo.getClass().getName()); + } + } + + Relation r = new Relation(); + r.source = outputVariable; + r.targets = externalInputs; + r.direction = Relation.Direction.OutputToInput; + r.origin = Relation.InternalOrExternal.External; + instanceRelations.add(r); + } + } + } + + private void buildFmi3Relation(Fmi3ModelDescription md2, ModelConnection.ModelInstance instance, LexIdentifier instanceLexIdentifier, + Map> idToRelations, List connections, + List globalVariablesToLogForGivenInstance) throws EnvironmentException { + List instanceOutputScalarVariablesPorts = + md2.getScalarVariables().stream().filter(x -> x.getVariable().getCausality() == Fmi3Causality.Output).collect(Collectors.toList()); + + Set instanceRelations = idToRelations.computeIfAbsent(instanceLexIdentifier, key -> new HashSet<>()); + + for (Fmi3ModelDescription.Fmi3ScalarVariable outputScalarVariable : instanceOutputScalarVariablesPorts) { + RelationVariable outputVariable = getOrCreateVariable( + new org.intocps.maestro.framework.fmi2.RelationVariable<>(outputScalarVariable, outputScalarVariable.getVariable().getName(), + instanceLexIdentifier), instanceLexIdentifier); + + // dependantInputs are the inputs on which the current output depends on internally + Map dependantInputs = new HashMap<>(); + for (Fmi3ModelDescription.Fmi3ScalarVariable inputScalarVariable : outputScalarVariable.getOutputDependencies().keySet()) { + if (inputScalarVariable.getVariable().getCausality() == Fmi3Causality.Input) { + RelationVariable inputVariable = getOrCreateVariable( + new org.intocps.maestro.framework.fmi2.RelationVariable<>(inputScalarVariable, + inputScalarVariable.getVariable().getName(), instanceLexIdentifier), instanceLexIdentifier); + dependantInputs.put(instanceLexIdentifier, inputVariable); + } + // TODO: Add relation from each input to the given output? + } + if (!dependantInputs.isEmpty()) { + Relation r = new Relation(); + r.source = outputVariable; + r.targets = dependantInputs; + r.direction = Relation.Direction.OutputToInput; + r.origin = Relation.InternalOrExternal.Internal; + instanceRelations.add(r); + } + + // externalInputTargets are the inputs that depend on the current output based on the provided connections. + List externalInputTargets = connections.stream() + .filter(conn -> conn.from.instance.equals(instance) && conn.from.variable.equals(outputScalarVariable.getVariable().getName())) + .map(conn -> conn.to).collect(Collectors.toList()); + if (!externalInputTargets.isEmpty()) { + // Log the current output as there is an input depending on it. + globalVariablesToLogForGivenInstance.add(outputVariable); + // externalInputs are all the external Inputs that depends on the current output + Map externalInputs = new HashMap<>(); + for (ModelConnection.Variable modelConnToVar : externalInputTargets) { + FrameworkUnitInfo frameworkUnitInfo = instanceNameToInstanceComponentInfo.get(modelConnToVar.instance.instanceName); + + if (frameworkUnitInfo instanceof InstanceInfo) { + + + Optional toScalarVariable = + ((InstanceInfo) frameworkUnitInfo).getModelDescription().getScalarVariables().stream() + .filter(sv -> sv.getVariable().getName().equals(modelConnToVar.variable)).findFirst(); + if (toScalarVariable.isPresent()) { + LexIdentifier inputInstanceLexIdentifier = new LexIdentifier(modelConnToVar.instance.instanceName, null); + RelationVariable inputVariable = getOrCreateVariable( + new org.intocps.maestro.framework.fmi2.RelationVariable<>(toScalarVariable.get(), + toScalarVariable.get().getVariable().getName(), inputInstanceLexIdentifier), inputInstanceLexIdentifier); externalInputs.put(inputInstanceLexIdentifier, inputVariable); //Add relation from the input to the given output @@ -433,13 +534,14 @@ private HashMap buildFmuKeyToFmuMD(Map fm return fmuKeyToFmuWithMD; } - Variable getOrCreateVariable(Fmi2ModelDescription.ScalarVariable inputScalarVariable, LexIdentifier instanceLexIdentifier) { - if (variables.containsKey(inputScalarVariable.name + instanceLexIdentifier)) { - return variables.get(inputScalarVariable.name + instanceLexIdentifier); + + RelationVariable getOrCreateVariable(RelationVariable relationVariable, LexIdentifier instanceLexIdentifier) { + if (variables.containsKey(relationVariable.getName() + instanceLexIdentifier)) { + return variables.get(relationVariable.getName() + instanceLexIdentifier); } else { - Variable variable = new Variable(new org.intocps.maestro.framework.fmi2.RelationVariable(inputScalarVariable, instanceLexIdentifier)); - variables.put(inputScalarVariable.name + instanceLexIdentifier, variable); - return variable; + // RelationVariable variable = new RelationVariable(relationVariable, relationVariable.getName(), instanceLexIdentifier); + variables.put(relationVariable.getName() + instanceLexIdentifier, relationVariable); + return relationVariable; } } @@ -523,10 +625,10 @@ public interface ModelDescriptionResolver extends BiFunction targets; + Map targets; @Override public InternalOrExternal getOrigin() { @@ -534,7 +636,7 @@ public InternalOrExternal getOrigin() { } @Override - public Variable getSource() { + public RelationVariable getSource() { return source; } @@ -544,7 +646,7 @@ public Direction getDirection() { } @Override - public Map getTargets() { + public Map getTargets() { return targets; } @@ -557,12 +659,12 @@ public String toString() { public static class RelationBuilder { - private final Variable source; - private final Map targets; + private final RelationVariable source; + private final Map targets; private InternalOrExternal origin = InternalOrExternal.External; private Direction direction = Direction.OutputToInput; - public RelationBuilder(Variable source, Map targets) { + public RelationBuilder(RelationVariable source, Map targets) { this.source = source; this.targets = targets; } @@ -588,27 +690,28 @@ public Relation build() { } } - public static class Variable implements IVariable { - public final org.intocps.maestro.framework.fmi2.RelationVariable scalarVariable; - - public Variable(org.intocps.maestro.framework.fmi2.RelationVariable scalarVariable) { - this.scalarVariable = scalarVariable; - } + // public static class Variable implements IVariable { + // public final org.intocps.maestro.framework.core.RelationVariable scalarVariable; + // + // public Variable(org.intocps.maestro.framework.core.RelationVariable scalarVariable) { + // this.scalarVariable = scalarVariable; + // } + // + // @Override + // public org.intocps.maestro.framework.core.RelationVariable getScalarVariable() { + // return scalarVariable; + // } + // + // T getFrameworkInfo(Framework framework) { + // return (T) scalarVariable; + // } + // + // @Override + // public String toString() { + // return scalarVariable.toString(); + // } + // } - @Override - public org.intocps.maestro.framework.fmi2.RelationVariable getScalarVariable() { - return scalarVariable; - } - - T getFrameworkInfo(Framework framework) { - return (T) scalarVariable; - } - - @Override - public String toString() { - return scalarVariable.toString(); - } - } public static class FileModelDescriptionResolver implements ModelDescriptionResolver { static XPath xPath = XPathFactory.newInstance().newXPath(); diff --git a/frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/InstanceInfo.java b/frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/InstanceInfo.java index e2527c4b9..57cbfcb9b 100644 --- a/frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/InstanceInfo.java +++ b/frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/InstanceInfo.java @@ -1,6 +1,6 @@ package org.intocps.maestro.framework.fmi2; -import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; +import org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; import org.intocps.maestro.framework.core.FaultInject; import org.intocps.maestro.framework.core.FrameworkUnitInfo; diff --git a/frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/RelationVariable.java b/frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/RelationVariable.java index d5724ca14..ce9f208ff 100644 --- a/frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/RelationVariable.java +++ b/frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/RelationVariable.java @@ -1,20 +1,46 @@ package org.intocps.maestro.framework.fmi2; import org.intocps.maestro.ast.LexIdentifier; +import org.intocps.maestro.ast.node.PExp; +import org.intocps.maestro.ast.node.PType; import org.intocps.maestro.fmi.Fmi2ModelDescription; +import org.intocps.maestro.fmi.fmi3.Fmi3Causality; +import org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; +import org.intocps.maestro.fmi.fmi3.Fmi3TypeEnum; +import java.util.Optional; -public class RelationVariable implements org.intocps.maestro.framework.core.RelationVariable { - public final Fmi2ModelDescription.ScalarVariable scalarVariable; +import static org.intocps.maestro.ast.MableAstFactory.*; + + +public class RelationVariable implements org.intocps.maestro.framework.core.RelationVariable { + private final SCALAR_TYPE scalarVariable; + final String name; // instance is necessary because: // If you look up the relations for FMU Component A, // and there is a dependency from FMU Component B Input as Source to FMU Component A as Target. // Then it is only possible to figure out that Source actually belongs to FMU Component B if instance is part of Source. public final LexIdentifier instance; + private final long valueReference; + private final Object type; - public RelationVariable(Fmi2ModelDescription.ScalarVariable scalarVariable, LexIdentifier instance) { + public RelationVariable(SCALAR_TYPE scalarVariable, String name, LexIdentifier instance, long valueReference, Type type) { this.scalarVariable = scalarVariable; + this.name = name; this.instance = instance; + this.valueReference = valueReference; + this.type = type; + } + + public RelationVariable(Fmi2ModelDescription.ScalarVariable scalarVariable, String name, LexIdentifier instance) { + this((SCALAR_TYPE) scalarVariable, name, instance, scalarVariable.getValueReference(), new RelationFmi2Type(scalarVariable.getType())); + + } + + public RelationVariable(Fmi3ModelDescription.Fmi3ScalarVariable scalarVariable, String name, LexIdentifier instance) { + this((SCALAR_TYPE) scalarVariable, name, instance, scalarVariable.getVariable().getValueReferenceAsLong(), + new RelationFmi3Type(scalarVariable.getVariable().getTypeIdentifier())); + } @Override @@ -24,7 +50,7 @@ public LexIdentifier getInstance() { @Override public String getName() { - return scalarVariable.getName(); + return name; } @Override @@ -35,8 +61,72 @@ public T getScalarVariable(Class clz) { return null; } - public Fmi2ModelDescription.ScalarVariable getScalarVariable() { - return getScalarVariable(this.scalarVariable.getClass()); + @Override + public boolean has(Object scalarAttributeType) { + if (scalarAttributeType instanceof Fmi2ModelDescription.Causality) { + return has((Fmi2ModelDescription.Causality) scalarAttributeType); + } else if (scalarAttributeType instanceof Fmi3Causality) { + return has((Fmi3Causality) scalarAttributeType); + } + return false; + } + + @Override + public Type getType() { + return (Type) type; + } + + public RelationFmi2Type getType2() { + if (this.type instanceof RelationFmi2Type) { + return (RelationFmi2Type) this.type; + } else if (this.type instanceof RelationFmi3Type) { + //todo convert if possible + } + return null; + } + + public RelationFmi3Type getType3() { + if (this.type instanceof RelationFmi2Type) { + //todo convert if possible + } else if (this.type instanceof RelationFmi3Type) { + return (RelationFmi3Type) this.type; + } + return null; + } + + // @Override + // public Type getType(Class clz) { + // + // if (type != null && clz.isAssignableFrom(type.get().getClass())) { + // return (Type) type; + // } + // return null; + // } + + @Override + public long getValueReference() { + return valueReference; + } + + public boolean has(Fmi2ModelDescription.Causality scalarAttributeType) { + return getFmi2ScalarVariable().map(s -> s.causality == scalarAttributeType).orElse(false); + } + + public boolean has(Fmi3Causality scalarAttributeType) { + return getFmi3ScalarVariable().map(s -> s.getVariable().getCausality() == scalarAttributeType).orElse(false); + } + + + public Optional getFmi2ScalarVariable() { + return Optional.of(getScalarVariable(Fmi2ModelDescription.ScalarVariable.class)); + } + + public Optional getFmi3ScalarVariable() { + return Optional.of(getScalarVariable(Fmi3ModelDescription.Fmi3ScalarVariable.class)); + } + + public SCALAR_TYPE getScalarVariable() { + return scalarVariable; } @Override @@ -56,4 +146,187 @@ public boolean equals(Object o) { RelationVariable rv = (RelationVariable) o; return rv.toString().equals(this.toString()); } + + public static class RelationFmi2Type implements org.intocps.maestro.framework.core.RelationVariable.Type { + + final Fmi2ModelDescription.Type type; + + public RelationFmi2Type(Fmi2ModelDescription.Type type) { + this.type = type; + } + + // @Override + // public T as(Class clz) { + // + // if (clz.isAssignableFrom(type.getClass())) { + // return (T) clz.cast(type); + // } + // + // return null; + // } + + @Override + public boolean hasType(Fmi2ModelDescription.Types type) { + return this.type.type == type; + } + + @Override + public Fmi2ModelDescription.Type get() { + return this.type; + } + + @Override + public PType getLexType() { + switch (this.type.type) { + case Boolean: + return newABoleanPrimitiveType(); + case Real: + return newARealNumericPrimitiveType(); + case Integer: + return newAIntNumericPrimitiveType(); + case String: + return newAStringPrimitiveType(); + default: + throw new UnsupportedOperationException("Converting fmi type: " + type + " to mabl type is not supported."); + } + } + + @Override + public PExp getLexDefaultValue() { + + + switch (this.type.type) { + + case Boolean: + return newABoolLiteralExp(false); + case Real: + return newARealLiteralExp(0.0); + case Integer: + case Enumeration: + return newAIntLiteralExp(0); + case String: + return newAStringLiteralExp(""); + + + } + throw new RuntimeException("Unknown type"); + } + + @Override + public boolean isAssignableFrom(Fmi2ModelDescription.Type other, boolean autoConvert) { + return this.type.isAssignableFrom(other, autoConvert); + } + } + + public static class RelationFmi3Type implements org.intocps.maestro.framework.core.RelationVariable.Type { + + final Fmi3TypeEnum type; + + public RelationFmi3Type(Fmi3TypeEnum type) { + this.type = type; + } + + // @Override + // public T as(Class clz) { + // + // if (clz.isAssignableFrom(type.getClass())) { + // return (T) clz.cast(type); + // } + // + // return null; + // } + + @Override + public boolean hasType(Fmi3TypeEnum type) { + return this.type == type; + } + + @Override + public Fmi3TypeEnum get() { + return this.type; + } + + @Override + public PType getLexType() { + switch (this.type) { + case Float32Type: + break; + case Float64Type: + break; + case Int8Type: + break; + case UInt8Type: + break; + case Int16Type: + break; + case UInt16Type: + break; + case Int32Type: + return newAIntNumericPrimitiveType(); + case UInt32Type: + break; + case Int64Type: + break; + case UInt64Type: + return newARealNumericPrimitiveType(); + case BooleanType: + return newABoleanPrimitiveType(); + case StringType: + return newAStringPrimitiveType(); + case BinaryType: + break; + case EnumerationType: + break; + case ClockType: + break; + default: + throw new UnsupportedOperationException("Converting fmi type: " + type + " to mabl type is not supported."); + } + return null; + } + + @Override + public PExp getLexDefaultValue() { + + switch (this.type) { + + case Float32Type: + break; + case Float64Type: + break; + case Int8Type: + break; + case UInt8Type: + break; + case Int16Type: + break; + case UInt16Type: + break; + case Int32Type: + return newAIntLiteralExp(0); + case UInt32Type: + break; + case Int64Type: + break; + case UInt64Type: + break; + case BooleanType: + return newABoolLiteralExp(false); + case StringType: + return newAStringLiteralExp(""); + case BinaryType: + break; + case EnumerationType: + break; + case ClockType: + break; + } + throw new RuntimeException("Unknown type"); + } + + @Override + public boolean isAssignableFrom(Fmi3TypeEnum other, boolean autoConvert) { + return this.type.equals(other); + } + } } diff --git a/frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/RelationVariable3.java b/frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/RelationVariable3.java index 680cfd003..dfddbb95f 100644 --- a/frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/RelationVariable3.java +++ b/frameworks/fmi2/src/main/java/org/intocps/maestro/framework/fmi2/RelationVariable3.java @@ -1,54 +1,54 @@ -package org.intocps.maestro.framework.fmi2; - -import org.intocps.maestro.ast.LexIdentifier; -import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; - -public class RelationVariable3 implements org.intocps.maestro.framework.core.RelationVariable { - public final Fmi3ModelDescription.Fmi3ScalarVariable scalarVariable; - public final LexIdentifier instance; - - public RelationVariable3(Fmi3ModelDescription.Fmi3ScalarVariable scalarVariable, LexIdentifier instance) { - this.scalarVariable = scalarVariable; - this.instance = instance; - } - - @Override - public LexIdentifier getInstance() { - return this.instance; - } - - @Override - public String getName() { - return scalarVariable.getVariable().getName(); - } - - @Override - public T getScalarVariable(Class clz) { - if (clz.isAssignableFrom(scalarVariable.getClass())) { - return clz.cast(scalarVariable); - } - return null; - } - - public Fmi3ModelDescription.Fmi3ScalarVariable getScalarVariable() { - return getScalarVariable(this.scalarVariable.getClass()); - } - - @Override - public String toString() { - return instance + "." + scalarVariable; - } - - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } - if (!(o instanceof RelationVariable)) { - return false; - } - - RelationVariable rv = (RelationVariable) o; - return rv.toString().equals(this.toString()); - } -} \ No newline at end of file +//package org.intocps.maestro.framework.fmi2; +// +//import org.intocps.maestro.ast.LexIdentifier; +//import org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; +// +//public class RelationVariable3 implements org.intocps.maestro.framework.core.RelationVariable { +// public final Fmi3ModelDescription.Fmi3ScalarVariable scalarVariable; +// public final LexIdentifier instance; +// +// public RelationVariable3(Fmi3ModelDescription.Fmi3ScalarVariable scalarVariable, LexIdentifier instance) { +// this.scalarVariable = scalarVariable; +// this.instance = instance; +// } +// +// @Override +// public LexIdentifier getInstance() { +// return this.instance; +// } +// +// @Override +// public String getName() { +// return scalarVariable.getVariable().getName(); +// } +// +// @Override +// public T getScalarVariable(Class clz) { +// if (clz.isAssignableFrom(scalarVariable.getClass())) { +// return clz.cast(scalarVariable); +// } +// return null; +// } +// +// public Fmi3ModelDescription.Fmi3ScalarVariable getScalarVariable() { +// return getScalarVariable(this.scalarVariable.getClass()); +// } +// +// @Override +// public String toString() { +// return instance + "." + scalarVariable; +// } +// +// @Override +// public boolean equals(Object o) { +// if (o == this) { +// return true; +// } +// if (!(o instanceof RelationVariable)) { +// return false; +// } +// +// RelationVariable rv = (RelationVariable) o; +// return rv.toString().equals(this.toString()); +// } +//} \ No newline at end of file diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/BuilderUtil.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/BuilderUtil.java index 40a3da138..3dc14248d 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/BuilderUtil.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/BuilderUtil.java @@ -1,9 +1,6 @@ package org.intocps.maestro.framework.fmi2.api.mabl; -import org.intocps.maestro.ast.node.PExp; -import org.intocps.maestro.ast.node.PStateDesignator; -import org.intocps.maestro.ast.node.PStm; -import org.intocps.maestro.ast.node.PType; +import org.intocps.maestro.ast.node.*; import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.variables.ComponentVariableFmi2Api; import org.intocps.maestro.framework.fmi2.api.mabl.variables.FmuVariableFmi2Api; @@ -32,7 +29,12 @@ public static List createTypeConvertingAssignment(PStateDesignator designa // String varName = builder.getNameGenerator().getName(); // statements.add(newVariable(varName, targetType)); - if (typeComparator.compatible(newBoleanType(), valueType) && (typeComparator.compatible(newRealType(), targetType)) || + if (typeComparator.compatible(newRealType(), valueType) && typeComparator.compatible(new AFloatNumericPrimitiveType(), targetType)) { + // real to float + + statements.add(newAAssignmentStm(designator, value)); + + } else if (typeComparator.compatible(newBoleanType(), valueType) && (typeComparator.compatible(newRealType(), targetType)) || typeComparator.compatible(newRealType(), targetType) || typeComparator.compatible(newRealType(), targetType)) { //bool to number PExp trueToken = newAIntLiteralExp(1); diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/FromMaBLToMaBLAPI.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/FromMaBLToMaBLAPI.java index 7031446d5..1c26f5040 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/FromMaBLToMaBLAPI.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/FromMaBLToMaBLAPI.java @@ -3,10 +3,13 @@ import org.intocps.maestro.ast.AVariableDeclaration; import org.intocps.maestro.ast.LexIdentifier; import org.intocps.maestro.ast.node.*; -import org.intocps.maestro.framework.core.*; +import org.intocps.maestro.framework.core.FrameworkUnitInfo; +import org.intocps.maestro.framework.core.IRelation; +import org.intocps.maestro.framework.core.ISimulationEnvironment; import org.intocps.maestro.framework.fmi2.ComponentInfo; import org.intocps.maestro.framework.fmi2.Fmi2SimulationEnvironment; import org.intocps.maestro.framework.fmi2.InstanceInfo; +import org.intocps.maestro.framework.fmi2.RelationVariable; import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.variables.ComponentVariableFmi2Api; import org.intocps.maestro.framework.fmi2.api.mabl.variables.FmuVariableFmi2Api; @@ -136,8 +139,8 @@ public static void createBindings(Map instance for (IRelation relation : relations.stream().filter(x -> x.getDirection() == Fmi2SimulationEnvironment.Relation.Direction.OutputToInput && x.getOrigin() == Fmi2SimulationEnvironment.Relation.InternalOrExternal.External).collect(Collectors.toList())) { - for (IVariable targetVar : relation.getTargets().values()) { - String targetName = targetVar.getScalarVariable().getInstance().getText(); + for (var targetVar : relation.getTargets().values()) { + String targetName = targetVar.getInstance().getText(); if (instances.containsKey(targetName) || instances.values().stream().anyMatch(x -> x.getEnvironmentName().equalsIgnoreCase(targetName))) { ComponentVariableFmi2Api instance = instances.get(targetName); @@ -149,9 +152,9 @@ public static void createBindings(Map instance } } - PortFmi2Api targetPort = instance.getPort(targetVar.getScalarVariable().getName()); + PortFmi2Api targetPort = instance.getPort(targetVar.getName()); - String sourcePortName = relation.getSource().getScalarVariable().getName(); + String sourcePortName = relation.getSource().getName(); if (targetPort != null) { entry.getValue().getPort(sourcePortName).linkTo(targetPort); } else { @@ -177,8 +180,8 @@ public static void createBindings3(Map instance for (IRelation relation : relations.stream().filter(x -> x.getDirection() == Fmi2SimulationEnvironment.Relation.Direction.OutputToInput && x.getOrigin() == Fmi2SimulationEnvironment.Relation.InternalOrExternal.External).collect(Collectors.toList())) { - for (IVariable targetVar : relation.getTargets().values()) { - String targetName = targetVar.getScalarVariable().getInstance().getText(); + for (var targetVar : relation.getTargets().values()) { + String targetName = targetVar.getInstance().getText(); if (instances.containsKey(targetName) || instances.values().stream().anyMatch(x -> x.getEnvironmentName().equalsIgnoreCase(targetName))) { InstanceVariableFmi3Api instance = instances.get(targetName); @@ -190,9 +193,9 @@ public static void createBindings3(Map instance } } - PortFmi3Api targetPort = instance.getPort(targetVar.getScalarVariable().getName()); + PortFmi3Api targetPort = instance.getPort(targetVar.getName()); - String sourcePortName = relation.getSource().getScalarVariable().getName(); + String sourcePortName = relation.getSource().getName(); if (targetPort != null) { entry.getValue().getPort(sourcePortName).linkTo(targetPort); } else { diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/ModelDescriptionContext.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/ModelDescriptionContext.java index b926d197f..408506ef1 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/ModelDescriptionContext.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/ModelDescriptionContext.java @@ -1,7 +1,6 @@ package org.intocps.maestro.framework.fmi2.api.mabl; import org.intocps.maestro.fmi.Fmi2ModelDescription; -import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; import javax.xml.xpath.XPathExpressionException; import java.lang.reflect.InvocationTargetException; @@ -13,6 +12,7 @@ public class ModelDescriptionContext { private final Fmi2ModelDescription modelDescription; public Map nameToSv = new HashMap<>(); public Map valRefToSv = new HashMap<>(); + public ModelDescriptionContext( Fmi2ModelDescription modelDescription) throws IllegalAccessException, XPathExpressionException, InvocationTargetException { this.modelDescription = modelDescription; @@ -21,6 +21,7 @@ public ModelDescriptionContext( this.valRefToSv.put(sv.valueReference, sv); }); } + public Fmi2ModelDescription getModelDescription() { return modelDescription; } diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/ModelDescriptionContext3.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/ModelDescriptionContext3.java index 3c9e75125..2c3142672 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/ModelDescriptionContext3.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/ModelDescriptionContext3.java @@ -1,7 +1,6 @@ package org.intocps.maestro.framework.fmi2.api.mabl; -import kotlin.UInt; -import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; +import org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; import javax.xml.xpath.XPathExpressionException; import java.lang.reflect.InvocationTargetException; @@ -13,6 +12,7 @@ public class ModelDescriptionContext3 { private final Fmi3ModelDescription modelDescription; public Map nameToSv = new HashMap<>(); public Map valRefToSv = new HashMap<>(); + public ModelDescriptionContext3( Fmi3ModelDescription modelDescription) throws IllegalAccessException, XPathExpressionException, InvocationTargetException { this.modelDescription = modelDescription; @@ -21,6 +21,7 @@ public ModelDescriptionContext3( this.valRefToSv.put((long) sv.getVariable().getValueReferenceAsLong(), sv); }); } + public Fmi3ModelDescription getModelDescription() { return modelDescription; } diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/PortFmi2Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/PortFmi2Api.java index 0d8390752..6445411c2 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/PortFmi2Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/PortFmi2Api.java @@ -1,5 +1,6 @@ package org.intocps.maestro.framework.fmi2.api.mabl; +import org.intocps.maestro.ast.node.PStm; import org.intocps.maestro.ast.node.PType; import org.intocps.maestro.fmi.Fmi2ModelDescription; import org.intocps.maestro.framework.fmi2.api.FmiBuilder; @@ -11,7 +12,7 @@ import static org.intocps.maestro.ast.MableAstFactory.*; -public class PortFmi2Api implements FmiBuilder.Port { +public class PortFmi2Api implements FmiBuilder.Port { public final ComponentVariableFmi2Api aMablFmi2ComponentAPI; public final Fmi2ModelDescription.ScalarVariable scalarVariable; @@ -61,6 +62,11 @@ public String getQualifiedName() { this.getName(); } + @Override + public FmiBuilder.FmiSimulationInstance getOwner() { + return this.aMablFmi2ComponentAPI; + } + @Override public Fmi2ModelDescription.ScalarVariable getSourceObject() { return this.scalarVariable; @@ -78,7 +84,7 @@ public Long getPortReferenceValue() { @Override - public void linkTo(FmiBuilder.Port... receivers) throws PortLinkException { + public void linkTo(FmiBuilder.Port... receivers) throws PortLinkException { if (receivers == null || receivers.length == 0) { return; @@ -88,7 +94,7 @@ public void linkTo(FmiBuilder.Port... recei throw new PortLinkException("Can only link output ports. This port is: " + this.scalarVariable.causality, this); } - for (FmiBuilder.Port receiver : receivers) { + for (FmiBuilder.Port receiver : receivers) { PortFmi2Api receiverPort = (PortFmi2Api) receiver; if (receiverPort.scalarVariable.causality != Fmi2ModelDescription.Causality.Input) { diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/PortFmi3Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/PortFmi3Api.java index 303838f7b..94f8e32d2 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/PortFmi3Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/PortFmi3Api.java @@ -1,8 +1,8 @@ package org.intocps.maestro.framework.fmi2.api.mabl; -import org.intocps.maestro.ast.node.PType; -import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3Causality; -import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; +import org.intocps.maestro.ast.node.*; +import org.intocps.maestro.fmi.fmi3.Fmi3Causality; +import org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.variables.InstanceVariableFmi3Api; import org.intocps.maestro.framework.fmi2.api.mabl.variables.VariableFmi2Api; @@ -10,7 +10,9 @@ import java.util.ArrayList; import java.util.List; -public class PortFmi3Api implements FmiBuilder.Port { +import static org.intocps.maestro.ast.MableAstFactory.*; + +public class PortFmi3Api implements FmiBuilder.Port { public final InstanceVariableFmi3Api aMablFmi3InstanceAPI; public final Fmi3ModelDescription.Fmi3ScalarVariable scalarVariable; @@ -42,15 +44,55 @@ public void setSharedAsVariable(VariableFmi2Api sharedAsVariable) { public PType getType() { switch (scalarVariable.getVariable().getTypeIdentifier()) { - // case Boolean: - // return newBoleanType(); - // case Real: - // return newRealType(); - // case Integer: - // return newIntType(); - // case String: - // return newStringType(); - // case Enumeration: + + + // case Boolean: + // return newBoleanType(); + // case Real: + // return newRealType(); + // case Integer: + // return newIntType(); + // case String: + // return newStringType(); + // case Enumeration: + /*#primitive + = {boolean} + | {string} + | #numeric + ; + +#numeric + = {real} + | {int} + | {uInt} + | {float} + | {short} + | {byte} + | {long}*/ + case Float64Type: + return new ARealNumericPrimitiveType(); + case Float32Type: + case ClockType: + return new AFloatNumericPrimitiveType(); + case Int8Type: + return new AShortNumericPrimitiveType(); + case UInt8Type: + case Int16Type: + case UInt16Type: + case Int32Type: + return newIntType(); + case UInt32Type: + case Int64Type: + case UInt64Type: + new ALongNumericPrimitiveType(); + case BooleanType: + return newBoleanType(); + case StringType: + return newStringType(); + case BinaryType: + return null; + case EnumerationType: + new ALongNumericPrimitiveType(); default: return null; } @@ -61,6 +103,11 @@ public String getQualifiedName() { return this.aMablFmi3InstanceAPI.getOwner().getFmuIdentifier() + "." + this.aMablFmi3InstanceAPI.getEnvironmentName() + "." + this.getName(); } + @Override + public FmiBuilder.FmiSimulationInstance getOwner() { + return this.aMablFmi3InstanceAPI; + } + @Override public Fmi3ModelDescription.Fmi3ScalarVariable getSourceObject() { return this.scalarVariable; @@ -78,7 +125,7 @@ public Long getPortReferenceValue() { @Override - public void linkTo(FmiBuilder.Port... receivers) throws PortLinkException { + public void linkTo(FmiBuilder.Port... receivers) throws PortLinkException { if (receivers == null || receivers.length == 0) { return; diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/DynamicActiveBuilderScope.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/DynamicActiveBuilderScope.java index 98b9b52e0..ebcd344fe 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/DynamicActiveBuilderScope.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/DynamicActiveBuilderScope.java @@ -2,7 +2,7 @@ import org.intocps.maestro.ast.node.PStm; import org.intocps.maestro.fmi.Fmi2ModelDescription; -import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; +import org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.variables.*; diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/IMablScope.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/IMablScope.java index 93c2b9069..29b0186af 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/IMablScope.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/IMablScope.java @@ -2,7 +2,7 @@ import org.intocps.maestro.ast.node.PStm; import org.intocps.maestro.fmi.Fmi2ModelDescription; -import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; +import org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.variables.*; diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/ScopeFmi2Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/ScopeFmi2Api.java index ac2608d99..294fb1680 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/ScopeFmi2Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/ScopeFmi2Api.java @@ -5,7 +5,8 @@ import org.intocps.maestro.ast.MableAstFactory; import org.intocps.maestro.ast.node.*; import org.intocps.maestro.fmi.Fmi2ModelDescription; -import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; + +import org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.MablApiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.PredicateFmi2Api; diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/PortValueExpresssionMapImpl.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/PortValueExpresssionMapImpl.java index 52c02e5c5..889089e02 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/PortValueExpresssionMapImpl.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/PortValueExpresssionMapImpl.java @@ -1,11 +1,12 @@ package org.intocps.maestro.framework.fmi2.api.mabl.values; +import org.intocps.maestro.ast.node.PStm; import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import java.util.HashMap; import java.util.Map; -public class PortValueExpresssionMapImpl extends HashMap, FmiBuilder.ExpressionValue> implements FmiBuilder.Fmi2ComponentVariable.PortExpressionValueMap { +public class PortValueExpresssionMapImpl extends HashMap, FmiBuilder.ExpressionValue> implements FmiBuilder.Fmi2ComponentVariable.PortExpressionValueMap { public PortValueExpresssionMapImpl(int initialCapacity, float loadFactor) { super(initialCapacity, loadFactor); } @@ -17,7 +18,7 @@ public PortValueExpresssionMapImpl(int initialCapacity) { public PortValueExpresssionMapImpl() { } - public PortValueExpresssionMapImpl(Map, ? extends FmiBuilder.ExpressionValue> m) { + public PortValueExpresssionMapImpl(Map, ? extends FmiBuilder.ExpressionValue> m) { super(m); } } diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/PortValueMapImpl.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/PortValueMapImpl.java index 0a6171ac6..58342628f 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/PortValueMapImpl.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/PortValueMapImpl.java @@ -1,11 +1,12 @@ package org.intocps.maestro.framework.fmi2.api.mabl.values; +import org.intocps.maestro.ast.node.PStm; import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import java.util.HashMap; import java.util.Map; -public class PortValueMapImpl extends HashMap, FmiBuilder.Value> implements FmiBuilder.Fmi2ComponentVariable.PortValueMap { +public class PortValueMapImpl extends HashMap, FmiBuilder.Value> implements FmiBuilder.Fmi2ComponentVariable.PortValueMap { public PortValueMapImpl(int initialCapacity, float loadFactor) { super(initialCapacity, loadFactor); } @@ -17,7 +18,7 @@ public PortValueMapImpl(int initialCapacity) { public PortValueMapImpl() { } - public PortValueMapImpl(Map, ? extends FmiBuilder.Value> m) { + public PortValueMapImpl(Map, ? extends FmiBuilder.Value> m) { super(m); } } diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/ComponentVariableFmi2Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/ComponentVariableFmi2Api.java index cf6c395c1..339ffa2b6 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/ComponentVariableFmi2Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/ComponentVariableFmi2Api.java @@ -98,13 +98,13 @@ public List getVariablesToLog() { return this.getPorts(this.variabesToLog.toArray(new String[0])); } - public void setVariablesToLog(List variablesToLog) { + public void setVariablesToLog(List variablesToLog) { this.variabesToLog = variablesToLog.stream().map(RelationVariable::getName).collect(Collectors.toList()); } @Override - public void share(FmiBuilder.Port port, FmiBuilder.Variable value) { - Map, FmiBuilder.Variable> map = new HashMap<>(); + public void share(FmiBuilder.Port port, FmiBuilder.Variable value) { + Map, FmiBuilder.Variable> map = new HashMap<>(); map.put(port, value); share(map); } @@ -474,12 +474,13 @@ public Map> getTentative(IMablScope scope, S } @Override - public Map> get(FmiBuilder.Port... ports) { + public Map> get(FmiBuilder.Port... ports) { return get(builder.getDynamicScope().getActiveScope(), ports); } @Override - public Map> get(FmiBuilder.Scope scope, FmiBuilder.Port... ports) { + public Map> get(FmiBuilder.Scope scope, + FmiBuilder.Port... ports) { List selectedPorts; if (ports == null || ports.length == 0) { @@ -664,15 +665,15 @@ public Map> getAndShare(String... names) { } @Override - public Map, ? extends FmiBuilder.Variable> getAndShare( - FmiBuilder.Port... ports) { + public Map, ? extends FmiBuilder.Variable> getAndShare( + FmiBuilder.Port... ports) { Map> values = get(ports); share(values); return values; } @Override - public Map, ? extends FmiBuilder.Variable> getAndShare() { + public Map, ? extends FmiBuilder.Variable> getAndShare() { Map> values = get(); share(values); return values; @@ -689,7 +690,7 @@ public VariableFmi2Api getShared(FmiBuilder.Port port) { } @Override - public VariableFmi2Api getSingle(FmiBuilder.Port port) { + public VariableFmi2Api getSingle(FmiBuilder.Port port) { return (VariableFmi2Api) this.get(port).entrySet().iterator().next().getValue(); } @@ -751,7 +752,7 @@ public void set(PortExpressionValueMap value) { this.set(builder.getDynamicScope().getActiveScope(), value); } - public void set(FmiBuilder.Scope scope, PortExpressionValueMap value) { + public void set(FmiBuilder.Scope scope, PortExpressionValueMap value) { if (value == null || value.isEmpty()) { return; } @@ -765,7 +766,7 @@ public void set(FmiBuilder.Scope scope, PortExpressionValueMap void set(FmiBuilder.Scope scope, PortValueMap value) { + public void set(FmiBuilder.Scope scope, PortValueMap value) { if (value == null || value.isEmpty()) { @@ -797,7 +798,7 @@ public void set(FmiBuilder.Scope scope, PortValueMap void set(FmiBuilder.Scope scope, PortVariableMap value) { + public void set(FmiBuilder.Scope scope, PortVariableMap value) { List selectedPorts; if (value == null || value.isEmpty()) { @@ -962,17 +963,18 @@ public void setDerivatives(ArrayVariableFmi2Api derValInBuf, ArrayVariableFmi2Ap } @Override - public void set(PortValueMap value) { + public void set(PortValueMap value) { set(builder.getDynamicScope(), value); } @Override - public void set(FmiBuilder.Port port, FmiBuilder.Variable value) { + public void set(FmiBuilder.Port port, FmiBuilder.Variable value) { this.set(new PortVariableMapImpl(Map.of(port, value))); } @Override - public void set(FmiBuilder.Scope scope, FmiBuilder.Port port, FmiBuilder.Variable value) { + public void set(FmiBuilder.Scope scope, FmiBuilder.Port port, + FmiBuilder.Variable value) { this.set(scope, new PortVariableMapImpl(Map.of(port, value))); } @@ -986,12 +988,12 @@ public void set(FmiBuilder.Port port, FmiBuilder.Value value) { @Override - public void set(PortVariableMap value) { + public void set(PortVariableMap value) { set(builder.getDynamicScope(), value); } @Override - public void setLinked(FmiBuilder.Scope scope, FmiBuilder.Port... filterPorts) { + public void setLinked(FmiBuilder.Scope scope, FmiBuilder.Port... filterPorts) { List selectedPorts = ports.stream().filter(isLinked).collect(Collectors.toList()); if (filterPorts != null && filterPorts.length != 0) { @@ -1081,7 +1083,7 @@ public void terminate(FmiBuilder.Scope scope) { } @Override - public void share(Map, ? extends FmiBuilder.Variable> values) { + public void share(Map, ? extends FmiBuilder.Variable> values) { // Group by the string value of the port type as grouping by the port type itself doesnt utilise equals values.entrySet().stream().collect(Collectors.groupingBy(map -> ((PortFmi2Api) map.getKey()).getType().toString())).entrySet().stream() .forEach(map -> { diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/InstanceVariableFmi3Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/InstanceVariableFmi3Api.java index f040c2b06..11a46967a 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/InstanceVariableFmi3Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/InstanceVariableFmi3Api.java @@ -6,9 +6,9 @@ import org.intocps.maestro.ast.analysis.AnalysisException; import org.intocps.maestro.ast.analysis.DepthFirstAnalysisAdaptor; import org.intocps.maestro.ast.node.*; -import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3Causality; -import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; -import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3TypeEnum; +import org.intocps.maestro.fmi.fmi3.Fmi3Causality; +import org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; +import org.intocps.maestro.fmi.fmi3.Fmi3TypeEnum; import org.intocps.maestro.framework.fmi2.RelationVariable; import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.*; @@ -94,12 +94,12 @@ public List getVariablesToLog() { } public void setVariablesToLog(List variablesToLog) { - this.variabesToLog = variablesToLog.stream().map(x -> x.scalarVariable.getName()).collect(Collectors.toList()); + this.variabesToLog = variablesToLog.stream().map(x -> x.getName()).collect(Collectors.toList()); } @Override - public void share(FmiBuilder.Port port, FmiBuilder.Variable value) { - Map, FmiBuilder.Variable> map = new HashMap<>(); + public void share(FmiBuilder.Port port, FmiBuilder.Variable value) { + Map, FmiBuilder.Variable> map = new HashMap<>(); map.put(port, value); share(map); } @@ -487,14 +487,14 @@ public Map> getTentative(IMablScope scope, S } @Override - public Map> get(FmiBuilder.Port... ports) { + public Map> get(FmiBuilder.Port... ports) { return get(builder.getDynamicScope().getActiveScope(), ports); } @SuppressWarnings("unchecked") @Override public Map> get(FmiBuilder.Scope scope, - FmiBuilder.Port... ports) { + FmiBuilder.Port... ports) { List selectedPorts; if (ports == null || ports.length == 0) { @@ -700,15 +700,15 @@ public Map> getAndShare(String... names) { } @Override - public Map, ? extends FmiBuilder.Variable> getAndShare( - FmiBuilder.Port... ports) { + public Map, ? extends FmiBuilder.Variable> getAndShare( + FmiBuilder.Port... ports) { Map> values = get(ports); share(values); return values; } @Override - public Map, ? extends FmiBuilder.Variable> getAndShare() { + public Map, ? extends FmiBuilder.Variable> getAndShare() { Map> values = get(); share(values); return values; @@ -728,7 +728,7 @@ public VariableFmi2Api getShared(FmiBuilder.Port port) { @SuppressWarnings("unchecked") @Override - public VariableFmi2Api getSingle(FmiBuilder.Port port) { + public VariableFmi2Api getSingle(FmiBuilder.Port port) { return (VariableFmi2Api) this.get(port).entrySet().iterator().next().getValue(); } @@ -748,7 +748,7 @@ private String createFunctionName(FmiFunctionType f, Fmi3TypeEnum type) { default: throw new RuntimeException("Attempting to call non type-dependant function with type: " + type); } - functionName += type.name(); + functionName += type.name().substring(0, type.name().length() - "Type".length()); return functionName; } @@ -764,7 +764,7 @@ public void set(FmiBuilder.Port p, FmiBuilder.ExpressionValue v) { } @SuppressWarnings("unchecked") - public void set(FmiBuilder.Scope scope, FmiBuilder.Port p, FmiBuilder.ExpressionValue v) { + public void set(FmiBuilder.Scope scope, FmiBuilder.Port p, FmiBuilder.ExpressionValue v) { this.set(scope, new PortValueMapImpl(Map.of(p, v))); } @@ -772,7 +772,7 @@ public void set(PortExpressionValueMap value) { this.set(builder.getDynamicScope().getActiveScope(), value); } - public void set(FmiBuilder.Scope scope, PortExpressionValueMap value) { + public void set(FmiBuilder.Scope scope, PortExpressionValueMap value) { if (value == null || value.isEmpty()) { return; } @@ -786,7 +786,7 @@ public void set(FmiBuilder.Scope scope, PortExpressionValueMap void set(FmiBuilder.Scope scope, PortValueMap value) { + public void set(FmiBuilder.Scope scope, PortValueMap value) { if (value == null || value.isEmpty()) { @@ -819,7 +819,7 @@ public void set(FmiBuilder.Scope scope, PortValueMap void set(FmiBuilder.Scope scope, PortVariableMap value) { + public void set(FmiBuilder.Scope scope, PortVariableMap value) { List selectedPorts; if (value == null || value.isEmpty()) { @@ -869,7 +869,7 @@ public void set(FmiBuilder.Scope scope, List selectedPorts, F AAssigmentStm stm = newAAssignmentStm(((IMablScope) scope).getFmiStatusVariable().getDesignator().clone(), call(this.getReferenceExp().clone(), createFunctionName(FmiFunctionType.SET, value.get(0)), vrefBuf.getReferenceExp().clone(), - newAUIntLiteralExp((long) value.size()), valBuf.getReferenceExp().clone())); + newAIntLiteralExp(value.size()), valBuf.getReferenceExp().clone(), newAIntLiteralExp(value.size()))); scope.add(stm); handleError(scope, createFunctionName(FmiFunctionType.SET, sortedPorts.get(0))); @@ -978,39 +978,39 @@ public void setDerivatives(ArrayVariableFmi2Api derValInBuf, ArrayVariableFmi2Ap } @Override - public void set(PortValueMap value) { + public void set(PortValueMap value) { set(builder.getDynamicScope(), value); } @SuppressWarnings("unchecked") @Override - public void set(FmiBuilder.Port port, FmiBuilder.Variable value) { + public void set(FmiBuilder.Port port, FmiBuilder.Variable value) { this.set(new PortVariableMapImpl(Map.of(port, value))); } @SuppressWarnings("unchecked") @Override - public void set(FmiBuilder.Scope scope, FmiBuilder.Port port, + public void set(FmiBuilder.Scope scope, FmiBuilder.Port port, FmiBuilder.Variable value) { this.set(scope, new PortVariableMapImpl(Map.of(port, value))); } @SuppressWarnings("unchecked") @Override - public void set(FmiBuilder.Port port, FmiBuilder.Value value) { + public void set(FmiBuilder.Port port, FmiBuilder.Value value) { PortValueMap map = new PortValueMapImpl(); map.put(port, value); set(map); } @Override - public void set(PortVariableMap value) { + public void set(PortVariableMap value) { set(builder.getDynamicScope(), value); } @SuppressWarnings("unchecked") @Override - public void setLinked(FmiBuilder.Scope scope, FmiBuilder.Port... filterPorts) { + public void setLinked(FmiBuilder.Scope scope, FmiBuilder.Port... filterPorts) { List selectedPorts = ports.stream().filter(isLinked).collect(Collectors.toList()); if (filterPorts != null && filterPorts.length != 0) { @@ -1051,7 +1051,7 @@ public void setLinked(FmiBuilder.Scope scope, FmiBuilder.Port[]) null); + this.setLinked(dynamicScope, (FmiBuilder.Port[]) null); } @SuppressWarnings("unchecked") @@ -1115,75 +1115,72 @@ public void freeInstance(FmiBuilder.Scope scope) { // TODO: implement this from the other share function below. This for now to build. - @Override - public void share(Map, ? extends FmiBuilder.Variable> values) { - ; - } - // @Override - // public void share(Map> values) { - // // Group by the string value of the port type as grouping by the port type itself doesnt utilise equals - // values.entrySet().stream().collect(Collectors.groupingBy(map -> ((PortFmi3Api) map.getKey()).getType().toString())).entrySet().stream() - // .forEach(map -> { - // PType type = ((PortFmi3Api) map.getValue().get(0).getKey()).getType(); - // - // Map data = - // map.getValue().stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - // - // data.keySet().stream().map(PortFmi3Api.class::cast).sorted(Comparator.comparing(PortFmi3Api::getPortReferenceValue)) - // .forEach(port -> { - // //this is the sorted set of assignments, these can be replaced by a memcopy later - // ArrayVariableFmi2Api buffer = getSharedBuffer(type); - // if (port.getSharedAsVariable() == null) { - // ArrayVariableFmi2Api newBuf = growBuffer(buffer, 1); - // this.setSharedBuffer(newBuf, type); - // - // VariableFmi2Api newShared = newBuf.items().get(newBuf.items().size() - 1); - // port.setSharedAsVariable(newShared); - // } - // - // PStateDesignator designator = port.getSharedAsVariable().getDesignator(); - // builder.getDynamicScope().addAll(BuilderUtil.createTypeConvertingAssignment(builder, dynamicScope, designator.clone(), - // ((VariableFmi2Api) data.get(port)).getReferenceExp().clone(), port.getType(), - // ((VariableFmi2Api) ((VariableFmi2Api) data.get(port))).type)); - // - // - // if (type.equals(new ARealNumericPrimitiveType()) && derivativePortsToShare != null) { - // // Find match a derivativePortsToShare where both port reference and derivative port reference matches. - // derivativePortsToShare.keySet().stream().filter(derivativePort -> { - // try { - // return modelDescriptionContext.getModelDescription().getDerivativesMap().entrySet().stream().anyMatch( - // e -> e.getKey().getValueReference().equals(port.getPortReferenceValue()) && - // e.getValue().getValueReference().equals(derivativePort.getPortReferenceValue())); - // } catch (XPathExpressionException | InvocationTargetException | IllegalAccessException e) { - // throw new RuntimeException( - // "Attempting to obtain shared values from a port that is linked but has no value shared. Share a value " + - // "first. " + port); - // } - // }).findFirst().ifPresent((derivativePort) -> { - // // If the derivative port is not yet shared then get shared derivative buffer, grow it by one and set the port as shared - // // with the new array. - // if (derivativePort.getSharedAsVariable() == null) { - // ArrayVariableFmi2Api sharedDerBuf = growSharedDerBuf(1); - // - // ArrayVariableFmi2Api newSharedArray = - // (ArrayVariableFmi2Api) sharedDerBuf.items().get(sharedDerBuf.items().size() - 1); - // derivativePort.setSharedAsVariable(newSharedArray); - // } - // - // // DerivativePorts.get(derivativePort).size should equal derivativePort.getSharedAsVariable().items().size() as they are - // // both determined by the max derivative order. - // List derivatives = ((ArrayVariableFmi2Api) derivativePort.getSharedAsVariable()).items(); - // for (int i = 0; i < derivatives.size(); i++) { - // PExp val = derivativePortsToShare.get(derivativePort).get(i).getReferenceExp().clone(); - // builder.getDynamicScope().add(newAAssignmentStm(derivatives.get(i).getDesignator().clone(), val)); - // } - // }); - // } - // }); - // }); + // public void share( + // Map, ? extends FmiBuilder.Variable> values) { + // ; // } + @Override + public void share( + Map, ? extends FmiBuilder.Variable> values) { + // Group by the string value of the port type as grouping by the port type itself doesnt utilise equals + values.entrySet().stream().collect(Collectors.groupingBy(map -> ((PortFmi3Api) map.getKey()).getType().toString())).entrySet().stream() + .forEach(map -> { + PType type = ((PortFmi3Api) map.getValue().get(0).getKey()).getType(); + + Map, FmiBuilder.Variable> data = + map.getValue().stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + + data.keySet().stream().map(PortFmi3Api.class::cast).sorted(Comparator.comparing(PortFmi3Api::getPortReferenceValue)) + .forEach(port -> { + //this is the sorted set of assignments, these can be replaced by a memcopy later + ArrayVariableFmi2Api buffer = getSharedBuffer(type); + if (port.getSharedAsVariable() == null) { + ArrayVariableFmi2Api newBuf = growBuffer(buffer, 1); + this.setSharedBuffer(newBuf, type); + + VariableFmi2Api newShared = newBuf.items().get(newBuf.items().size() - 1); + port.setSharedAsVariable(newShared); + } + + PStateDesignator designator = port.getSharedAsVariable().getDesignator(); + builder.getDynamicScope().addAll(BuilderUtil.createTypeConvertingAssignment(builder, dynamicScope, designator.clone(), + ((VariableFmi2Api) data.get(port)).getReferenceExp().clone(), port.getType(), + ((VariableFmi2Api) ((VariableFmi2Api) data.get(port))).type)); + + + if (type.equals(new ARealNumericPrimitiveType()) && derivativePortsToShare != null) { + // Find match a derivativePortsToShare where both port reference and derivative port reference matches. + derivativePortsToShare.keySet().stream().filter(derivativePort -> { + return modelDescriptionContext.getModelDescription().getDerivatives().stream() + .map(v -> v.getVariable().getValueReferenceAsLong()).anyMatch( + vref -> vref.equals(port.getPortReferenceValue()) && + vref.equals(derivativePort.getPortReferenceValue())); + }).findFirst().ifPresent((derivativePort) -> { + // If the derivative port is not yet shared then get shared derivative buffer, grow it by one and set the port as shared + // with the new array. + if (derivativePort.getSharedAsVariable() == null) { + ArrayVariableFmi2Api sharedDerBuf = growSharedDerBuf(1); + + ArrayVariableFmi2Api newSharedArray = + (ArrayVariableFmi2Api) sharedDerBuf.items().get(sharedDerBuf.items().size() - 1); + derivativePort.setSharedAsVariable(newSharedArray); + } + + // DerivativePorts.get(derivativePort).size should equal derivativePort.getSharedAsVariable().items().size() as they are + // both determined by the max derivative order. + List derivatives = ((ArrayVariableFmi2Api) derivativePort.getSharedAsVariable()).items(); + for (int i = 0; i < derivatives.size(); i++) { + PExp val = derivativePortsToShare.get(derivativePort).get(i).getReferenceExp().clone(); + builder.getDynamicScope().add(newAAssignmentStm(derivatives.get(i).getDesignator().clone(), val)); + } + }); + } + }); + }); + } + /** * @param increaseByCount the length of which the outer array should grow * @return a two dimensional non-jagged array for derivatives. diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/PortVariableMapImpl.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/PortVariableMapImpl.java index dec8237c8..942d01c9b 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/PortVariableMapImpl.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/PortVariableMapImpl.java @@ -6,7 +6,7 @@ import java.util.HashMap; import java.util.Map; -public class PortVariableMapImpl extends HashMap, FmiBuilder.Variable> implements FmiBuilder.FmiSimulationInstance.PortVariableMap { +public class PortVariableMapImpl extends HashMap, FmiBuilder.Variable> implements FmiBuilder.FmiSimulationInstance.PortVariableMap { public PortVariableMapImpl(int initialCapacity, float loadFactor) { super(initialCapacity, loadFactor); } @@ -18,7 +18,7 @@ public PortVariableMapImpl(int initialCapacity) { public PortVariableMapImpl() { } - public PortVariableMapImpl(Map, ? extends FmiBuilder.Variable> m) { + public PortVariableMapImpl(Map, ? extends FmiBuilder.Variable> m) { super(m); } } diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/VariableCreatorFmi3Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/VariableCreatorFmi3Api.java index 154b44e1c..a3efc7179 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/VariableCreatorFmi3Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/VariableCreatorFmi3Api.java @@ -7,9 +7,12 @@ import org.intocps.maestro.ast.node.PStm; import org.intocps.maestro.ast.node.PType; import org.intocps.maestro.fmi.Fmi2ModelDescription; -import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; +import org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; import org.intocps.maestro.framework.fmi2.FmuFactory; -import org.intocps.maestro.framework.fmi2.api.mabl.*; +import org.intocps.maestro.framework.fmi2.api.mabl.MablApiBuilder; +import org.intocps.maestro.framework.fmi2.api.mabl.ModelDescriptionContext3; +import org.intocps.maestro.framework.fmi2.api.mabl.PredicateFmi2Api; +import org.intocps.maestro.framework.fmi2.api.mabl.TagNameGenerator; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.DynamicActiveBuilderScope; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.IMablScope; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.ScopeFmi2Api; diff --git a/frameworks/fmi2api/src/test/java/org/intocps/maestro/framework/fmi2/api/mabl/SetPortsTest.java b/frameworks/fmi2api/src/test/java/org/intocps/maestro/framework/fmi2/api/mabl/SetPortsTest.java index 2651f7f30..b82ef8aee 100644 --- a/frameworks/fmi2api/src/test/java/org/intocps/maestro/framework/fmi2/api/mabl/SetPortsTest.java +++ b/frameworks/fmi2api/src/test/java/org/intocps/maestro/framework/fmi2/api/mabl/SetPortsTest.java @@ -1,5 +1,6 @@ package org.intocps.maestro.framework.fmi2.api.mabl; +import org.intocps.maestro.ast.node.PStm; import org.intocps.maestro.fmi.Fmi2ModelDescription; import org.intocps.maestro.framework.fmi2.api.FmiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.DynamicActiveBuilderScope; @@ -37,7 +38,7 @@ public void undeclaredPortsTest() throws Exception { controllerInstance.get(controllerInstance.getPorts().stream().map(PortFmi2Api::getName).toArray(String[]::new)); controllerInstance.share(controllerPortMap); - FmiBuilder.Fmi2ComponentVariable.PortValueMap portsToSet = + FmiBuilder.Fmi2ComponentVariable.PortValueMap portsToSet = new PortValueMapImpl(controllerPortMap); // ASSERT diff --git a/maestro-webapi/src/main/java/org/intocps/maestro/webapi/maestro2/Maestro2Broker.java b/maestro-webapi/src/main/java/org/intocps/maestro/webapi/maestro2/Maestro2Broker.java index 9c111ae6e..55ef8500a 100644 --- a/maestro-webapi/src/main/java/org/intocps/maestro/webapi/maestro2/Maestro2Broker.java +++ b/maestro-webapi/src/main/java/org/intocps/maestro/webapi/maestro2/Maestro2Broker.java @@ -55,8 +55,9 @@ public class Maestro2Broker { final File workingDirectory; final ErrorReporter reporter; private final Supplier isStopRequsted; - private final Function>, List> flattenFmuIds = map -> map.entrySet().stream() - .flatMap(entry -> entry.getValue().stream().map(v -> entry.getKey() + "." + v)).collect(Collectors.toList()); + private final Function>, List> flattenFmuIds = + map -> map.entrySet().stream().flatMap(entry -> entry.getValue().stream().map(v -> entry.getKey() + "." + v)) + .collect(Collectors.toList()); private Map.Entry> typeCheckResult; public Maestro2Broker(File workingDirectory, ErrorReporter reporter, Supplier isStopRequsted) { @@ -74,18 +75,20 @@ public Maestro2Broker(File workingDirectory, ErrorReporter reporter, Supplier void buildAndRunMasterModel(Map> livestreamVariables, WebSocketSession socket, T multiModel, SigverSimulateRequestBody body, File csvOutputFile) throws Exception { MasterModel masterModel = ScenarioLoader.load(new ByteArrayInputStream(body.getMasterModel().getBytes())); - Fmi2SimulationEnvironmentConfiguration simulationConfiguration = new Fmi2SimulationEnvironmentConfiguration( - MasterModelMapper.Companion.masterModelConnectionsToMultiModelConnections(masterModel), multiModel.getFmus()); + Fmi2SimulationEnvironmentConfiguration simulationConfiguration = + new Fmi2SimulationEnvironmentConfiguration(MasterModelMapper.Companion.masterModelConnectionsToMultiModelConnections(masterModel), + multiModel.getFmus()); simulationConfiguration.logVariables = multiModel.getLogVariables(); if (simulationConfiguration.logVariables == null) { simulationConfiguration.variablesToLog = new HashMap<>(); } Fmi2SimulationEnvironment simulationEnvironment = Fmi2SimulationEnvironment.of(simulationConfiguration, reporter); - ScenarioConfiguration configuration = new ScenarioConfiguration(simulationEnvironment, masterModel, multiModel.getParameters(), - multiModel.getGlobal_relative_tolerance(), multiModel.getGlobal_absolute_tolerance(), multiModel.getConvergenceAttempts(), - body.getStartTime(), body.getEndTime(), multiModel.getAlgorithm().getStepSize(), Pair.of(Framework.FMI2, simulationConfiguration), - multiModel.isLoggingOn(), multiModel.getLogLevels()); + ScenarioConfiguration configuration = + new ScenarioConfiguration(simulationEnvironment, masterModel, multiModel.getParameters(), multiModel.getGlobal_relative_tolerance(), + multiModel.getGlobal_absolute_tolerance(), multiModel.getConvergenceAttempts(), body.getStartTime(), body.getEndTime(), + multiModel.getAlgorithm().getStepSize(), Pair.of(Framework.FMI2, simulationConfiguration), multiModel.isLoggingOn(), + multiModel.getLogLevels()); String runtimeJsonConfigString = generateSpecification(configuration, null); @@ -101,7 +104,7 @@ public void buildAndRunMasterModel(Map portsToLog = Stream.concat(simulationEnvironment.getConnectedOutputs().stream().map(x -> { ComponentInfo i = simulationEnvironment.getUnitInfo(new LexIdentifier(x.instance.getText(), null), Framework.FMI2); - return String.format("%s.%s.%s", i.fmuIdentifier, x.instance.getText(), x.scalarVariable.getName()); + return String.format("%s.%s.%s", i.fmuIdentifier, x.instance.getText(), x.getName()); }), multiModel.getLogVariables() == null ? Stream.of() : multiModel.getLogVariables().entrySet().stream() .flatMap(entry -> entry.getValue().stream().map(v -> entry.getKey() + "." + v))).collect(Collectors.toList()); @@ -117,8 +120,8 @@ public void buildAndRun(InitializationData initializeRequest, SimulateRequestBod //Initially resolve any FMUs to the local folder in case they are uploaded ImportCmd.resolveFmuPaths(Collections.singletonList(workingDirectory), initializeRequest.getFmus()); - Fmi2SimulationEnvironmentConfiguration simulationConfiguration = new Fmi2SimulationEnvironmentConfiguration( - initializeRequest.getConnections(), initializeRequest.getFmus()); + Fmi2SimulationEnvironmentConfiguration simulationConfiguration = + new Fmi2SimulationEnvironmentConfiguration(initializeRequest.getConnections(), initializeRequest.getFmus()); simulationConfiguration.logVariables = initializeRequest.getLogVariables(); if (simulationConfiguration.logVariables == null) { @@ -162,10 +165,11 @@ public void buildAndRun(InitializationData initializeRequest, SimulateRequestBod config.startTime = body.getStartTime(); config.endTime = body.getEndTime(); - MaBLTemplateConfiguration.MaBLTemplateConfigurationBuilder builder = MaBLTemplateConfiguration.MaBLTemplateConfigurationBuilder.getBuilder() - .setFrameworkConfig(Framework.FMI2, simulationConfiguration).useInitializer(true, new ObjectMapper().writeValueAsString(initialize)) - .setFramework(Framework.FMI2).setLogLevels(removedFMUKeyFromLogLevels).setVisible(initializeRequest.isVisible()) - .setLoggingOn(initializeRequest.isLoggingOn()).setStepAlgorithmConfig(config); + MaBLTemplateConfiguration.MaBLTemplateConfigurationBuilder builder = + MaBLTemplateConfiguration.MaBLTemplateConfigurationBuilder.getBuilder().setFrameworkConfig(Framework.FMI2, simulationConfiguration) + .useInitializer(true, new ObjectMapper().writeValueAsString(initialize)).setFramework(Framework.FMI2) + .setLogLevels(removedFMUKeyFromLogLevels).setVisible(initializeRequest.isVisible()) + .setLoggingOn(initializeRequest.isLoggingOn()).setStepAlgorithmConfig(config); MaBLTemplateConfiguration configuration = builder.build(); @@ -187,8 +191,8 @@ public void buildAndRun(InitializationData initializeRequest, SimulateRequestBod if (filesNotResolved.size() > 0) { errMsg = "Cannot resolve path to spec files: " + nonMablFiles.stream().map(File::getName).reduce("", (prev, cur) -> prev + " " + cur); } else if (nonMablFiles.size() > 0) { - errMsg = "Cannot load spec files: " + nonMablFiles.stream().map(File::getName) - .reduce("", (prev, cur) -> prev + " " + cur) + ". Only mabl files should be " + "included as " + "external specs."; + errMsg = "Cannot load spec files: " + nonMablFiles.stream().map(File::getName).reduce("", (prev, cur) -> prev + " " + cur) + + ". Only mabl files should be " + "included as " + "external specs."; } if (!errMsg.equals("")) { @@ -198,8 +202,8 @@ public void buildAndRun(InitializationData initializeRequest, SimulateRequestBod mabl.parse(initializeRequest.getExternalSpecs()); } // If fault injection is configured then the faultinject.mabl file should be included as an external spec. - if (initializeRequest.faultInjectConfigurationPath != null && !initializeRequest.faultInjectConfigurationPath.equals( - "") && !didLocateFaultInjectionFile.get()) { + if (initializeRequest.faultInjectConfigurationPath != null && !initializeRequest.faultInjectConfigurationPath.equals("") && + !didLocateFaultInjectionFile.get()) { throw new Exception("Remember to include FaultInject.mabl as an external spec"); } String runtimeJsonConfigString = generateSpecification(configuration, parameters); @@ -215,7 +219,7 @@ public void buildAndRun(InitializationData initializeRequest, SimulateRequestBod List connectedOutputs = simulationEnvironment.getConnectedOutputs().stream().map(x -> { ComponentInfo i = simulationEnvironment.getUnitInfo(new LexIdentifier(x.instance.getText(), null), Framework.FMI2); - return String.format("%s.%s.%s", i.fmuIdentifier, x.instance.getText(), x.scalarVariable.getName()); + return String.format("%s.%s.%s", i.fmuIdentifier, x.instance.getText(), x.getName()); }).collect(Collectors.toList()); diff --git a/maestro/src/main/java/org/intocps/maestro/MablSpecificationGenerator.java b/maestro/src/main/java/org/intocps/maestro/MablSpecificationGenerator.java index 84970e79b..91562d818 100644 --- a/maestro/src/main/java/org/intocps/maestro/MablSpecificationGenerator.java +++ b/maestro/src/main/java/org/intocps/maestro/MablSpecificationGenerator.java @@ -66,7 +66,7 @@ public static Collection loadExpansionPlugins(Framework //load recursive plugin dependencies List pluginsToUnfoldWithDependencies = Stream.concat(pluginsToUnfold.stream(), - pluginsToUnfold.stream().map(p -> collectPluginDependencies(plugins, p, new Vector<>()).stream()).flatMap(Function.identity())) + pluginsToUnfold.stream().map(p -> collectPluginDependencies(plugins, p, new Vector<>()).stream()).flatMap(Function.identity())) .distinct().collect(Collectors.toList()); @@ -95,7 +95,7 @@ static Collection collectPluginDependencies(Collection< } return Stream.concat(requiredPlugins.stream(), - requiredPlugins.stream().map(p -> collectPluginDependencies(plugins, p, checked).stream()).flatMap(Function.identity())) + requiredPlugins.stream().map(p -> collectPluginDependencies(plugins, p, checked).stream()).flatMap(Function.identity())) .collect(Collectors.toList()); } @@ -203,8 +203,7 @@ private ARootDocument expandExternals(List importedDocumentList, .collect(Collectors.toList())); }); - for (Map.Entry>> callReplacement : replaceWith - .entrySet()) { + for (Map.Entry>> callReplacement : replaceWith.entrySet()) { ACallExp call = callReplacement.getKey(); AFunctionDeclaration replacement = callReplacement.getValue().get().getValue(); IMaestroExpansionPlugin replacementPlugin = @@ -255,8 +254,8 @@ private void replaceCall(ACallExp callToBeReplaced, AFunctionDeclaration replace BuilderHelper builderHelper = new BuilderHelper(callToBeReplaced, typesMap, simulationEnvironment); builderHelper.getBuilder().resetDirty(); - IMaestroExpansionPlugin.RuntimeConfigAddition runtimeConfigProduced = replacementPlugin - .expandWithRuntimeAddition(replacement, builderHelper.getBuilder(), builderHelper.getArgumentVariables(), config, + IMaestroExpansionPlugin.RuntimeConfigAddition runtimeConfigProduced = + replacementPlugin.expandWithRuntimeAddition(replacement, builderHelper.getBuilder(), builderHelper.getArgumentVariables(), config, simulationEnvironment, reporter); if (builderHelper.getBuilder().isDirty()) { @@ -273,19 +272,19 @@ private void replaceCall(ACallExp callToBeReplaced, AFunctionDeclaration replace //2: see fallback to the raw interface { if (unfoled == null) { - unfoled = replacementPlugin - .expandWithRuntimeAddition(replacement, callToBeReplaced.getArgs(), config, simulationEnvironment, reporter); + unfoled = replacementPlugin.expandWithRuntimeAddition(replacement, callToBeReplaced.getArgs(), config, simulationEnvironment, + reporter); } } } catch (ExpandException e) { - logger.error("Internal error in plug-in '{}' at {}. Message: {}", replacementPlugin.getName(), - callToBeReplaced.getMethodName().toString(), e.getMessage()); + logger.error(String.format("Internal error in plug-in '%s' at %s. Message: %s", replacementPlugin.getName(), + callToBeReplaced.getMethodName().toString(), e.getMessage()), e); reporter.report(999, String.format("Internal error in plug-in '%s' at %s. Message: %s", replacementPlugin.getName(), callToBeReplaced.getMethodName().toString(), e.getMessage()), callToBeReplaced.getMethodName().getSymbol()); } catch (Exception e) { - logger.error("Internal error while processing builder for in plug-in '{}' at {}. Message: {}", replacementPlugin.getName(), - callToBeReplaced.getMethodName().toString(), e.getMessage()); + logger.error(String.format("Internal error while processing builder for in plug-in '%s' at %s. Message: %s", replacementPlugin.getName(), + callToBeReplaced.getMethodName().toString(), e.getMessage()), e); reporter.report(998, String.format("Internal error in plug-in '%s' at %s. Message: %s", replacementPlugin.getName(), callToBeReplaced.getMethodName().toString(), e.getMessage()), callToBeReplaced.getMethodName().getSymbol()); } @@ -452,8 +451,9 @@ private void handleInstanceMappingStatements(ASimulationSpecificationCompilation if (simulationModule.getBody() instanceof SBlockStm) { Optional> instanceMappings = NodeCollector.collect(simulationModule.getBody(), AInstanceMappingStm.class); if (instanceMappings.isPresent()) { - instanceMappings.get().forEach(x -> ((Fmi2SimulationEnvironment) this.simulationEnvironment) - .setLexNameToInstanceNameMapping(x.getIdentifier().getText(), x.getName())); + instanceMappings.get().forEach( + x -> ((Fmi2SimulationEnvironment) this.simulationEnvironment).setLexNameToInstanceNameMapping(x.getIdentifier().getText(), + x.getName())); } } } diff --git a/maestro/src/main/java/org/intocps/maestro/template/MaBLTemplateGenerator.java b/maestro/src/main/java/org/intocps/maestro/template/MaBLTemplateGenerator.java index 842dca19f..1f08c2eb6 100644 --- a/maestro/src/main/java/org/intocps/maestro/template/MaBLTemplateGenerator.java +++ b/maestro/src/main/java/org/intocps/maestro/template/MaBLTemplateGenerator.java @@ -11,13 +11,10 @@ import org.intocps.maestro.core.dto.IAlgorithmConfig; import org.intocps.maestro.fmi.Fmi2ModelDescription; import org.intocps.maestro.fmi.ModelDescription; -import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; +import org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; import org.intocps.maestro.framework.core.FrameworkUnitInfo; import org.intocps.maestro.framework.core.IRelation; -import org.intocps.maestro.framework.fmi2.ComponentInfo; -import org.intocps.maestro.framework.fmi2.FaultInjectWithLexName; -import org.intocps.maestro.framework.fmi2.Fmi2SimulationEnvironment; -import org.intocps.maestro.framework.fmi2.InstanceInfo; +import org.intocps.maestro.framework.fmi2.*; import org.intocps.maestro.plugin.IMaestroPlugin; import org.intocps.maestro.plugin.JacobianStepConfig; import org.slf4j.Logger; @@ -520,15 +517,12 @@ private static void checkConnectionUnits(Fmi2SimulationEnvironment unitRelationS for (Map.Entry instance : unitRelationShip.getInstances()) { for (Fmi2SimulationEnvironment.Relation relation : unitRelationShip.getRelations(instance.getKey())) { if (relation.getOrigin() == IRelation.InternalOrExternal.External && relation.getDirection() == IRelation.Direction.OutputToInput) { - for (Map.Entry target : relation.getTargets().entrySet()) { + for (Map.Entry target : relation.getTargets().entrySet()) { - if (!target.getValue().getScalarVariable().getScalarVariable().getType() - .isAssignableFrom(relation.getSource().getScalarVariable().getScalarVariable().getType(), false)) { + if (!target.getValue().getType().isAssignableFrom(relation.getSource().getType().get(), false)) { sbUnitError.append(String.format("Invalid unit for connection: %s.%s [%s] -> %s.%s [%s]", instance.getKey(), - relation.getSource().getScalarVariable().getScalarVariable().name, - relation.getSource().getScalarVariable().getScalarVariable().getType().unit.getName(), target.getKey().getText(), - target.getValue().getScalarVariable().getScalarVariable().name, - target.getValue().getScalarVariable().getScalarVariable().getType().unit.getName())); + relation.getSource().getName(), relation.getSource().getType2().get().unit.getName(), target.getKey().getText(), + target.getValue().getName(), target.getValue().getType2().get().unit.getName())); } } } diff --git a/maestro/src/test/java/org/intocps/maestro/BuilderFmi3Test.java b/maestro/src/test/java/org/intocps/maestro/BuilderFmi3Test.java index 5df7cc699..95561bc32 100644 --- a/maestro/src/test/java/org/intocps/maestro/BuilderFmi3Test.java +++ b/maestro/src/test/java/org/intocps/maestro/BuilderFmi3Test.java @@ -10,7 +10,7 @@ import org.intocps.maestro.core.messages.ErrorReporter; import org.intocps.maestro.core.messages.IErrorReporter; import org.intocps.maestro.fmi.Fmi2ModelDescription; -import org.intocps.maestro.fmi.org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; +import org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; import org.intocps.maestro.fmi3.Fmi3ModuleReferenceFmusTest; import org.intocps.maestro.framework.fmi2.Fmi2SimulationEnvironment; import org.intocps.maestro.framework.fmi2.Fmi2SimulationEnvironmentConfiguration; @@ -31,7 +31,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; -import java.lang.reflect.Array; import java.net.URI; import java.nio.charset.StandardCharsets; import java.util.Collections; @@ -79,7 +78,7 @@ public void wt() throws Exception { URI ballUri = new File("target/Fmi3ModuleReferenceFmusTest/cache/BouncingBall.fmu").getAbsoluteFile().toURI(); Fmu3 ball = new Fmu3(new File(ballUri)); - ArrayVariableFmi2Api requiredIntermediateVariables = builder.getDynamicScope().store("requiredIntermediateVariables", new Long[] {1L}); + ArrayVariableFmi2Api requiredIntermediateVariables = builder.getDynamicScope().store("requiredIntermediateVariables", new Long[]{1L}); Fmi3ModelDescription md3Ball = new Fmi3ModelDescription(ball.getModelDescription()); @@ -89,25 +88,20 @@ public void wt() throws Exception { boolean loggingOn = true; boolean eventModeUsed = true; boolean earlyReturnAllowed = true; - InstanceVariableFmi3Api ballInstance = ballFmu.instantiate("ballInstance", visible, loggingOn, eventModeUsed, earlyReturnAllowed, - requiredIntermediateVariables); + InstanceVariableFmi3Api ballInstance = + ballFmu.instantiate("ballInstance", visible, loggingOn, eventModeUsed, earlyReturnAllowed, requiredIntermediateVariables); - ballInstance.enterInitializationMode(false, 0.0, 0.0, true,10.0); + ballInstance.enterInitializationMode(false, 0.0, 0.0, true, 10.0); ballInstance.exitInitializationMode(); -// ArrayVariableFmi2Api svs = builder.getDynamicScope().store("svs", new Long[] {5L, 6L}); -// ArrayVariableFmi2Api values_r = builder.getDynamicScope().store("values_r", new Double[] {-9.81, 0.7}); + // ArrayVariableFmi2Api svs = builder.getDynamicScope().store("svs", new Long[] {5L, 6L}); + // ArrayVariableFmi2Api values_r = builder.getDynamicScope().store("values_r", new Double[] {-9.81, 0.7}); ballInstance.terminate(); -// ballInstance.freeInstance(); - - - - - + // ballInstance.freeInstance(); // Create the two FMUs diff --git a/maestro/src/test/resources/cli-test/config-fmi3.json b/maestro/src/test/resources/cli-test/config-fmi3.json index 594755e72..f3891dc6b 100644 --- a/maestro/src/test/resources/cli-test/config-fmi3.json +++ b/maestro/src/test/resources/cli-test/config-fmi3.json @@ -4,7 +4,7 @@ "{x2}": "src/test/resources/singlewatertank-20sim.fmu" }, "connections": { - "{x1}.controller.valve": [ + "{x1}.controller.h": [ "{x2}.tank.valvecontrol" ], "{x2}.tank.level": [ diff --git a/maestro/src/test/resources/fmi3/basic/basic1/fmi3_basic.mabl b/maestro/src/test/resources/fmi3/basic/basic1/fmi3_basic.mabl index cd1738d60..0a074f590 100644 --- a/maestro/src/test/resources/fmi3/basic/basic1/fmi3_basic.mabl +++ b/maestro/src/test/resources/fmi3/basic/basic1/fmi3_basic.mabl @@ -27,7 +27,7 @@ import FMI3; float f1 = 1; byte b1 = 2; byte valu8[3]={100,0,0}; - instance.setUInt8(sv,valu8); + instance.setUInt8(sv,3,valu8,3); x1.freeInstance(instance); diff --git a/maestro/src/test/resources/fmi3/reference/bounchingball/fmi3_bb.mabl b/maestro/src/test/resources/fmi3/reference/bounchingball/fmi3_bb.mabl index 466015039..5a0701018 100644 --- a/maestro/src/test/resources/fmi3/reference/bounchingball/fmi3_bb.mabl +++ b/maestro/src/test/resources/fmi3/reference/bounchingball/fmi3_bb.mabl @@ -34,7 +34,7 @@ import Logger; uint svs[2]={sv_par_g, sv_par_e}; float values_r[2]={-9.81,0.7}; - res=instance.setFloat32(svs,values_r); + res=instance.setFloat32(svs,2,values_r,2); logger.log(3,"setFloat32 status %d",res); res=instance.enterInitializationMode(false, 0.0, 0.0, true,10.0); diff --git a/plugins/fixedstep/src/main/java/org/intocps/maestro/plugin/DataExchangeHandler.java b/plugins/fixedstep/src/main/java/org/intocps/maestro/plugin/DataExchangeHandler.java index 73141d9c7..b5fd7dac0 100644 --- a/plugins/fixedstep/src/main/java/org/intocps/maestro/plugin/DataExchangeHandler.java +++ b/plugins/fixedstep/src/main/java/org/intocps/maestro/plugin/DataExchangeHandler.java @@ -33,11 +33,11 @@ public DataExchangeHandler(Set relations, Fm // outputs contains both outputs based on relations and outputs based on additional variables to log //FIXME fmi3 is excluded - outputs = outputRelations.stream().map(r -> r.getSource().scalarVariable.instance).distinct().collect(Collectors.toMap(Function.identity(), - s -> outputRelations.stream().filter(r -> r.getSource().scalarVariable.instance.equals(s)).flatMap(r -> { - List outputs_ = - env.getVariablesToLog(s.getText()).stream().map(x -> x.getScalarVariable(Fmi2ModelDescription.ScalarVariable.class)) - .filter(Objects::nonNull).collect(Collectors.toList()); + outputs = outputRelations.stream().map(r -> r.getSource().getInstance()).distinct().collect( + Collectors.toMap(Function.identity(), s -> outputRelations.stream().filter(r -> r.getSource().getInstance().equals(s)).flatMap(r -> { + List outputs_ = env.getVariablesToLog(s.getText()).stream() + .map(x -> (Fmi2ModelDescription.ScalarVariable) x.getScalarVariable(Fmi2ModelDescription.ScalarVariable.class)) + .filter(Objects::nonNull).collect(Collectors.toList()); //outputs_.add(r.getSource().scalarVariable.getScalarVariable()); return outputs_.stream(); }).distinct().collect(Collectors.groupingBy(sv -> sv.getType().type)))); @@ -47,9 +47,10 @@ public DataExchangeHandler(Set relations, Fm inputRelations = relations.stream().filter(r -> r.getDirection() == Fmi2SimulationEnvironment.Relation.Direction.InputToOutput) .collect(Collectors.toSet()); - inputs = inputRelations.stream().map(r -> r.getSource().scalarVariable.instance).distinct().collect(Collectors.toMap(Function.identity(), - s -> inputRelations.stream().filter(r -> r.getSource().scalarVariable.instance.equals(s)) - .map(r -> r.getSource().scalarVariable.getScalarVariable()).collect(Collectors.groupingBy(sv -> sv.getType().type)))); + inputs = inputRelations.stream().map(r -> r.getSource().getInstance()).distinct().collect(Collectors.toMap(Function.identity(), + s -> inputRelations.stream().filter(r -> r.getSource().getInstance().equals(s)) + .map(r -> (Fmi2ModelDescription.ScalarVariable) r.getSource().getScalarVariable(Fmi2ModelDescription.ScalarVariable.class)) + .collect(Collectors.groupingBy(sv -> sv.getType().type)))); } @@ -189,32 +190,35 @@ public List setAll() { public List exchangeData() { Consumer> exchangeData = (list) -> inputRelations.forEach(r -> { - int toIndex = - inputs.get(r.getSource().scalarVariable.instance).get(r.getSource().scalarVariable.getScalarVariable().getType().type).stream() - .map(Fmi2ModelDescription.ScalarVariable::getName).collect(Collectors.toList()) - .indexOf(r.getSource().scalarVariable.scalarVariable.getName()); - AArrayStateDesignator to = newAArayStateDesignator(newAIdentifierStateDesignator( - getBufferName(r.getSource().scalarVariable.instance, r.getSource().scalarVariable.getScalarVariable().getType().type, - UsageType.In)), newAIntLiteralExp(toIndex)); + Fmi2ModelDescription.Types sourceType = r.getSource().getType2().get().type; + + int toIndex = inputs.get(r.getSource().getInstance()).get(sourceType).stream().map(Fmi2ModelDescription.ScalarVariable::getName) + .collect(Collectors.toList()).indexOf(r.getSource().getName()); + + AArrayStateDesignator to = + newAArayStateDesignator(newAIdentifierStateDesignator(getBufferName(r.getSource().getInstance(), sourceType, UsageType.In)), + newAIntLiteralExp(toIndex)); //the relation should be a one to one relation so just take the first one - RelationVariable fromVar = r.getTargets().values().iterator().next().scalarVariable; - PExp from = newAArrayIndexExp(newAIdentifierExp(getBufferName(fromVar.instance, fromVar.getScalarVariable().type.type, UsageType.Out)), - Collections.singletonList(newAIntLiteralExp(outputs.get(fromVar.instance).get(fromVar.getScalarVariable().getType().type).stream() - .map(Fmi2ModelDescription.ScalarVariable::getName).collect(Collectors.toList()) - .indexOf(fromVar.scalarVariable.getName())))); + RelationVariable fromVar = r.getTargets().values().iterator().next(); + + Fmi2ModelDescription.Types fromVarType = fromVar.getType2().get().type; + + PExp from = newAArrayIndexExp(newAIdentifierExp(getBufferName(fromVar.instance, fromVar.getType2().get().type, UsageType.Out)), + Collections.singletonList(newAIntLiteralExp(outputs.get(fromVar.instance).get(fromVar.getType2().get().type).stream() + .map(Fmi2ModelDescription.ScalarVariable::getName).collect(Collectors.toList()).indexOf(fromVar.getName())))); - if (r.getSource().scalarVariable.getScalarVariable().getType().type != fromVar.getScalarVariable().getType().type) { + if (sourceType != fromVar.getType2().get().type) { //ok the types are not matching, lets use a converter - AArrayIndexExp toAsExp = newAArrayIndexExp(newAIdentifierExp( - getBufferName(r.getSource().scalarVariable.instance, r.getSource().scalarVariable.getScalarVariable().getType().type, - UsageType.In)), Arrays.asList(newAIntLiteralExp(toIndex))); + AArrayIndexExp toAsExp = newAArrayIndexExp( + newAIdentifierExp(getBufferName(r.getSource().getInstance(), r.getSource().getType2().get().type, UsageType.In)), + Arrays.asList(newAIntLiteralExp(toIndex))); - list.add(newExpressionStm(newACallExp(newExpandToken(), newAIdentifierExp("TypeConverter"), newAIdentifier( - "convert" + fromVar.getScalarVariable().getType().type + "2" + - r.getSource().scalarVariable.getScalarVariable().getType().type), Arrays.asList(from, toAsExp)))); + list.add(newExpressionStm(newACallExp(newExpandToken(), newAIdentifierExp("TypeConverter"), + newAIdentifier("convert" + fromVar.getType2().get().type + "2" + r.getSource().getType2().get().type), + Arrays.asList(from, toAsExp)))); } else { diff --git a/plugins/fixedstep/src/main/java/org/intocps/maestro/plugin/DataWriterHandler.java b/plugins/fixedstep/src/main/java/org/intocps/maestro/plugin/DataWriterHandler.java index 796c7bebd..9986ab4ec 100644 --- a/plugins/fixedstep/src/main/java/org/intocps/maestro/plugin/DataWriterHandler.java +++ b/plugins/fixedstep/src/main/java/org/intocps/maestro/plugin/DataWriterHandler.java @@ -4,6 +4,8 @@ import org.intocps.maestro.ast.MableAstFactory; import org.intocps.maestro.ast.node.PExp; import org.intocps.maestro.ast.node.PStm; +import org.intocps.maestro.ast.node.PType; +import org.intocps.maestro.ast.node.SPrimitiveType; import org.intocps.maestro.core.Framework; import org.intocps.maestro.fmi.Fmi2ModelDescription; import org.intocps.maestro.framework.core.FrameworkUnitInfo; @@ -34,11 +36,11 @@ public List allocate(Set inputRelation List statements = new Vector<>(); List variableNames = new Vector<>(); - Function getLogName = k -> k.getInstance().getText() + "." + k.getName(); + Function getLogName = k -> k.getInstance().getText() + "." + k.getName(); csvFields = inputRelations.stream().map(r -> r.getTargets().values().stream().findFirst()).filter(Optional::isPresent).map(Optional::get) .flatMap(h -> { - List outputs_ = env.getVariablesToLog(h.scalarVariable.instance.getText()); + List outputs_ = env.getVariablesToLog(h.getInstance().getText()); //outputs_.add(h.scalarVariable); return outputs_.stream(); //return h.scalarVariable; @@ -46,17 +48,14 @@ public List allocate(Set inputRelation //the relation should be a one to one relation so just take the first one - org.intocps.maestro.framework.core.RelationVariable fromVar = r; - - if (fromVar instanceof RelationVariable) { - Fmi2ModelDescription.Types fromType = ((RelationVariable) fromVar).getScalarVariable().type.type; - PExp from = arrayGet(getBufferName(fromVar.getInstance(), fromType, DataExchangeHandler.UsageType.Out), - outputs.get(fromVar.getInstance()).get(fromType).stream().map(Fmi2ModelDescription.ScalarVariable::getName) - .collect(Collectors.toList()).indexOf(fromVar.getName())); - return from; - } else { - throw new RuntimeException("Not a fmi 2 variable"); - } + RelationVariable fromVar = r; + + + PType fromType = fromVar.getType().getLexType(); + PExp from = arrayGet(getBufferName(fromVar.getInstance(), (SPrimitiveType) fromType, DataExchangeHandler.UsageType.Out), + outputs.get(fromVar.getInstance()).get(fromVar.getType2().get().type).stream() + .map(Fmi2ModelDescription.ScalarVariable::getName).collect(Collectors.toList()).indexOf(fromVar.getName())); + return from; }, (oldValue, newValue) -> oldValue, LinkedHashMap::new)); diff --git a/plugins/fixedstep/src/main/java/org/intocps/maestro/plugin/DerivativesHandler.java b/plugins/fixedstep/src/main/java/org/intocps/maestro/plugin/DerivativesHandler.java index 6b2a8daf3..020e99dee 100644 --- a/plugins/fixedstep/src/main/java/org/intocps/maestro/plugin/DerivativesHandler.java +++ b/plugins/fixedstep/src/main/java/org/intocps/maestro/plugin/DerivativesHandler.java @@ -30,9 +30,9 @@ class DerivativesHandler { final static Logger logger = LoggerFactory.getLogger(DerivativesHandler.class); - final BiPredicate canInterpolateInputsFilter = (env, v) -> { + final BiPredicate canInterpolateInputsFilter = (env, v) -> { try { - return ((ComponentInfo) env.getUnitInfo(v.scalarVariable.instance, Framework.FMI2)).modelDescription.getCanInterpolateInputs(); + return ((ComponentInfo) env.getUnitInfo(v.getInstance(), Framework.FMI2)).modelDescription.getCanInterpolateInputs(); } catch (XPathExpressionException e) { return false; } @@ -50,7 +50,7 @@ class DerivativesHandler { Map derivativesGetInfo = new HashMap<>(); private boolean allocated = false; private boolean requireArrayUtilUnload = false; - private Map>, LinkedHashMap>> + private Map>, LinkedHashMap>> resolvedInputData; public List allocateMemory(List componentNames, Set inputRelations, @@ -58,20 +58,19 @@ public List allocateMemory(List componentNames, Set> tmp = - inputRelations.stream().filter(r -> canInterpolateInputsFilter.test(env, r.getSource())) - .map(Fmi2SimulationEnvironment.Relation::getTargets).collect(Collectors.toSet()); + Set> tmp = inputRelations.stream().filter(r -> canInterpolateInputsFilter.test(env, r.getSource())) + .map(Fmi2SimulationEnvironment.Relation::getTargets).collect(Collectors.toSet()); - Map> vars = new HashMap<>(); - for (Map map : tmp) { - for (Map.Entry entry : map.entrySet()) { + Map> vars = new HashMap<>(); + for (Map map : tmp) { + for (Map.Entry entry : map.entrySet()) { vars.computeIfAbsent(entry.getKey(), key -> new Vector<>()).add(entry.getValue()); } } - for (Map.Entry> entry : vars.entrySet()) { - entry.getValue().sort(Comparator.comparing(v -> v.getScalarVariable().getScalarVariable().valueReference)); + for (Map.Entry> entry : vars.entrySet()) { + entry.getValue().sort(Comparator.comparing(v -> v.getValueReference())); } @@ -92,7 +91,7 @@ public List allocateMemory(List componentNames, Set allocateMemory(List componentNames, Set IntStream.range(1, order + 1) - .mapToObj(o -> newAIntLiteralExp((int) v.getScalarVariable().getScalarVariable().valueReference))) + statements.add(newVariable(varSelectName, newUIntType(), f.getValue().stream() + .flatMap(v -> IntStream.range(1, order + 1).mapToObj(o -> newAIntLiteralExp((int) v.getValueReference()))) .collect(Collectors.toList()))); varDerInfo.valueSelectArrayId = varSelectName; derivativesGetInfo.put(id, varDerInfo); @@ -130,20 +129,18 @@ public List allocateMemory(List componentNames, Set allocateForInput(Set inputRelations, Fmi2SimulationEnvironment env) { resolvedInputData = inputRelations.stream().filter(r -> canInterpolateInputsFilter.test(env, r.getSource())) - .collect(Collectors.groupingBy(s -> s.getSource().getScalarVariable().instance)).entrySet().stream().collect(Collectors - .toMap(Function.identity(), mapped -> mapped.getValue().stream() - .sorted(Comparator.comparing(map -> map.getSource().getScalarVariable().getScalarVariable().valueReference)) + .collect(Collectors.groupingBy(s -> s.getSource().getInstance())).entrySet().stream().collect(Collectors.toMap(Function.identity(), + mapped -> mapped.getValue().stream().sorted(Comparator.comparing(map -> map.getSource().getValueReference())) .collect(Collectors.toMap(Fmi2SimulationEnvironment.Relation::getSource, map -> { //the relation should be a one to one relation so just take the first one - Fmi2SimulationEnvironment.Variable next = map.getTargets().values().iterator().next(); - RelationVariable fromVar = next.scalarVariable; + RelationVariable next = map.getTargets().values().iterator().next(); + RelationVariable fromVar = next; GetDerivativesInfo fromVarDerivativeInfo = derivativesGetInfo.get(fromVar.instance); if (fromVarDerivativeInfo != null) { - logger.trace("Derivative mapping {}.{} to {}.{}", fromVar.instance, fromVar.scalarVariable.name, - map.getSource().getScalarVariable().instance, - map.getSource().getScalarVariable().scalarVariable.name); + logger.trace("Derivative mapping {}.{} to {}.{}", fromVar.instance, fromVar.getName(), + map.getSource().getInstance(), map.getSource().getName()); } return Map.entry(next, fromVarDerivativeInfo); @@ -161,12 +158,11 @@ private List allocateForInput(Set inpu List allocationStatements = Stream.concat(Stream.of(newVariable("der_input_buffer", newARealNumericPrimitiveType(), size)), resolvedInputData.entrySet().stream().flatMap(map -> { - LinkedHashMap> resolved = - map.getValue(); + LinkedHashMap> resolved = map.getValue(); List inputSelectIndices = resolved.entrySet().stream().flatMap( - m -> IntStream.range(1, m.getValue().getValue().varMaxOrder + 1) - .mapToObj(i -> Long.valueOf(m.getKey().getScalarVariable().scalarVariable.valueReference).intValue())) + m -> IntStream.range(1, m.getValue().getValue().varMaxOrder + 1) + .mapToObj(i -> Long.valueOf(m.getKey().getValueReference()).intValue())) .collect(Collectors.toList()); List inputOrders = resolved.entrySet().stream().flatMap(m -> IntStream.range(1, m.getValue().getValue().varMaxOrder + 1).mapToObj(i -> i)) @@ -175,7 +171,7 @@ private List allocateForInput(Set inpu LexIdentifier name = map.getKey().getKey(); return Stream.of(newVariable("der_input_select_" + name.getText(), newAIntNumericPrimitiveType(), - inputSelectIndices.stream().map(MableAstFactory::newAIntLiteralExp).collect(Collectors.toList())), + inputSelectIndices.stream().map(MableAstFactory::newAIntLiteralExp).collect(Collectors.toList())), newVariable("der_input_order" + "_" + name.getText(), newAIntNumericPrimitiveType(), inputOrders.stream().map(MableAstFactory::newAIntLiteralExp).collect(Collectors.toList()))); @@ -282,7 +278,7 @@ class GetDerivativesInfo { String orderArrayId; String valueSelectArrayId; PExp valueDestIdentifier; - Map varStartIndex = new HashMap<>(); + Map varStartIndex = new HashMap<>(); Integer varMaxOrder; } } diff --git a/plugins/initializer/src/main/java/org/intocps/maestro/plugin/initializer/PhasePredicates.java b/plugins/initializer/src/main/java/org/intocps/maestro/plugin/initializer/PhasePredicates.java index f7e60d47f..3dc77e1ed 100644 --- a/plugins/initializer/src/main/java/org/intocps/maestro/plugin/initializer/PhasePredicates.java +++ b/plugins/initializer/src/main/java/org/intocps/maestro/plugin/initializer/PhasePredicates.java @@ -1,6 +1,7 @@ package org.intocps.maestro.plugin.initializer; import org.intocps.maestro.fmi.Fmi2ModelDescription; +import org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; import static org.intocps.maestro.fmi.Fmi2ModelDescription.*; @@ -13,16 +14,12 @@ public static Predicate iniPhase() { (o.causality == Causality.Parameter && o.variability == Variability.Tunable); } - public static Predicate iniePhase() { - return o -> o.initial == Initial.Exact && o.variability != Variability.Constant; - } public static Predicate inPhase() { return o -> (o.causality == Causality.Input && o.initial == Initial.Calculated || o.causality == Causality.Parameter && o.variability == Variability.Tunable); } - public static Predicate initPhase() { - return o -> o.causality == Causality.Output; - } + + } \ No newline at end of file diff --git a/plugins/initializer/src/main/java/org/intocps/maestro/plugin/initializer/PhasePredicates3.java b/plugins/initializer/src/main/java/org/intocps/maestro/plugin/initializer/PhasePredicates3.java new file mode 100644 index 000000000..25ecea2e5 --- /dev/null +++ b/plugins/initializer/src/main/java/org/intocps/maestro/plugin/initializer/PhasePredicates3.java @@ -0,0 +1,23 @@ +package org.intocps.maestro.plugin.initializer; + + +import org.intocps.maestro.fmi.ModelDescription; +import org.intocps.maestro.fmi.fmi3.Fmi3Causality; +import org.intocps.maestro.fmi.fmi3.Fmi3Variable; + +import java.util.function.Predicate; + +public class PhasePredicates3 { + + public static Predicate iniPhase() { + return o -> ((o.getInitial() == ModelDescription.Initial.Exact || o.getInitial() == ModelDescription.Initial.Approx) && + o.getVariability() != ModelDescription.Variability.Constant) || + (o.getCausality() == Fmi3Causality.Parameter && o.getVariability() == ModelDescription.Variability.Tunable); + } + + + public static Predicate inPhase() { + return o -> (o.getCausality() == Fmi3Causality.Input && o.getInitial() == ModelDescription.Initial.Calculated || + o.getCausality() == Fmi3Causality.Parameter && o.getVariability() == ModelDescription.Variability.Tunable); + } +} diff --git a/plugins/initializer/src/main/java/org/intocps/maestro/plugin/initializer/RelationsPredicates.java b/plugins/initializer/src/main/java/org/intocps/maestro/plugin/initializer/RelationsPredicates.java index 4568ba9c1..4fa44aae5 100644 --- a/plugins/initializer/src/main/java/org/intocps/maestro/plugin/initializer/RelationsPredicates.java +++ b/plugins/initializer/src/main/java/org/intocps/maestro/plugin/initializer/RelationsPredicates.java @@ -19,11 +19,11 @@ public static Predicate inputToOutput() { } public static Predicate inputSource() { - return o -> (o.getSource().scalarVariable.getScalarVariable().causality == Fmi2ModelDescription.Causality.Input); + return o -> (o.getSource().has( Fmi2ModelDescription.Causality.Input)); } public static Predicate outputSource() { - return o -> (o.getSource().scalarVariable.getScalarVariable().causality == Fmi2ModelDescription.Causality.Output); + return o -> (o.getSource().has( Fmi2ModelDescription.Causality.Output)); } } \ No newline at end of file diff --git a/plugins/initializer/src/main/java/org/intocps/maestro/plugin/initializer/TopologicalPlugin.java b/plugins/initializer/src/main/java/org/intocps/maestro/plugin/initializer/TopologicalPlugin.java index 6e6f430dd..966246505 100644 --- a/plugins/initializer/src/main/java/org/intocps/maestro/plugin/initializer/TopologicalPlugin.java +++ b/plugins/initializer/src/main/java/org/intocps/maestro/plugin/initializer/TopologicalPlugin.java @@ -15,7 +15,7 @@ public class TopologicalPlugin { //This method find the right instantiation order using the topological sort plugin. The plugin is in scala so some mapping between java and // scala is needed - public List findInstantiationOrder(Set relations, + public List findInstantiationOrder(Set relations, Set filterTargets) throws ExpandException { TarjanGraph graphSolver = getTarjanGraph(relations, filterTargets); @@ -25,27 +25,27 @@ public List findInstantiationOrder(Set) JavaConverters + return (List) JavaConverters .seqAsJavaListConverter(((AcyclicDependencyResult) topologicalOrderToInstantiate).totalOrder()).asJava(); } - public List> findInstantiationOrderStrongComponents(Set relations, + public List> findInstantiationOrderStrongComponents(Set relations, Set filterTargets) { TarjanGraph graphSolver = getTarjanGraph(relations, filterTargets); var topologicalOrderToInstantiate = graphSolver.topologicalSCC(); - Map javaMap = - (Map) JavaConverters.mapAsJavaMapConverter(topologicalOrderToInstantiate).asJava(); + Map javaMap = + (Map) JavaConverters.mapAsJavaMapConverter(topologicalOrderToInstantiate).asJava(); return groupSCC(javaMap); } - private List> groupSCC(Map javaMap) { - List> sccs = new Vector<>(); + private List> groupSCC(Map javaMap) { + List> sccs = new Vector<>(); var list = javaMap.entrySet().stream().collect(Collectors.groupingBy(o -> o.getValue())); javaMap.values().stream().sorted().forEach(scc -> { - HashSet variablesSet = new HashSet<>(); + HashSet variablesSet = new HashSet<>(); list.get(scc).forEach(v -> variablesSet.add(v.getKey())); sccs.add(variablesSet); }); @@ -62,9 +62,9 @@ private TarjanGraph getTarjanGraph(Set relat .outputSource().and(o -> externalRelations.stream().anyMatch(i -> o.getSource() == i.getSource())))) .collect(Collectors.toList()); - var edges = new Vector>(); + var edges = new Vector>(); externalRelations.forEach(o -> o.getTargets().values().forEach(e -> { - if (filterTargets != null && filterTargets.contains(e.getScalarVariable().getInstance())) { return; } + if (filterTargets != null && filterTargets.contains(e.getInstance())) { return; } edges.add(new Edge11(o.getSource(), e, o.getOrigin())); })); internalRelations.forEach(o -> o.getTargets().values().forEach(e -> { diff --git a/plugins/initializer/src/main/java/org/intocps/maestro/plugin/initializer/spec/StatementGeneratorContainer.java b/plugins/initializer/src/main/java/org/intocps/maestro/plugin/initializer/spec/StatementGeneratorContainer.java index 13965e9f2..f2ed43fe6 100644 --- a/plugins/initializer/src/main/java/org/intocps/maestro/plugin/initializer/spec/StatementGeneratorContainer.java +++ b/plugins/initializer/src/main/java/org/intocps/maestro/plugin/initializer/spec/StatementGeneratorContainer.java @@ -39,8 +39,8 @@ public class StatementGeneratorContainer { private final Map intArrays = new HashMap<>(); private final Map stringArrays = new HashMap<>(); - private final Map convergenceRefArray = new HashMap<>(); - private final Map loopValueArray = new HashMap<>(); + private final Map convergenceRefArray = new HashMap<>(); + private final Map loopValueArray = new HashMap<>(); private final EnumMap typesStringMap = new EnumMap<>(Fmi2ModelDescription.Types.class) { { @@ -154,8 +154,8 @@ public PStm exitInitializationMode(String instanceName) { (LexIdentifier) createLexIdentifier.apply("exitInitializationMode").clone(), null)); } - public List createFixedPointIteration(List loopVariables, int iterationMax, int sccNumber, - Fmi2SimulationEnvironment env) throws ExpandException { + public List createFixedPointIteration(List loopVariables, int iterationMax, + int sccNumber, Fmi2SimulationEnvironment env) throws ExpandException { LexIdentifier end = newAIdentifier(String.format("end%d", sccNumber)); LexIdentifier start = newAIdentifier(String.format("start%d", sccNumber)); List statements = new Vector<>(); @@ -164,13 +164,13 @@ public List createFixedPointIteration(List o.scalarVariable.getScalarVariable().causality == Fmi2ModelDescription.Causality.Output && - o.scalarVariable.scalarVariable.getType().type == Fmi2ModelDescription.Types.Real).collect(Collectors.toList()); + var outputs = loopVariables.stream() + .filter(o -> o.has(Fmi2ModelDescription.Causality.Output) && o.getType().hasType(Fmi2ModelDescription.Types.Real)) + .collect(Collectors.toList()); - for (Fmi2SimulationEnvironment.Variable output : outputs) { - var lexIdentifier = createLexIdentifier.apply( - "Ref" + output.scalarVariable.instance.getText() + output.scalarVariable.scalarVariable.getName() + "ValueRef" + - output.scalarVariable.scalarVariable.getValueReference()); + for (org.intocps.maestro.framework.fmi2.RelationVariable output : outputs) { + var lexIdentifier = + createLexIdentifier.apply("Ref" + output.getInstance().getText() + output.getName() + "ValueRef" + output.getValueReference()); statements.add(createReferenceArray(output, lexIdentifier)); //Create map to test references against convergenceRefArray.put(output, lexIdentifier); @@ -204,28 +204,29 @@ public List createFixedPointIteration(List performLoopActions(List loopVariables, Fmi2SimulationEnvironment env) { + private List performLoopActions(List loopVariables, Fmi2SimulationEnvironment env) { List LoopStatements = new Vector<>(); loopVariables.stream().forEach(variable -> { - long[] scalarValueIndices = new long[]{variable.scalarVariable.scalarVariable.valueReference}; + long[] scalarValueIndices = new long[]{variable.getValueReference()}; //All members of the same set has the same causality, type and comes from the same instance - if (variable.scalarVariable.scalarVariable.causality == Fmi2ModelDescription.Causality.Output) { - var lexId = createLexIdentifier.apply(variable.scalarVariable.instance + variable.scalarVariable.getScalarVariable().name); - LoopStatements.add(newALocalVariableStm( - newAVariableDeclaration(lexId, newAArrayType(fmiTypeToMablType(variable.scalarVariable.scalarVariable.getType().type)), 1, - null))); + if (variable.has(Fmi2ModelDescription.Causality.Output)) { + var lexId = createLexIdentifier.apply(variable.getInstance().getText() + variable.getName()); + LoopStatements.add(newALocalVariableStm(newAVariableDeclaration(lexId, newAArrayType(variable.getType().getLexType()), 1, null))); loopValueArray.put(variable, lexId); try { - LoopStatements.addAll(getValueStm(variable.scalarVariable.instance.getText(), lexId, scalarValueIndices, - variable.scalarVariable.scalarVariable.getType().type)); + LoopStatements.addAll(getValueStm(variable.getInstance().getText(), lexId, scalarValueIndices, + ((Fmi2ModelDescription.Type) variable.getType().get()).type)); } catch (ExpandException e) { e.printStackTrace(); } } else { try { - LoopStatements.addAll(setValueOnPortStm(variable.scalarVariable.instance, variable.scalarVariable.scalarVariable.getType().type, - Collections.singletonList(variable.scalarVariable.scalarVariable), scalarValueIndices, env)); + LoopStatements.addAll(setValueOnPortStm(variable.getInstance(), + ((Fmi2ModelDescription.Type)variable.getType().get()).type, + Collections.singletonList( + (Fmi2ModelDescription.ScalarVariable) variable.getScalarVariable(Fmi2ModelDescription.ScalarVariable.class)), + scalarValueIndices, env)); } catch (ExpandException e) { e.printStackTrace(); } @@ -257,17 +258,15 @@ public List setValueOnPortStm(LexIdentifier comp, Fmi2ModelDescription.Typ } } - private PStm createReferenceArray(Fmi2SimulationEnvironment.Variable variable, LexIdentifier lexID) throws ExpandException { + private PStm createReferenceArray(org.intocps.maestro.framework.fmi2.RelationVariable variable, LexIdentifier lexID) throws ExpandException { List args = new ArrayList<>(); - args.add(getDefaultArrayValue(variable.scalarVariable.scalarVariable.getType().type)); + args.add(variable.getType().getLexDefaultValue()); PInitializer initializer = MableAstFactory.newAArrayInitializer(args); - return newALocalVariableStm( - newAVariableDeclaration(lexID, newAArrayType(fmiTypeToMablType(variable.scalarVariable.scalarVariable.getType().type)), 1, - initializer)); + return newALocalVariableStm(newAVariableDeclaration(lexID, newAArrayType(variable.getType().getLexType()), 1, initializer)); } - private List updateReferenceArray(List outputPorts) { + private List updateReferenceArray(List outputPorts) { List updateStmts = new Vector<>(); outputPorts.forEach(o -> { var referenceValue = convergenceRefArray.get(o); @@ -279,7 +278,7 @@ private List updateReferenceArray(List } //This method should check if all output of the Fixed Point iteration have stabilized/converged - private List checkLoopConvergence(List outputPorts, LexIdentifier doesConverge) { + private List checkLoopConvergence(List outputPorts, LexIdentifier doesConverge) { LexIdentifier index = newAIdentifier("index"); List result = new Vector<>(); result.add(newALocalVariableStm(newAVariableDeclaration(index, newAIntNumericPrimitiveType(), newAExpInitializer(newAIntLiteralExp(0))))); @@ -497,7 +496,8 @@ public List setRealsStm(String instanceName, long[] longs, double[] double LexIdentifier valueArray = findArrayOfSize(realArrays, longs.length); // The array does not exist. Create it and initialize it. if (valueArray == null) { - var value = createArray(doubles.length, valueLocator, realArrayVariableName.apply(longs.length), Fmi2ModelDescription.Types.Real, realArrays); + var value = + createArray(doubles.length, valueLocator, realArrayVariableName.apply(longs.length), Fmi2ModelDescription.Types.Real, realArrays); valueArray = value.getLeft(); statements.addAll(value.getRight()); } else { @@ -548,7 +548,8 @@ public List setIntegersStm(String instanceName, long[] longs, int[] ints) LexIdentifier valueArray = findArrayOfSize(intArrays, longs.length); // The array does not exist. Create it and initialize it. if (valueArray == null) { - var value = createArray(ints.length, valueLocator, intArrayVariableName.apply(longs.length), Fmi2ModelDescription.Types.Integer, intArrays); + var value = + createArray(ints.length, valueLocator, intArrayVariableName.apply(longs.length), Fmi2ModelDescription.Types.Integer, intArrays); valueArray = value.getLeft(); statements.addAll(value.getRight()); } else { @@ -656,7 +657,8 @@ private Object getNewValue(Fmi2ModelDescription.ScalarVariable sv, ModelConnecti return newVal; } - public List getValueStm(String instanceName, LexIdentifier valueArray, long[] longs, Fmi2ModelDescription.Types type) throws ExpandException { + public List getValueStm(String instanceName, LexIdentifier valueArray, long[] longs, + Fmi2ModelDescription.Types type) throws ExpandException { if (!instancesLookupDependencies) { instancesLookupDependencies = true; } diff --git a/plugins/initializer/src/main/kotlin/Initializer.kt b/plugins/initializer/src/main/kotlin/Initializer.kt index 6aceca8ee..0d0146faa 100644 --- a/plugins/initializer/src/main/kotlin/Initializer.kt +++ b/plugins/initializer/src/main/kotlin/Initializer.kt @@ -9,6 +9,7 @@ import org.intocps.maestro.ast.node.* import org.intocps.maestro.core.Framework import org.intocps.maestro.core.messages.IErrorReporter import org.intocps.maestro.fmi.Fmi2ModelDescription +import org.intocps.maestro.fmi.fmi3.* import org.intocps.maestro.framework.core.IRelation import org.intocps.maestro.framework.core.ISimulationEnvironment import org.intocps.maestro.framework.core.RelationVariable @@ -17,6 +18,7 @@ import org.intocps.maestro.framework.fmi2.InvalidVariableStringException import org.intocps.maestro.framework.fmi2.ModelConnection import org.intocps.maestro.framework.fmi2.api.FmiBuilder import org.intocps.maestro.framework.fmi2.api.FmiBuilder.ArrayVariable +import org.intocps.maestro.framework.fmi2.api.FmiBuilder.SimulationInstance import org.intocps.maestro.framework.fmi2.api.mabl.* import org.intocps.maestro.framework.fmi2.api.mabl.scoping.DynamicActiveBuilderScope import org.intocps.maestro.framework.fmi2.api.mabl.scoping.ScopeFmi2Api @@ -97,7 +99,7 @@ class Initializer : BasicMaestroExpansionPlugin { ), MableAstFactory.newAVoidType() ) - private val portsAlreadySet = HashMap>() + private val portsAlreadySet = HashMap, Set>() private val topologicalPlugin: TopologicalPlugin private val initializationPrologQuery: InitializationPrologQuery var config: InitializationConfig? = null @@ -359,11 +361,7 @@ class Initializer : BasicMaestroExpansionPlugin { math ) -// val algorithm = builder.buildRaw() as SBlockStm -// algorithm.apply(ToParExp()) -// -// -// algorithm.body + } catch (e: Exception) { throw ExpandException("Internal error: ", e) } @@ -422,11 +420,12 @@ class Initializer : BasicMaestroExpansionPlugin { //Set variables for all components in IniPhase setComponentsVariables(fmuInstances, PhasePredicates.iniPhase(), builder) + setInstanceVariables(fmu3Instances, PhasePredicates3.iniPhase(), builder) //Enter initialization Mode logger.debug("Enter initialization Mode") fmuInstances.values.forEach(Consumer { fmu: ComponentVariableFmi2Api -> fmu.enterInitializationMode() }) - //FIXME: missing parameters + val fmi3ToloranceDefined = dynamicScope.store("absoluteTolerance", this.config!!.absoluteTolerance) fmu3Instances.values.forEach(Consumer { fmu: InstanceVariableFmi3Api -> fmu.enterInitializationMode( @@ -438,6 +437,8 @@ class Initializer : BasicMaestroExpansionPlugin { ) }) + + //TODO not sure what this is - stabilization maybe val instructions = instantiationOrder.map { i -> createInitInstructions( i.toList(), dynamicScope, fmuInstances, booleanLogic, math @@ -459,9 +460,11 @@ class Initializer : BasicMaestroExpansionPlugin { stabilisationScope.activate() stabilisationScope.leave(); } + //TODO end setRemainingInputs(fmuInstances, builder) + setRemainingInputs3(fmu3Instances, builder) //Exit initialization Mode fmuInstances.values.forEach(Consumer { obj: ComponentVariableFmi2Api -> obj.exitInitializationMode() }) @@ -527,76 +530,7 @@ class Initializer : BasicMaestroExpansionPlugin { booleanLogic, math ); -// -// // Create bindings -// FromMaBLToMaBLAPI.createBindings(fmuInstances, env) -// -// this.config = config as InitializationConfig -// -// this.modelParameters = config.modelParameters -// this.envParameters = config.envParameters -// -// // Convergence related variables -// absoluteTolerance = dynamicScope.store("absoluteTolerance", this.config!!.absoluteTolerance) -// relativeTolerance = dynamicScope.store("relativeTolerance", this.config!!.relativeTolerance) -// maxConvergeAttempts = dynamicScope.store("maxConvergeAttempts", this.config!!.maxIterations) -// -// logger.debug("Setup experiment for all components") -// fmuInstances.values.forEach { i -> -// i.setupExperiment( -// externalStartTime, -// externalEndTime, -// this.config!!.relativeTolerance -// ) -// }; -// val connections = createConnections(env, fmuInstances) -// -// //Find the right order to instantiate dependentPorts and make sure where doesn't exist any cycles in the connections -// val instantiationOrder = topologicalPlugin.findInstantiationOrderStrongComponents(connections) -// -// //Verification against prolog should only be done if it turned on and there is no loops -// if (this.config!!.verifyAgainstProlog && instantiationOrder.all { i -> i.size == 1 }) -// initializationPrologQuery.initializationOrderIsValid(instantiationOrder.flatten(), connections) -// -// -// //Set variables for all components in IniPhase -// setComponentsVariables(fmuInstances, PhasePredicates.iniPhase(), builder) -// -// //Enter initialization Mode -// logger.debug("Enter initialization Mode") -// fmuInstances.values.forEach(Consumer { fmu: ComponentVariableFmi2Api -> fmu.enterInitializationMode() }) -// -// val instructions = instantiationOrder.map { i -> -// createInitInstructions( -// i.toList(), -// dynamicScope, -// fmuInstances, -// booleanLogic, -// math -// ) -// } -// var stabilisationScope: ScopeFmi2Api? = null -// var stabilisationLoop: IntVariableFmi2Api? = null -// if (this.config!!.stabilisation) { -// stabilisationLoop = dynamicScope.store("stabilisation_loop", this.config!!.maxIterations) -// stabilisationScope = dynamicScope.enterWhile( -// stabilisationLoop!!.toMath().greaterThan(IntExpressionValue.of(0)) -// ) -// } -// -// instructions.forEach { i -> i.perform() } -// -// if (stabilisationScope != null) { -// stabilisationLoop!!.decrement(); -// stabilisationScope.activate() -// stabilisationScope.leave(); -// } -// -// -// setRemainingInputs(fmuInstances, builder) -// -// //Exit initialization Mode -// fmuInstances.values.forEach(Consumer { obj: ComponentVariableFmi2Api -> obj.exitInitializationMode() }) + val algorithm = builder.buildRaw() as SBlockStm algorithm.apply(ToParExp()) @@ -615,7 +549,7 @@ class Initializer : BasicMaestroExpansionPlugin { try { val scalarVariables = comp.modelDescription.scalarVariables val inputsScalars = scalarVariables.filter { x -> - PhasePredicates.inPhase().test(x) && !portSet(comp, x) + PhasePredicates.inPhase().test(x) && !isPortSet(comp, x) } val ports = @@ -631,10 +565,36 @@ class Initializer : BasicMaestroExpansionPlugin { } } - private fun portSet(comp: ComponentVariableFmi2Api, x: Fmi2ModelDescription.ScalarVariable?): Boolean { + private fun setRemainingInputs3( + fmuInstances: Map, builder: MablApiBuilder + ) { + for (comp in fmuInstances.values) { + try { + val scalarVariables = comp.modelDescription.getScalarVariables() + val inputsScalars = scalarVariables.filter { x -> + PhasePredicates3.inPhase().test(x.variable) && !isPortSet(comp, x.variable) + } + + val ports = + comp.getPorts( + *inputsScalars.stream() + .mapToInt { sv -> Math.toIntExact(sv.variable.getValueReferenceAsLong()) } + .toArray()) + + for (port in ports) { + setParameterOnPort(port, comp, builder) + } + } catch (e: Exception) { + throw ExpandException("Initializer failed to read scalarvariables", e) + } + } + } + + private fun isPortSet(comp: SimulationInstance, x: Any?): Boolean { return if (portsAlreadySet.containsKey(comp)) portsAlreadySet.getValue(comp).contains(x) else false } + private fun setParameterOnPort( port: PortFmi2Api, comp: ComponentVariableFmi2Api, builder: MablApiBuilder ) { @@ -691,7 +651,69 @@ class Initializer : BasicMaestroExpansionPlugin { addToPortsAlreadySet(comp, port.scalarVariable) } - private fun addToPortsAlreadySet(comp: ComponentVariableFmi2Api, port: Fmi2ModelDescription.ScalarVariable) { + private fun setParameterOnPort( + port: PortFmi3Api, comp: InstanceVariableFmi3Api, builder: MablApiBuilder + ) { + val fmuName = comp.name +// var value = findUseDefault(fmuName, port.scalarVariable, modelParameters) + + val useEnvForPort = this.envParameters?.contains(port.multiModelScalarVariableName) + if (useEnvForPort == null || !useEnvForPort) { + + var staticValue = findParameterOrDefault(fmuName, port.scalarVariable, modelParameters) + when (port.scalarVariable.variable.typeIdentifier!!) { + Fmi3TypeEnum.BooleanType -> comp.set(port, BooleanExpressionValue.of(staticValue as Boolean)) + Fmi3TypeEnum.Float64Type -> { + + if (port.scalarVariable.variable.isScalar()) { + staticValue = (staticValue as List).get(0) + + + if (staticValue is Int) { + staticValue = staticValue.toDouble() + } + val b: Double = staticValue as Double + comp.set(port, DoubleExpressionValue.of(b)) + } + } + + Fmi3TypeEnum.Int32Type -> comp.set(port, IntExpressionValue.of(staticValue as Int)) + Fmi3TypeEnum.StringType -> comp.set(port, StringExpressionValue.of(staticValue as String)) + Fmi3TypeEnum.EnumerationType -> throw ExpandException("Enumeration not supported") + else -> throw ExpandException("Not known type") + } + } else { + when (port.scalarVariable.variable.typeIdentifier!!) { + Fmi3TypeEnum.BooleanType -> { + val v = builder.executionEnvironment.getBool(port.multiModelScalarVariableName) + comp.set(port, v) + } + + Fmi3TypeEnum.Float64Type -> { + val v = builder.executionEnvironment.getReal(port.multiModelScalarVariableName) + comp.set(port, v) + } + + Fmi3TypeEnum.Int32Type -> { + val v = builder.executionEnvironment.getInt(port.multiModelScalarVariableName) + comp.set(port, v) + } + + Fmi3TypeEnum.StringType -> { + val v = builder.executionEnvironment.getString(port.multiModelScalarVariableName) + comp.set(port, v) + } + + Fmi3TypeEnum.EnumerationType -> throw ExpandException("Enumeration not supported") + else -> throw ExpandException("Not known type") + } + } + + + addToPortsAlreadySet(comp, port.scalarVariable) + } + + private fun addToPortsAlreadySet(comp: FmiBuilder.SimulationInstance, port: Any?) { if (portsAlreadySet.containsKey(comp)) { portsAlreadySet.replace(comp, portsAlreadySet.getValue(comp).plus(port)) } else { @@ -700,7 +722,7 @@ class Initializer : BasicMaestroExpansionPlugin { } private fun createInitInstructions( - ports: List, + ports: List>, dynamicScope: DynamicActiveBuilderScope, fmuInstances: Map, booleanLogic: BooleanBuilderFmi2Api, @@ -712,8 +734,8 @@ class Initializer : BasicMaestroExpansionPlugin { } else { val actions = ports.map { c -> fmuCoSimInstruction(fmuInstances, c) } val outputPorts = - ports.filter { p -> p.scalarVariable.scalarVariable.causality == Fmi2ModelDescription.Causality.Output } - .map { i -> i.scalarVariable } + ports.filter { p -> p.has(Fmi2ModelDescription.Causality.Output) } + .map { i -> i } LoopSimInstruction( dynamicScope, maxConvergeAttempts!!, @@ -728,22 +750,22 @@ class Initializer : BasicMaestroExpansionPlugin { } private fun fmuCoSimInstruction( - fmuInstances: Map, p: Fmi2SimulationEnvironment.Variable + fmuInstances: Map, p: org.intocps.maestro.framework.fmi2.RelationVariable ): FMUCoSimInstruction { - val fmu = fmuInstances.values.find { x -> x.environmentName.equals(p.scalarVariable.instance.text) } + val instance = fmuInstances.values.find { x -> x.environmentName.equals(p.getInstance().text) } // val fmu = fmuInstances.getValue(p.scalarVariable.instance.text) - if (fmu != null) { - val port = fmu.getPort(p.scalarVariable.scalarVariable.name) - return when (p.scalarVariable.scalarVariable.causality) { - Fmi2ModelDescription.Causality.Output -> GetInstruction(fmu, port, false) - Fmi2ModelDescription.Causality.Input -> { - addToPortsAlreadySet(fmu, port.scalarVariable) - SetInstruction(fmu, port) + if (instance != null) { + val port = instance.getPort(p.name) + return when { + p.has(Fmi2ModelDescription.Causality.Output) -> GetInstruction(instance, port, false) + p.has(Fmi2ModelDescription.Causality.Input) -> { + addToPortsAlreadySet(instance, port.scalarVariable) + SetInstruction(instance, port) } else -> throw ExpandException("Internal error") } - } else throw ExpandException("Failed to retrieve FMUInstance by name: " + p.scalarVariable.instance.text) + } else throw ExpandException("Failed to retrieve FMUInstance by name: " + p.name) } @@ -811,6 +833,19 @@ class Initializer : BasicMaestroExpansionPlugin { } } + private fun setInstanceVariables( + fmuInstances: Map, + predicate: Predicate, + builder: MablApiBuilder + ) { + fmuInstances.entries.forEach { (fmuName, comp) -> + for (sv in comp.modelDescription.getModelVariables().filter { i -> predicate.test(i) }) { + val port = comp.getPort(sv.name) + setParameterOnPort(port, comp, builder) + } + } + } + @Throws(ExpandException::class) private fun verifyArguments( @@ -941,6 +976,29 @@ class Initializer : BasicMaestroExpansionPlugin { return if (parameterValue != null) parameterValue.value else sv.type.start } + private fun findParameterOrDefault( + compName: String, sv: Fmi3ModelDescription.Fmi3ScalarVariable, modelParameters: List? + ): Any? { + val parameterValue = + modelParameters?.firstOrNull { x: ModelParameter -> x.variable.instance.instanceName == compName && x.variable.variable == sv.variable.name } + return if (parameterValue != null) parameterValue.value else getStartValue(sv.variable) + } + + private fun getStartValue(variable: Fmi3Variable): Any? { + return when (variable) { + is FloatVariable -> variable.start + is Int64Variable -> variable.start + is IntVariable -> variable.start + is BooleanVariable -> variable.start + is StringVariable -> variable.start + is BinaryVariable -> variable.start + is EnumerationVariable -> variable.start + is ClockVariable -> null + else -> null + + } + } + // /** // * This functions either returns null if the parameter has a value or it returns the model description start value // */ diff --git a/plugins/jacobianstepbuilder/src/main/java/org/intocps/maestro/plugin/JacobianStepBuilder.java b/plugins/jacobianstepbuilder/src/main/java/org/intocps/maestro/plugin/JacobianStepBuilder.java index f010b1a4b..10be060b4 100644 --- a/plugins/jacobianstepbuilder/src/main/java/org/intocps/maestro/plugin/JacobianStepBuilder.java +++ b/plugins/jacobianstepbuilder/src/main/java/org/intocps/maestro/plugin/JacobianStepBuilder.java @@ -672,8 +672,8 @@ private PortFmi2Api getSwapSourcePort(PortFmi2Api port, Set r.getTargets().values().stream().anyMatch(v -> v.toString().equals(port.getMultiModelScalarVariableNameWithoutFmu()))) .findFirst(); if (relation.isPresent()) { - String source = relation.get().getSource().scalarVariable.instance.getText(); - sourcePort = fmuInstances.get(source).getPort(relation.get().getSource().scalarVariable.scalarVariable.getName()); + String source = relation.get().getSource().getInstance().getText(); + sourcePort = fmuInstances.get(source).getPort(relation.get().getSource().getName()); } return sourcePort; } @@ -685,7 +685,7 @@ private ModelSwapInfo getSwapSourceInfo(PortFmi2Api port, Set r.getTargets().values().stream().anyMatch(v -> v.toString().equals(port.getMultiModelScalarVariableNameWithoutFmu()))) .findFirst(); if (relation.isPresent()) { - String source = relation.get().getSource().scalarVariable.instance.getText(); + String source = relation.get().getSource().getInstance().getText(); Optional> infoEntry = env.getModelSwaps().stream().filter(e -> e.getValue().swapInstance.equals(source)).findFirst(); if (infoEntry.isPresent()) { diff --git a/plugins/verificationsuite/src/main/java/org/intocps/maestro/plugin/verificationsuite/graph/GraphDrawer.java b/plugins/verificationsuite/src/main/java/org/intocps/maestro/plugin/verificationsuite/graph/GraphDrawer.java index 73b51ba37..8827fee85 100644 --- a/plugins/verificationsuite/src/main/java/org/intocps/maestro/plugin/verificationsuite/graph/GraphDrawer.java +++ b/plugins/verificationsuite/src/main/java/org/intocps/maestro/plugin/verificationsuite/graph/GraphDrawer.java @@ -6,6 +6,7 @@ import guru.nidi.graphviz.engine.Graphviz; import guru.nidi.graphviz.model.MutableGraph; import org.intocps.maestro.framework.fmi2.Fmi2SimulationEnvironment; +import org.intocps.maestro.framework.fmi2.RelationVariable; import java.io.File; import java.io.IOException; @@ -16,8 +17,8 @@ import static guru.nidi.graphviz.model.Factory.mutNode; public class GraphDrawer { - private String getInstanceName(Fmi2SimulationEnvironment.Variable o) { - return o.scalarVariable.instance.getText() + "." + o.scalarVariable.scalarVariable.getName(); + private String getInstanceName(RelationVariable o) { + return o.getInstance().getText() + "." + o.getName(); } public void plotGraph(Set relations, String name) throws IOException { diff --git a/plugins/verificationsuite/src/main/java/org/intocps/maestro/plugin/verificationsuite/prologverifier/InitializationPrologQuery.java b/plugins/verificationsuite/src/main/java/org/intocps/maestro/plugin/verificationsuite/prologverifier/InitializationPrologQuery.java index 6618742c4..bfd83c0a4 100644 --- a/plugins/verificationsuite/src/main/java/org/intocps/maestro/plugin/verificationsuite/prologverifier/InitializationPrologQuery.java +++ b/plugins/verificationsuite/src/main/java/org/intocps/maestro/plugin/verificationsuite/prologverifier/InitializationPrologQuery.java @@ -2,6 +2,7 @@ import com.ugos.jiprolog.engine.*; import org.intocps.maestro.framework.fmi2.Fmi2SimulationEnvironment; +import org.intocps.maestro.framework.fmi2.RelationVariable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -23,8 +24,7 @@ public InitializationPrologQuery() { this.prologGenerator = new PrologGenerator(); } - public boolean initializationOrderIsValid(List instantiationOrder, - Set relations) { + public boolean initializationOrderIsValid(List instantiationOrder, Set relations) { // New instance of prolog engine JIPEngine jip = new JIPEngine(); JIPTerm queryTerm = null; diff --git a/plugins/verificationsuite/src/main/java/org/intocps/maestro/plugin/verificationsuite/prologverifier/PrologGenerator.java b/plugins/verificationsuite/src/main/java/org/intocps/maestro/plugin/verificationsuite/prologverifier/PrologGenerator.java index f59a2f6df..b49599561 100644 --- a/plugins/verificationsuite/src/main/java/org/intocps/maestro/plugin/verificationsuite/prologverifier/PrologGenerator.java +++ b/plugins/verificationsuite/src/main/java/org/intocps/maestro/plugin/verificationsuite/prologverifier/PrologGenerator.java @@ -3,6 +3,7 @@ import org.intocps.maestro.ast.LexIdentifier; import org.intocps.maestro.fmi.Fmi2ModelDescription; import org.intocps.maestro.framework.fmi2.Fmi2SimulationEnvironment; +import org.intocps.maestro.framework.fmi2.RelationVariable; import org.intocps.maestro.plugin.ExpandException; import java.util.Collection; @@ -11,12 +12,11 @@ import java.util.stream.Collectors; public class PrologGenerator { - public String createInitOperationOrder(List instantiationOrder) { + public String createInitOperationOrder(List instantiationOrder) { StringBuilder initOrder = new StringBuilder(); instantiationOrder.forEach(o -> { try { - initOrder.append(String.format("%s(%s, %s),", getMethod(o), o.scalarVariable.getInstance().getText().toLowerCase(), - o.scalarVariable.getScalarVariable().getName().toLowerCase())); + initOrder.append(String.format("%s(%s, %s),", getMethod(o), o.getInstance().getText().toLowerCase(), o.getName().toLowerCase())); } catch (ExpandException e) { e.printStackTrace(); } @@ -27,7 +27,7 @@ public String createInitOperationOrder(List public String createFMUs(Set relations) { StringBuilder fmuString = new StringBuilder(); - var fmuList = relations.stream().map(o -> o.getSource().scalarVariable.getInstance()).collect(Collectors.toSet()); + var fmuList = relations.stream().map(o -> o.getSource().getInstance()).collect(Collectors.toSet()); fmuList.forEach(fmu -> { fmuString.append(String.format("fmu(%s, %s, %s),", fmu.getText().toLowerCase(), getInPorts(relations, fmu), getOutPorts(relations, fmu))); }); @@ -39,10 +39,8 @@ public String createConnections(List relatio StringBuilder connections = new StringBuilder(); relations.forEach(relation -> { relation.getTargets().values().forEach(target -> { - connections.append(String.format("connect(%s,%s, %s, %s),", relation.getSource().scalarVariable.getInstance().getText().toLowerCase(), - relation.getSource().scalarVariable.getScalarVariable().getName().toLowerCase(), - target.scalarVariable.getInstance().getText().toLowerCase(), - target.scalarVariable.getScalarVariable().getName().toLowerCase())); + connections.append(String.format("connect(%s,%s, %s, %s),", relation.getSource().getInstance().getText().toLowerCase(), + relation.getSource().getName().toLowerCase(), target.getInstance().getText().toLowerCase(), target.getName().toLowerCase())); }); }); return fixListFormat(connections).toString(); @@ -60,11 +58,10 @@ private StringBuilder fixListFormat(StringBuilder stringBuilder) { private String getInPorts(Set relations, LexIdentifier fmu) { StringBuilder inPorts = new StringBuilder(); var inputPorts = relations.stream().map(p -> p.getTargets().values()).collect(Collectors.toList()).stream().flatMap(Collection::stream) - .collect(Collectors.toSet()).stream().filter(o -> o.scalarVariable.getInstance().getText().equals(fmu.getText())) - .collect(Collectors.toSet()); + .collect(Collectors.toSet()).stream().filter(o -> o.getInstance().getText().equals(fmu.getText())).collect(Collectors.toSet()); inputPorts.forEach(port -> { - inPorts.append(String.format("port(%s, delayed),", port.scalarVariable.getScalarVariable().getName().toLowerCase())); + inPorts.append(String.format("port(%s, delayed),", port.getName().toLowerCase())); }); return fixListFormat(inPorts).toString(); @@ -76,33 +73,33 @@ private String getOutPorts(Set relations, Le .collect(Collectors.toSet()); var internalRelations = relations.stream().filter(o -> o.getOrigin() == Fmi2SimulationEnvironment.Relation.InternalOrExternal.Internal) .collect(Collectors.toSet()); - var outputPorts = externalRelations.stream().filter(p -> p.getSource().scalarVariable.getInstance() == fmu).collect(Collectors.toSet()); + var outputPorts = externalRelations.stream().filter(p -> p.getSource().getInstance() == fmu).collect(Collectors.toSet()); outputPorts.forEach(port -> { - outPorts.append(String.format("port(%s, %s),", port.getSource().scalarVariable.getScalarVariable().getName().toLowerCase(), + outPorts.append(String.format("port(%s, %s),", port.getSource().getName().toLowerCase(), getInternalDependencies(port.getSource(), internalRelations))); }); return fixListFormat(outPorts).toString(); } - private String getInternalDependencies(Fmi2SimulationEnvironment.Variable source, Set internalRelations) { + private String getInternalDependencies(RelationVariable source, Set internalRelations) { var sources = internalRelations.stream().filter(rel -> rel.getSource() == source).map(o -> o.getTargets().values()).collect(Collectors.toSet()) .stream().flatMap(Collection::stream).collect(Collectors.toSet()); StringBuilder internalConnections = new StringBuilder(); sources.forEach(s -> { - internalConnections.append(String.format("%s,", s.scalarVariable.getScalarVariable().getName().toLowerCase())); + internalConnections.append(String.format("%s,", s.getName().toLowerCase())); }); return fixListFormat(internalConnections).toString(); } - private String getMethod(Fmi2SimulationEnvironment.Variable variable) throws ExpandException { - if (variable.scalarVariable.getScalarVariable().causality == Fmi2ModelDescription.Causality.Output) { + private String getMethod(RelationVariable variable) throws ExpandException { + if (variable.has(Fmi2ModelDescription.Causality.Output)) { return "getOut"; - } else if (variable.scalarVariable.getScalarVariable().causality == Fmi2ModelDescription.Causality.Input) { + } else if (variable.has(Fmi2ModelDescription.Causality.Input)) { return "setIn"; } else { throw new ExpandException("Unknown causality of port"); diff --git a/plugins/verificationsuite/src/test/java/GraphPlotterTest.java b/plugins/verificationsuite/src/test/java/GraphPlotterTest.java index dce2278d6..e2faedcf3 100644 --- a/plugins/verificationsuite/src/test/java/GraphPlotterTest.java +++ b/plugins/verificationsuite/src/test/java/GraphPlotterTest.java @@ -51,17 +51,17 @@ public void plotGraphWithSimpleLoop() throws Exception { var variable3 = createVariable("CE", "Level", unitRelationship); var variable4 = createVariable("Tank", "Level", unitRelationship); - HashMap target1 = new HashMap<>(); - target1.put(new LexIdentifier(variable1.scalarVariable.instance.getText(), null), variable1); - HashMap target2 = new HashMap<>(); - target2.put(new LexIdentifier(variable2.scalarVariable.instance.getText(), null), variable2); - HashMap target3 = new HashMap<>(); - target3.put(new LexIdentifier(variable3.scalarVariable.instance.getText(), null), variable3); - HashMap target4 = new HashMap<>(); - target4.put(new LexIdentifier(variable4.scalarVariable.instance.getText(), null), variable4); + HashMap target1 = new HashMap<>(); + target1.put(new LexIdentifier(variable1.getInstance().getText(), null), variable1); + HashMap target2 = new HashMap<>(); + target2.put(new LexIdentifier(variable2.getInstance().getText(), null), variable2); + HashMap target3 = new HashMap<>(); + target3.put(new LexIdentifier(variable3.getInstance().getText(), null), variable3); + HashMap target4 = new HashMap<>(); + target4.put(new LexIdentifier(variable4.getInstance().getText(), null), variable4); relations.add(new Fmi2SimulationEnvironment.Relation.RelationBuilder(variable1, target2).build()); - relations.add(new Fmi2SimulationEnvironment.Relation.RelationBuilder(variable3, target2) - .setInternalOrExternal(Fmi2SimulationEnvironment.Relation.InternalOrExternal.Internal).build()); + relations.add(new Fmi2SimulationEnvironment.Relation.RelationBuilder(variable3, target2).setInternalOrExternal( + Fmi2SimulationEnvironment.Relation.InternalOrExternal.Internal).build()); relations.add(new Fmi2SimulationEnvironment.Relation.RelationBuilder(variable3, target1).build()); relations.add(new Fmi2SimulationEnvironment.Relation.RelationBuilder(variable3, target4).build()); @@ -69,10 +69,10 @@ public void plotGraphWithSimpleLoop() throws Exception { } - private Fmi2SimulationEnvironment.Variable createVariable(String fmuName, String variableName, Fmi2SimulationEnvironment unitRelationship) { + private RelationVariable createVariable(String fmuName, String variableName, Fmi2SimulationEnvironment unitRelationship) { var scalarVar = new Fmi2ModelDescription.ScalarVariable(); scalarVar.name = variableName; - return new Fmi2SimulationEnvironment.Variable(new RelationVariable(scalarVar, new LexIdentifier(fmuName, null))); + return new RelationVariable(scalarVar, scalarVar.getName(), new LexIdentifier(fmuName, null)); } } diff --git a/plugins/verificationsuite/src/test/java/PrologVerifierTest.java b/plugins/verificationsuite/src/test/java/PrologVerifierTest.java index 76dcd16c5..1ffcf02ba 100644 --- a/plugins/verificationsuite/src/test/java/PrologVerifierTest.java +++ b/plugins/verificationsuite/src/test/java/PrologVerifierTest.java @@ -71,10 +71,10 @@ public void VerifyInitializationOrderProlog() throws Exception { } */ - private Fmi2SimulationEnvironment.Variable createVariable(String fmuName, String variableName, Fmi2SimulationEnvironment unitRelationship) { + private RelationVariable createVariable(String fmuName, String variableName, Fmi2SimulationEnvironment unitRelationship) { var scalarVar = new Fmi2ModelDescription.ScalarVariable(); scalarVar.name = variableName; - return new Fmi2SimulationEnvironment.Variable(new RelationVariable(scalarVar, new LexIdentifier(fmuName, null))); + return new RelationVariable(scalarVar, scalarVar.getName(), new LexIdentifier(fmuName, null)); } } diff --git a/pom.xml b/pom.xml index 1e8896238..a2683db33 100644 --- a/pom.xml +++ b/pom.xml @@ -24,7 +24,7 @@ 11 11 2.17.1 - 1.3.6-SNAPSHOT + 1.4.0-SNAPSHOT 1.0.10 1.9.0 2.13.11 diff --git a/typechecker/src/main/resources/org/intocps/maestro/typechecker/FMI3.mabl b/typechecker/src/main/resources/org/intocps/maestro/typechecker/FMI3.mabl index 657f40d04..2c5d9bf8e 100644 --- a/typechecker/src/main/resources/org/intocps/maestro/typechecker/FMI3.mabl +++ b/typechecker/src/main/resources/org/intocps/maestro/typechecker/FMI3.mabl @@ -84,29 +84,29 @@ module FMI3Instance import FMU3State;{ /* end::getters[] */ /* tag::setters[] */ - int setFloat32(uint valueReferences[], float values[]); + int setFloat32(uint valueReferences[],int nvr, float values[],int nv); - int setFloat64(uint valueReferences[], real values[]); + int setFloat64(uint valueReferences[],int nvr, real values[],int nv); - int setInt8(uint valueReferences[], byte values[]); + int setInt8(uint valueReferences[],int nvr, byte values[],int nv); - int setUInt8(uint valueReferences[], byte values[]); + int setUInt8(uint valueReferences[],int nvr, byte values[],int nv); - int setInt16(uint valueReferences[], short values[]); + int setInt16(uint valueReferences[],int nvr, short values[],int nv); - int setUInt16(uint valueReferences[], short values[]); + int setUInt16(uint valueReferences[],int nvr, short values[],int nv); - int setInt32(uint valueReferences[], int values[]); + int setInt32(uint valueReferences[],int nvr, int values[],int nv); - int setUInt32(uint valueReferences[], int values[]); + int setUInt32(uint valueReferences[],int nvr, int values[],int nv); - int setInt64(uint valueReferences[], long values[]); + int setInt64(uint valueReferences[],int nvr, long values[],int nv); - int setUInt64(uint valueReferences[], long values[]); + int setUInt64(uint valueReferences[],int nvr, long values[],int nv); - int setBoolean(uint valueReferences[], bool values[]); + int setBoolean(uint valueReferences[],int nvr, bool values[],int nv); - int setString(uint valueReferences[], string values[]); + int setString(uint valueReferences[],int nvr, string values[],int nv); int setBinary(uint valueReferences[], long sizes[], byte array_name[][]); /* end::setters[] */ From 671246b1429512edd511cf2ee0f2efc1d6f9e2a7 Mon Sep 17 00:00:00 2001 From: Nestor Date: Thu, 2 Nov 2023 14:37:35 +0100 Subject: [PATCH 29/54] all the missing functions added to Fmi3Interpreter (except setBinary for now) Signed-off-by: Nestor --- .idea/codeStyles/Project.xml | 29 - .idea/saveactions_settings.xml | 18 - .../framework/fmi2/api/FmiBuilder.java | 2 +- .../variables/InstanceVariableFmi3Api.java | 1 - .../extensions/fmi3/Fmi3Interpreter.java | 152 +++- maestro/outputs.csv | 102 +++ maestro/spec.mabl | 664 ++++++++++++++++++ maestro/spec.runtime.json | 10 + .../org/intocps/maestro/typechecker/FMI3.mabl | 8 +- 9 files changed, 931 insertions(+), 55 deletions(-) delete mode 100644 .idea/saveactions_settings.xml create mode 100644 maestro/outputs.csv create mode 100644 maestro/spec.mabl create mode 100644 maestro/spec.runtime.json diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index 8688e3c92..1bec35e57 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -1,37 +1,8 @@ -