Aufgrund einer Wartung wird GitLab am 18.01. zwischen 8:00 und 9:00 Uhr kurzzeitig nicht zur Verfügung stehen. / Due to maintenance, GitLab will be temporarily unavailable on 18.01. between 8:00 and 9:00 am.

Commit 00fc041e authored by Markus Mirz's avatar Markus Mirz
Browse files

make shmem interface specialization of interface


Signed-off-by: Markus Mirz's avatarMarkus Mirz <mmirz@eonerc.rwth-aachen.de>
parent d2b8a83f
......@@ -15,6 +15,7 @@
*********************************************************************************/
#include <DPsim.h>
#include <dpsim/InterfaceShmem.h>
using namespace DPsim;
using namespace CPS::Signal;
......@@ -26,7 +27,7 @@ int main(int argc, char *argv[]) {
Real finalTime = 10;
String simName = "ShmemControllableSource";
Interface intf("/dpsim01", "/dpsim10");
InterfaceShmem intf("/dpsim01", "/dpsim10");
// Controllers and filter
std::vector<Real> coefficients = { -0.0024229,-0.0020832,0.0067703,0.016732,
......
......@@ -15,6 +15,7 @@
*********************************************************************************/
#include <DPsim.h>
#include <dpsim/InterfaceShmem.h>
using namespace DPsim;
using namespace CPS::DP;
......@@ -25,7 +26,7 @@ int main(int argc, char *argv[]) {
Real finalTime = 10;
String simName = "ShmemControllableSource";
Interface intf("/dpsim01", "/dpsim10");
InterfaceShmem intf("/dpsim01", "/dpsim10");
// Nodes
auto n1 = SimNode::make("n1");
......
......@@ -15,6 +15,7 @@
*********************************************************************************/
#include <DPsim.h>
#include <dpsim/InterfaceShmem.h>
using namespace DPsim;
using namespace CPS::DP;
......@@ -91,7 +92,7 @@ int main(int argc, char *argv[]) {
sim.addLogger(logger);
// Map attributes to interface entries
Interface intf(in, out);
InterfaceShmem intf(in, out);
evs->setAttributeRef("V_ref", intf.importComplex(0));
auto evsAttrMinus = evs->attributeMatrixComp("i_intf")->coeff(0,0);
intf.exportComplex(evsAttrMinus, 0);
......@@ -138,7 +139,7 @@ int main(int argc, char *argv[]) {
sim.addLogger(logger);
// Map attributes to interface entries
Interface intf(in, out);
InterfaceShmem intf(in, out);
ecs->setAttributeRef("I_ref", intf.importComplex(0));
//intf.exportComplex(ecs->attributeMatrixComp("v_intf")->coeff(0, 0), 0);
intf.exportComplex(ecs->attributeMatrixComp("v_intf")->coeff(0, 0)->scale(Complex(-1.,0)), 0);
......
......@@ -15,6 +15,7 @@
*********************************************************************************/
#include <DPsim.h>
#include <dpsim/InterfaceShmem.h>
using namespace DPsim;
using namespace CPS::DP;
......@@ -40,7 +41,7 @@ int main(int argc, char *argv[]) {
out = "/villas1-out";
}
Interface intf(in, out, nullptr);
InterfaceShmem intf(in, out, nullptr);
if (String(argv[1]) == "0") {
// Nodes
......
......@@ -17,6 +17,7 @@
#include <fstream>
#include <DPsim.h>
#include <dpsim/InterfaceShmem.h>
using namespace DPsim;
using namespace CPS::DP;
......@@ -60,10 +61,10 @@ int main(int argc, char* argv[]) {
#ifdef REALTIME
RealTimeSimulation sim(simName, sys, timeStep, 1.0);
Interface intf("/villas1-in", "/villas1-out", nullptr, false);
InterfaceShmem intf("/villas1-in", "/villas1-out", nullptr, false);
#else
Simulation sim(simName, sys, timeStep, 1.0);
Interface intf("/villas1-in", "/villas1-out");
InterfaceShmem intf("/villas1-in", "/villas1-out");
#endif
// Interface
......
......@@ -16,6 +16,7 @@
#include <cps/CIM/Reader.h>
#include <DPsim.h>
#include <dpsim/InterfaceShmem.h>
using namespace std;
using namespace DPsim;
......@@ -51,7 +52,7 @@ int main(int argc, char** argv) {
RealTimeSimulation sim(simName, sys,
args.timeStep, args.duration,
args.solver.domain, args.solver.type, args.logLevel);
Interface intf("/dpsim1-villas", "/villas-dpsim1");
InterfaceShmem intf("/dpsim1-villas", "/villas-dpsim1");
// Register exportable node voltages
UInt o = 0;
......
......@@ -16,6 +16,7 @@
#include <cps/CIM/Reader.h>
#include <DPsim.h>
#include <dpsim/InterfaceShmem.h>
#include <cps/CSVReader.h>
#include <iostream>
#include <fstream>
......@@ -78,7 +79,7 @@ int main(int argc, char** argv){
csvreader.assignLoadProfile(sys, 0, args.timeStep, args.duration, CSVReader::Mode::MANUAL);
RealTimeSimulation sim(simName, sys, args.timeStep, args.duration, args.solver.domain, args.solver.type, args.logLevel);
Interface intf("/dpsim1-villas", "/villas-dpsim1");
InterfaceShmem intf("/dpsim1-villas", "/villas-dpsim1");
ofstream villas_conf;
villas_conf.open ("villas_sent_data.conf");
......
......@@ -18,6 +18,7 @@
#include <list>
#include <DPsim.h>
#include <dpsim/InterfaceShmem.h>
using namespace DPsim;
using namespace CPS::DP;
......@@ -40,7 +41,7 @@ int main(int argc, char *argv[]) {
RealTimeSimulation sim(simName, sys, 0.001, 120,
Domain::DP, Solver::Type::MNA, Logger::Level::debug, true);
Interface intf("/dpsim-villas", "/villas-dpsim");
InterfaceShmem intf("/dpsim-villas", "/villas-dpsim");
// Register exportable node voltages
UInt o = 0;
......
......@@ -18,6 +18,7 @@
#include <list>
#include <DPsim.h>
#include <dpsim/InterfaceShmem.h>
using namespace DPsim;
using namespace CPS::DP::Ph1;
......@@ -74,7 +75,7 @@ int main(int argc, char *argv[]) {
RealTimeSimulation sim(simName, sys, args.timeStep, args.duration, Domain::DP, Solver::Type::MNA, Logger::Level::off, true);
Interface intf("/dpsim1-villas", "/villas-dpsim1", nullptr, false);
InterfaceShmem intf("/dpsim1-villas", "/villas-dpsim1", nullptr, false);
auto logger = DataLogger::make(simName);
......
......@@ -18,7 +18,7 @@
#include <list>
#include <DPsim.h>
#include <dpsim/Interface.h>
#include <dpsim/InterfaceShmem.h>
#include <cps/CIM/Reader.h>
using namespace DPsim;
......@@ -61,8 +61,8 @@ int main(int argc, char *argv[]) {
RealTimeSimulation sim(args.name + "_1", sys, args.timeStep, args.duration,
Domain::DP, Solver::Type::MNA, Logger::Level::debug, true);
Interface intf1("/dpsim01", "/dpsim10", nullptr, false);
Interface intf2("/dpsim1-villas", "/villas-dpsim1", nullptr, false);
InterfaceShmem intf1("/dpsim01", "/dpsim10", nullptr, false);
InterfaceShmem intf2("/dpsim1-villas", "/villas-dpsim1", nullptr, false);
sim.addInterface(&intf1);
sim.addInterface(&intf2, false);
......@@ -123,10 +123,10 @@ int main(int argc, char *argv[]) {
auto sys = SystemTopology(args.sysFreq, SystemNodeList{n1}, SystemComponentList{evs, load, filtP});
RealTimeSimulation sim(args.name + "_2", sys, args.timeStep, args.duration);
Interface intf1("/dpsim10", "/dpsim01", nullptr, false);
InterfaceShmem intf1("/dpsim10", "/dpsim01", nullptr, false);
sim.addInterface(&intf1);
Interface intf2("/dpsim2-villas", "/villas-dpsim2", nullptr, false);
InterfaceShmem intf2("/dpsim2-villas", "/villas-dpsim2", nullptr, false);
sim.addInterface(&intf2, false);
// Register voltage source reference and current flowing through source
......
......@@ -25,10 +25,6 @@
#include <cps/Components.h>
#include <cps/Logger.h>
#ifdef WITH_SHMEM
#include <dpsim/Interface.h>
#endif
#ifdef WITH_CIM
#include <cps/CIM/Reader.h>
#endif
......
/* Copyright 2017-2020 Institute for Automation of Complex Power Systems,
* EONERC, RWTH Aachen University
* DPsim
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
* This program 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 General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*********************************************************************************/
#pragma once
#include <vector>
#include <cps/Logger.h>
#include <dpsim/Config.h>
#include <dpsim/Definitions.h>
#include <dpsim/Scheduler.h>
#include <cps/Attribute.h>
#include <cps/Task.h>
#include <cps/PtrFactory.h>
#include <villas/sample.h>
#include <villas/shmem.h>
namespace DPsim {
......@@ -39,126 +25,40 @@ namespace DPsim {
* the registered components or send voltages or currents to the external
* sink.
*/
class Interface : public SharedFactory<Interface> {
class Interface {
public:
typedef std::shared_ptr<Interface> Ptr;
typedef struct ::sample Sample;
typedef struct ::shmem_conf Config;
typedef struct ::shmem_int ShmemInterface;
protected:
// Using std::function / lambda makes the other template code nicer, but from
// the outside, only the attribute-based functions should be used to
// guarantee proper scheduling
void addImport(std::function<void(Sample*)> l) { mImports.push_back(l); }
void addExport(std::function<void(Sample*)> l) { mExports.push_back(l); }
std::vector<std::function<void(Sample*)>> mExports, mImports;
CPS::AttributeBase::List mExportAttrs, mImportAttrs;
ShmemInterface mShmem;
Sample *mLastSample;
bool mOpened;
int mSequence;
String mRName, mWName;
Config mConf;
CPS::Logger::Log mLog;
/// Is this interface used for synchorinzation?
bool mSync;
/// Downsampling
UInt mDownsampling;
public:
class PreStep : public CPS::Task {
public:
PreStep(Interface& intf) :
Task(intf.mRName + ".Read"), mIntf(intf) {
for (auto attr : intf.mImportAttrs) {
mModifiedAttributes.push_back(attr);
}
}
void execute(Real time, Int timeStepCount);
private:
Interface& mIntf;
};
class PostStep : public CPS::Task {
public:
PostStep(Interface& intf) :
Task(intf.mWName + ".Write"), mIntf(intf) {
for (auto attr : intf.mExportAttrs) {
mAttributeDependencies.push_back(attr);
}
mModifiedAttributes.push_back(Scheduler::external);
}
void execute(Real time, Int timeStepCount);
private:
Interface& mIntf;
};
/** Create a Interface with a specific configuration for the output queue.
*
* @param wname The name of the POSIX shmem object where samples will be written to.
* @param rname The name of the POSIX shmem object where samples will be read from.
* @param conf The configuration object for the output queue (see VILLASnode's documentation), or nullptr for sensible defaults.
*/
Interface(const String &wn, const String &rn, Config *conf = nullptr, Bool sync = true, UInt downsampling = 1) :
mOpened(false),
mRName(rn),
mWName(wn),
mSync(sync),
mDownsampling(downsampling)
{
if (conf != nullptr) {
mConf = *conf;
} else {
mConf.queuelen = 512;
mConf.samplelen = 64;
mConf.polling = 0;
}
}
~Interface() {
if (mOpened)
close();
}
Interface() = default;
virtual ~Interface() { };
void open(CPS::Logger::Log log);
void close();
virtual void open(CPS::Logger::Log log) = 0;
virtual void close() = 0;
CPS::Attribute<Int>::Ptr importInt(UInt idx);
CPS::Attribute<Real>::Ptr importReal(UInt idx);
CPS::Attribute<Bool>::Ptr importBool(UInt idx);
CPS::Attribute<Complex>::Ptr importComplex(UInt idx);
CPS::Attribute<Complex>::Ptr importComplexMagPhase(UInt idx);
virtual CPS::Attribute<Int>::Ptr importInt(UInt idx) = 0;
virtual CPS::Attribute<Real>::Ptr importReal(UInt idx) = 0;
virtual CPS::Attribute<Bool>::Ptr importBool(UInt idx) = 0;
virtual CPS::Attribute<Complex>::Ptr importComplex(UInt idx) = 0;
virtual CPS::Attribute<Complex>::Ptr importComplexMagPhase(UInt idx) = 0;
void exportInt(CPS::Attribute<Int>::Ptr attr, UInt idx);
void exportReal(CPS::Attribute<Real>::Ptr attr, UInt idx);
void exportBool(CPS::Attribute<Bool>::Ptr attr, UInt idx);
void exportComplex(CPS::Attribute<Complex>::Ptr attr, UInt idx);
virtual void exportInt(CPS::Attribute<Int>::Ptr attr, UInt idx) = 0;
virtual void exportReal(CPS::Attribute<Real>::Ptr attr, UInt idx) = 0;
virtual void exportBool(CPS::Attribute<Bool>::Ptr attr, UInt idx) = 0;
virtual void exportComplex(CPS::Attribute<Complex>::Ptr attr, UInt idx) = 0;
/** Read data for a timestep from the interface and passes the values
* to all registered current / voltage sources.
*/
void readValues(bool blocking = true);
virtual void readValues(bool blocking = true) = 0;
/** Write all exported values to the interface. Called after every timestep.
* @param model Reference to the system model which should be used to
* calculate needed voltages.
*/
void writeValues();
virtual void writeValues() = 0;
CPS::Task::List getTasks();
virtual CPS::Task::List getTasks() = 0;
};
}
/* Copyright 2017-2020 Institute for Automation of Complex Power Systems,
* EONERC, RWTH Aachen University
* DPsim
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
* This program 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 General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
#pragma once
#include <vector>
#include <cps/PtrFactory.h>
#include <dpsim/Interface.h>
#include <villas/sample.h>
#include <villas/shmem.h>
namespace DPsim {
/// Shmem interface used in combination with VILLAS
class InterfaceShmem :
public Interface,
public SharedFactory<InterfaceShmem> {
public:
typedef std::shared_ptr<InterfaceShmem> Ptr;
typedef struct ::sample Sample;
typedef struct ::shmem_conf Config;
typedef struct ::shmem_int ShmemInt;
protected:
// Using std::function / lambda makes the other template code nicer, but from
// the outside, only the attribute-based functions should be used to
// guarantee proper scheduling
void addImport(std::function<void(Sample*)> l) { mImports.push_back(l); }
void addExport(std::function<void(Sample*)> l) { mExports.push_back(l); }
std::vector<std::function<void(Sample*)>> mExports, mImports;
CPS::AttributeBase::List mExportAttrs, mImportAttrs;
ShmemInt mShmem;
Sample *mLastSample;
bool mOpened;
int mSequence;
String mRName, mWName;
Config mConf;
CPS::Logger::Log mLog;
/// Is this InterfaceShmem used for synchorinzation?
bool mSync;
/// Downsampling
UInt mDownsampling;
public:
class PreStep : public CPS::Task {
public:
PreStep(InterfaceShmem& intf) :
Task(intf.mRName + ".Read"), mIntf(intf) {
for (auto attr : intf.mImportAttrs) {
mModifiedAttributes.push_back(attr);
}
}
void execute(Real time, Int timeStepCount);
private:
InterfaceShmem& mIntf;
};
class PostStep : public CPS::Task {
public:
PostStep(InterfaceShmem& intf) :
Task(intf.mWName + ".Write"), mIntf(intf) {
for (auto attr : intf.mExportAttrs) {
mAttributeDependencies.push_back(attr);
}
mModifiedAttributes.push_back(Scheduler::external);
}
void execute(Real time, Int timeStepCount);
private:
InterfaceShmem& mIntf;
};
/** Create a InterfaceShmem with a specific configuration for the output queue.
*
* @param wname The name of the POSIX shmem object where samples will be written to.
* @param rname The name of the POSIX shmem object where samples will be read from.
* @param conf The configuration object for the output queue (see VILLASnode's documentation), or nullptr for sensible defaults.
*/
InterfaceShmem(const String &wn, const String &rn, Config *conf = nullptr, Bool sync = true, UInt downsampling = 1) :
mOpened(false),
mRName(rn),
mWName(wn),
mSync(sync),
mDownsampling(downsampling)
{
if (conf != nullptr) {
mConf = *conf;
} else {
mConf.queuelen = 512;
mConf.samplelen = 64;
mConf.polling = 0;
}
}
~InterfaceShmem() {
if (mOpened)
close();
}
void open(CPS::Logger::Log log);
void close();
CPS::Attribute<Int>::Ptr importInt(UInt idx);
CPS::Attribute<Real>::Ptr importReal(UInt idx);
CPS::Attribute<Bool>::Ptr importBool(UInt idx);
CPS::Attribute<Complex>::Ptr importComplex(UInt idx);
CPS::Attribute<Complex>::Ptr importComplexMagPhase(UInt idx);
void exportInt(CPS::Attribute<Int>::Ptr attr, UInt idx);
void exportReal(CPS::Attribute<Real>::Ptr attr, UInt idx);
void exportBool(CPS::Attribute<Bool>::Ptr attr, UInt idx);
void exportComplex(CPS::Attribute<Complex>::Ptr attr, UInt idx);
/** Read data for a timestep from the InterfaceShmem and passes the values
* to all registered current / voltage sources.
*/
void readValues(bool blocking = true);
/** Write all exported values to the InterfaceShmem. Called after every timestep.
* @param model Reference to the system model which should be used to
* calculate needed voltages.
*/
void writeValues();
CPS::Task::List getTasks();
};
}
......@@ -26,12 +26,14 @@
#include <cps/Config.h>
#include <cps/Definitions.h>
#include <dpsim/Interface.h>
namespace DPsim {
#ifdef WITH_SHMEM
class Interface;
#include <dpsim/InterfaceShmem.h>
#endif
namespace DPsim {
namespace Python {
// Thin Python wrapper around Interface
......@@ -39,7 +41,7 @@ namespace Python {
PyObject_HEAD
#ifdef WITH_SHMEM
DPsim::Interface::Config conf;
DPsim::InterfaceShmem::Config conf;
DPsim::Interface::Ptr intf;
const char *wname, *rname;
PyObject *pyExports;
......
......@@ -27,15 +27,12 @@
#include <cps/Logger.h>
#include <cps/SystemTopology.h>
#include <cps/SimNode.h>
#include <dpsim/Interface.h>
#ifdef WITH_GRAPHVIZ
#include <cps/Graph.h>
#endif
#ifdef WITH_SHMEM
#include <dpsim/Interface.h>
#endif
namespace DPsim {
/// \brief The Simulation holds a SystemTopology and a Solver.
///
......
......@@ -45,7 +45,7 @@ endif()
if(WITH_SHMEM)
list(APPEND DPSIM_SOURCES
Interface.cpp
InterfaceShmem.cpp
PthreadPoolScheduler.cpp
)
......
......@@ -20,23 +20,23 @@
#include <spdlog/sinks/stdout_color_sinks.h>
#include <dpsim/Interface.h>
#include <dpsim/Interface