All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.javafmi.proxy.v21.Fmu Maven / Gradle / Ivy

Go to download

javaFMI is a Java Library for the functional mock-up interface (or FMI). FMI defines a standardized interface to be used in computer simulations. The FMI Standard has beed developed by a large number of software companies and research centers that have worked in a cooperation project under the name of MODELISAR. This library addresses the connection of a java application with a FMU (functional mock-up unit).

There is a newer version: 2.26.5
Show newest version
/*
 *  Copyright 2013-2016 SIANI - ULPGC
 *
 *  This File is part of JavaFMI Project
 *
 *  JavaFMI Project is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as published by
 *  the Free Software Foundation, either version 3 of the License.
 *
 *  JavaFMI Project is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  GNU Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with JavaFMI. If not, see .
 */

package org.javafmi.proxy.v21;

import com.sun.jna.*;
import com.sun.jna.ptr.PointerByReference;
import org.javafmi.kernel.OS;
import org.javafmi.proxy.FmiProxyV21;
import org.javafmi.proxy.MethodExecutionException;
import org.javafmi.proxy.NativeBoolean;
import org.javafmi.proxy.Status;

import java.util.HashMap;
import java.util.Map;

public class Fmu {

	private final NativeLibrary instance;
	private final Map functions;
	private Pointer component;
	private String[] functionNames = {"Instantiate", "FreeInstance", "SetDebugLogging", "SetupExperiment", "EnterInitializationMode", "ExitInitializationMode", "Terminate", "Reset", "GetReal",
			"GetInteger", "GetBoolean", "GetString", "SetReal", "SetInteger", "SetBoolean", "SetString", "GetNextEventTime", "GetFMUstate", "SetFMUstate", "FreeFMUstate", "SerializedFMUstateSize",
			"SerializeFMUstate", "DeSerializeFMUstate", "NewDiscreteStates", "GetDirectionalDerivative", "SetRealInputDerivatives", "GetRealOutputDerivatives", "DoStep", "HybridDoStep", "CancelStep",
			"GetStatus", "GetRealStatus", "GetIntegerStatus", "GetBooleanStatus", "GetStringStatus"};

	public Fmu(String libraryPath, String generationTool) {
		instance = getInstance(libraryPath, generationTool);
		functions = loadFmiFunctions(instance);
	}

	private NativeLibrary getInstance(String libraryPath, String generationTool) {
		int RTLD_NOW = 0x00002, RTLD_DEEPBIND = 0x00008;
		Map options = new HashMap<>();
		if (OS.isLinux32() || OS.isLinux64()) options.put(Library.OPTION_OPEN_FLAGS, RTLD_NOW | RTLD_DEEPBIND);
		return NativeLibrary.getInstance(libraryPath, options);
	}

	private Map loadFmiFunctions(NativeLibrary instance) {
		Map result = new HashMap<>();
		for (String functionName : functionNames)
			try {
				result.put(functionName, instance.getFunction(fmi21(functionName)));
			} catch (UnsatisfiedLinkError e) {
				System.err.println("This FMU is not fully FMI V2.1 hybrid compliant, function not found: " + fmi21(functionName));
			}
		return result;
	}

	public void instantiate(String modelName, int fmiType, String guID, String resourcesLocation, CallbackFunctions callbacks, boolean visible, boolean loggingOn) {
		component = invoke("Instantiate")
				.with(modelName, fmiType, guID, resourcesLocation, callbacks, visible, loggingOn).asPointer();
		if (component == null)
			throw new MethodExecutionException("Impossible to instantiate " + modelName + " fmi2Instantiate returns null");
	}

	public void free() {
		invoke("FreeInstance").with(component).asVoid();
		instance.dispose();
	}

	public int setDebugLogging(boolean loggingOn, String... categories) {
		return invoke("SetDebugLogging").with(component, loggingOn, categories.length, categories).asInt();
	}

	public int setUpExperiment(boolean toleranceDefined, double tolerance, double startTime, boolean stopTimeDefined, double stopTime) {
		return invoke("SetupExperiment").with(component, toleranceDefined, tolerance, startTime, stopTimeDefined, stopTime).asInt();
	}

	public int enterInitializationMode() {
		return invoke("EnterInitializationMode").with(component).asInt();
	}

	public int exitInitializationMode() {
		return invoke("ExitInitializationMode").with(component).asInt();
	}

	public int terminate() {
		return invoke("Terminate").with(component).asInt();
	}

	public int reset() {
		return invoke("Reset").with(component).asInt();
	}

	public double[] getReal(int... valueReferences) {
		double[] doubleValues = new double[valueReferences.length];
		int status = invoke("GetReal").with(component, valueReferences, valueReferences.length, doubleValues).asInt();
		if (Status.translateStatus(status) != Status.OK)
			throw new RuntimeException("There was an error getting a variable inside the FMU");
		return doubleValues;
	}

	public int[] getInteger(int... valueReferences) {
		int[] integerValues = new int[valueReferences.length];
		int status = invoke("GetInteger").with(component, valueReferences, valueReferences.length, integerValues).asInt();
		if (Status.translateStatus(status) != Status.OK)
			throw new RuntimeException("There was an error getting a variable inside the FMU");
		return integerValues;
	}

	public boolean[] getBoolean(int... valueReferences) {
		int[] booleanValues = new int[valueReferences.length];
		int status = invoke("GetBoolean").with(component, valueReferences, valueReferences.length, booleanValues).asInt();
		if (Status.translateStatus(status) != Status.OK)
			throw new RuntimeException("There was an error getting a variable inside the FMU");
		boolean[] result = new boolean[booleanValues.length];
		for (int i = 0; i < result.length; i++) {
			result[i] = NativeBoolean.getBooleanFor((byte) booleanValues[i]);
		}
		return result;
	}

	public String[] getString(int... valueReferences) {
		String[] stringValues = new String[valueReferences.length];
		int status = invoke("GetString").with(component, valueReferences, valueReferences.length, stringValues).asInt();
		if (Status.translateStatus(status) != Status.OK)
			throw new RuntimeException("There was an error getting a variable inside the FMU");
		return stringValues;
	}

	public int setReal(int[] valueReferences, double[] values) {
		return invoke("SetReal").with(component, valueReferences, valueReferences.length, values).asInt();
	}

	public int setInteger(int[] valueReferences, int[] intValues) {
		return invoke("SetInteger").with(component, valueReferences, valueReferences.length, intValues).asInt();
	}

	public int setBoolean(int[] valueReferences, boolean[] booleanValues) {
		int[] booleanAsIntegers = new int[booleanValues.length];
		for (int i = 0; i < booleanAsIntegers.length; i++) {
			booleanAsIntegers[i] = NativeBoolean.getValueFor(booleanValues[i]);
		}
		return invoke("SetBoolean").with(component, valueReferences, valueReferences.length, booleanAsIntegers).asInt();
	}

	public int setString(int[] valueReferences, String[] stringValues) {
		return invoke("SetString").with(component, valueReferences, valueReferences.length, stringValues).asInt();
	}

	public double getNextEventTime() {
		Memory memory = new Memory(Pointer.SIZE);
		invoke("GetNextEventTime").with(component, memory).asInt();
		double result = memory.getDouble(0);
		memory.clear();
		return result;
	}

	public Pointer getFmuState(Pointer state) {
		PointerByReference pointerByReference = new PointerByReference(state);
		invoke("GetFMUstate").with(component, pointerByReference).asInt();
		return pointerByReference.getValue();
	}

	public int setFmuState(Pointer pointer) {
		return invoke("SetFMUstate").with(component, pointer).asInt();
	}

	public int freeFmuState(Pointer state) {
		return invoke("FreeFMUstate").with(component, new PointerByReference(state)).asInt();
	}

	public int serializedFmuStateSize(Pointer state) {
		Memory memory = new Memory(Pointer.SIZE);
		invoke("SerializedFMUstateSize").with(component, state, memory).asInt();
		return memory.getInt(0);
	}

	public byte[] serializeFmuState(Pointer state) {
		int size = serializedFmuStateSize(state);
		byte[] byteBuffer = new byte[size];
		invoke("SerializeFMUstate").with(component, state, byteBuffer, size).asInt();
		return byteBuffer;
	}

	public Pointer deSerializeFMUState(byte[] serializedState) {
		PointerByReference pointerByReference = new PointerByReference(new Memory(Pointer.SIZE));
		invoke("DeSerializeFMUstate").with(component, serializedState, serializedState.length, pointerByReference).asInt();
		return pointerByReference.getValue();
	}

	public double[] getDirectionalDerivative(int[] unknownValueReferences, int[] knownValueReferences, double[] knownDifferential) {
		double[] sharedDoubles = new double[knownDifferential.length];
		invoke("GetDirectionalDerivative").with(component, unknownValueReferences, unknownValueReferences.length, knownValueReferences, knownValueReferences.length, knownDifferential, sharedDoubles).asInt();
		return sharedDoubles;
	}

	public int setRealInputDerivatives(int[] valueReferences, int[] orders, double[] values) {
		return invoke("SetRealInputDerivatives").with(component, valueReferences, valueReferences.length, orders, values).asInt();
	}

	public double[] getRealOutputDerivatives(int[] valueReferences, int[] orders) {
		double[] values = new double[valueReferences.length];
		invoke("GetRealOutputDerivatives").with(component, valueReferences, valueReferences.length, orders, values).asInt();
		return values;
	}

	public int doStep(double currentSimulationTime, double stepSize, boolean noSetFmuStatePriorToCurrentPoint) {
		return invoke("DoStep").with(component, currentSimulationTime, stepSize, noSetFmuStatePriorToCurrentPoint).asInt();
	}

	public Object[] hybridDoStep(double currentSimulationTime, double stepSize, boolean noSetFmuStatePriorToCurrentPoint) {
		Memory eventOccurred = new Memory(Pointer.SIZE);
		Memory endTime = new Memory(Pointer.SIZE);
		int status = invoke("HybridDoStep").with(component, currentSimulationTime, stepSize, noSetFmuStatePriorToCurrentPoint, eventOccurred, endTime).asInt();
		int eventOccurredValue = eventOccurred.getInt(0);
		double endTimeValue = endTime.getDouble(0);
		eventOccurred.clear();
		endTime.clear();
		return new Object[]{status, eventOccurredValue, endTimeValue};
	}


	public int newDiscreteStates(FmiProxyV21.EventInfo info) {
		return invoke("NewDiscreteStates").with(component, info).asInt();
	}

	public int cancelStep() {
		return invoke("CancelStep").with(component).asInt();
	}

	public int getStatus(int statusKind) {
		Memory status = new Memory(Pointer.SIZE);
		invoke("GetStatus").with(component, statusKind, status).asInt();
		return status.getInt(0);
	}

	public double getRealStatus(int statusKind) {
		double[] realStatus = new double[1];
		invoke("GetRealStatus").with(component, statusKind, realStatus).asInt();
		return realStatus[0];
	}

	public int getIntegerStatus(int statusKind) {
		Memory integerStatus = new Memory(Pointer.SIZE);
		invoke("GetIntegerStatus").with(component, statusKind, integerStatus).asInt();
		return integerStatus.getInt(0);
	}

	public boolean getBooleanStatus(int statusKind) {
		Memory booleanStatus = new Memory(Pointer.SIZE);
		invoke("GetBooleanStatus").with(component, statusKind, booleanStatus).asInt();
		return booleanStatus.getInt(0) == 1;
	}

	public String getStringStatus(int statusKind) {
		PointerByReference stringStatus = new PointerByReference(new Memory(Pointer.SIZE));
		invoke("GetStringStatus").with(component, statusKind, stringStatus).asInt();
		return stringStatus.getValue().getString(0);
	}

	private Invocation invoke(final String name) {
		return args -> new Invocation.Result() {
			@Override
			public Pointer asPointer() {
				return (Pointer) function(name).invoke(Pointer.class, args);
			}

			@Override
			public int asInt() {
				return function(name).invokeInt(args);
			}

			@Override
			public void asVoid() {
				function(name).invoke(args);
			}
		};
	}

	private Function function(String name) {
		return functions.get(name);
	}

	private String fmi21(String name) {
		return "fmi2" + name;
	}


	private interface Invocation {
		Result with(Object... args);

		interface Result {
			public Pointer asPointer();

			public int asInt();

			public void asVoid();
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy