<commit_before>#include "EnvironmentNetworking.h"

#include <time.h>
#include <fstream>
#include <sstream>
#include <algorithm>
#include <stdio.h>

#ifdef _WIN32
	#include <windows.h>
	#include <tchar.h>
	#include <stdio.h>
	#include <strsafe.h>
#else
	#include <sys/socket.h>
	#include <arpa/inet.h>
	#include <time.h>
	#include <sys/socket.h>
	#include <netinet/in.h>
	#include <unistd.h>
#endif

std::string EnvironmentNetworking::serializeMap(const hlt::Map & map)
{
	std::string returnString = "";
	std::ostringstream oss;
	oss << map.map_width << " " << map.map_height << " ";

	// Run-length encode of owners
	unsigned short currentOwner = map.contents[0][0].owner;
	unsigned short counter = 0;
	for (int a = 0; a < map.contents.size(); ++a)
	{
		for (int b = 0; b < map.contents[a].size(); ++b)
		{
			if (map.contents[a][b].owner == currentOwner)
			{
				counter++;
			}
			else
			{
				oss << (unsigned short)counter << " " << (unsigned short)currentOwner << " ";
				counter = 1;
				currentOwner = map.contents[a][b].owner;
			}
		}
	}
	// Place the last run into the string
	oss << (unsigned short)counter << " " << (unsigned short)currentOwner << " ";

	// Encoding of ages
	for (int a = 0; a < map.contents.size(); ++a)
	{
		for (int b = 0; b < map.contents[a].size(); ++b)
		{
			oss << (unsigned short)map.contents[a][b].strength << " ";
		}
	}

	returnString = oss.str();

	return returnString;
}

std::set<hlt::Move> EnvironmentNetworking::deserializeMoveSet(std::string & inputString)
{
	std::set<hlt::Move> moves = std::set<hlt::Move>();

	std::stringstream iss(inputString);
	hlt::Location l;
	int d;
	while (iss >> l.x >> l.y >> d) moves.insert({ l, (unsigned char)d });

	return moves;
}

std::string EnvironmentNetworking::serializeMessages(const std::vector<hlt::Message> &messages) {
	std::ostringstream oss;

	oss << messages.size() << " ";

	for (int a = 0; a < messages.size(); a++)
	{
		hlt::Message message = messages[a];
		oss << (unsigned short)message.type << " ";
		oss << message.senderID << " " << message.recipientID << " " << message.targetID << " ";
	}

	return oss.str();
}

std::vector<hlt::Message> EnvironmentNetworking::deserializeMessages(const std::string &inputString)
{
	std::vector<hlt::Message> messages = std::vector<hlt::Message>();
	std::stringstream iss(inputString);

	int numberOfMessages;
	iss >> numberOfMessages;

	for (int a = 0; a < numberOfMessages; a++)
	{
		hlt::Message message;

		int messageTypeInt;
		iss >> messageTypeInt;
		message.type = static_cast<hlt::MessageType>(messageTypeInt);

		iss >> message.senderID >> message.recipientID >> message.targetID;

		messages.push_back(message);
	}

	return messages;
}

void EnvironmentNetworking::sendString(unsigned char playerTag, const std::string &sendString)
{
#ifdef _WIN32

#else
	int connectionFd = connections[playerTag - 1];
	uint32_t length = sendString.length();
	// Copy the string into a buffer. May want to get rid of this operation for performance purposes
	std::vector<char> buffer(sendString.begin(), sendString.end());

	send(connectionFd, (char *)&length, sizeof(length), 0);
	send(connectionFd, &buffer[0], buffer.size(), 0);
#endif
}

std::string EnvironmentNetworking::getString(unsigned char playerTag)
{
#ifdef _WIN32

#else
	int connectionFd = connections[playerTag - 1];
	uint32_t numChars;
	recv(connectionFd, (char *)&numChars, sizeof(numChars), 0);

	std::vector<char> buffer(numChars);
	recv(connectionFd, &buffer[0], buffer.size(), 0);

	// Copy the buffer into a string. May want to get rid of this for performance purposes
	return std::string(buffer.begin(), buffer.end());
	//return "Done";
#endif
}

void EnvironmentNetworking::createAndConnectSocket(int port)
{
#ifdef _WIN32
	// stdin write - write to this
	// stdout read - read from this
	Connection connection;

	SECURITY_ATTRIBUTES saAttr;
	saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
	saAttr.bInheritHandle = TRUE;
	saAttr.lpSecurityDescriptor = NULL;

	bool success = CreateProcess(NULL,
		"../Debug/ExampleBot.exe",     // command line
		NULL,          // process security attributes
		NULL,          // primary thread security attributes
		TRUE,          // handles are inherited
		0,             // creation flags
		NULL,          // use parent's environment
		NULL,          // use parent's current directory
		&siStartInfo,  // STARTUPINFO pointer
		&piProcInfo);  // receives PROCESS_INFORMATION
#else
	std::cout << "Waiting for player to connect on port " << port << ".\n";

	int socketFd = socket(AF_INET, SOCK_STREAM, 0);
	if (socketFd < 0)
	{
		std::cout << "ERROR opening socket\n";
		throw 1;
	}

	struct sockaddr_in serverAddr;
	memset(&serverAddr, 0, sizeof(serverAddr));
	serverAddr.sin_family = AF_INET;
	serverAddr.sin_addr.s_addr = INADDR_ANY;
	serverAddr.sin_port = htons(port);

	if (bind(socketFd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0)
	{
		std::cout << "ERROR on binding to port number " << port << "\n";
		throw 1;
	}

	listen(socketFd, 5);

	struct sockaddr_in clientAddr;
	socklen_t clientLength = sizeof(clientAddr);
	int connectionFd = accept(socketFd, (struct sockaddr *)&clientAddr, &clientLength);
	if (connectionFd < 0)
	{
		std::cout << "ERROR on accepting\n";
		throw 1;
	}

	std::cout << "Connected.\n";

	connections.push_back(connectionFd);
#endif
}

double EnvironmentNetworking::handleInitNetworking(unsigned char playerTag, std::string name, hlt::Map & m)
{
	sendString(playerTag, std::to_string(playerTag));
	sendString(playerTag, serializeMap(m));

	std::string str = "Init Message sent to player " + name + "\n";
	std::cout << str;

	std::string receiveString = "";

	clock_t initialTime = clock();

	receiveString = getString(playerTag);
	str = "Init Message received from player " + name + "\n";
	std::cout << str;

	clock_t finalTime = clock() - initialTime;
	double timeElapsed = float(finalTime) / CLOCKS_PER_SEC;

	if (receiveString != "Done") return FLT_MAX;
	return timeElapsed;
}

double EnvironmentNetworking::handleFrameNetworking(unsigned char playerTag, const hlt::Map & m, const std::vector<hlt::Message> &messagesForThisBot, std::set<hlt::Move> * moves, std::vector<hlt::Message> * messagesFromThisBot)
{
	// Send this bot the game map and the messages addressed to this bot
	sendString(playerTag, serializeMap(m));
	sendString(playerTag, serializeMessages(messagesForThisBot));

	moves->clear();

	clock_t initialTime = clock();

	*moves = deserializeMoveSet(getString(playerTag));
	*messagesFromThisBot = deserializeMessages(getString(playerTag));

	clock_t finalTime = clock() - initialTime;
	double timeElapsed = float(finalTime) / CLOCKS_PER_SEC;

	return timeElapsed;
}
<commit_msg>Server windows networking<commit_after>#include "EnvironmentNetworking.h"

#include <time.h>
#include <fstream>
#include <sstream>
#include <algorithm>
#include <stdio.h>

#ifdef _WIN32
	#include <windows.h>
	#include <tchar.h>
	#include <stdio.h>
	#include <strsafe.h>
#else
	#include <sys/socket.h>
	#include <arpa/inet.h>
	#include <time.h>
	#include <sys/socket.h>
	#include <netinet/in.h>
	#include <unistd.h>
#endif

std::string EnvironmentNetworking::serializeMap(const hlt::Map & map)
{
	std::string returnString = "";
	std::ostringstream oss;
	oss << map.map_width << " " << map.map_height << " ";

	// Run-length encode of owners
	unsigned short currentOwner = map.contents[0][0].owner;
	unsigned short counter = 0;
	for (int a = 0; a < map.contents.size(); ++a)
	{
		for (int b = 0; b < map.contents[a].size(); ++b)
		{
			if (map.contents[a][b].owner == currentOwner)
			{
				counter++;
			}
			else
			{
				oss << (unsigned short)counter << " " << (unsigned short)currentOwner << " ";
				counter = 1;
				currentOwner = map.contents[a][b].owner;
			}
		}
	}
	// Place the last run into the string
	oss << (unsigned short)counter << " " << (unsigned short)currentOwner << " ";

	// Encoding of ages
	for (int a = 0; a < map.contents.size(); ++a)
	{
		for (int b = 0; b < map.contents[a].size(); ++b)
		{
			oss << (unsigned short)map.contents[a][b].strength << " ";
		}
	}

	returnString = oss.str();

	return returnString;
}

std::set<hlt::Move> EnvironmentNetworking::deserializeMoveSet(std::string & inputString)
{
	std::set<hlt::Move> moves = std::set<hlt::Move>();

	std::stringstream iss(inputString);
	hlt::Location l;
	int d;
	while (iss >> l.x >> l.y >> d) moves.insert({ l, (unsigned char)d });

	return moves;
}

std::string EnvironmentNetworking::serializeMessages(const std::vector<hlt::Message> &messages) {
	std::ostringstream oss;

	oss << messages.size() << " ";

	for (int a = 0; a < messages.size(); a++)
	{
		hlt::Message message = messages[a];
		oss << (unsigned short)message.type << " ";
		oss << message.senderID << " " << message.recipientID << " " << message.targetID << " ";
	}

	return oss.str();
}

std::vector<hlt::Message> EnvironmentNetworking::deserializeMessages(const std::string &inputString)
{
	std::vector<hlt::Message> messages = std::vector<hlt::Message>();
	std::stringstream iss(inputString);

	int numberOfMessages;
	iss >> numberOfMessages;

	for (int a = 0; a < numberOfMessages; a++)
	{
		hlt::Message message;

		int messageTypeInt;
		iss >> messageTypeInt;
		message.type = static_cast<hlt::MessageType>(messageTypeInt);

		iss >> message.senderID >> message.recipientID >> message.targetID;

		messages.push_back(message);
	}

	return messages;
}

void EnvironmentNetworking::sendString(unsigned char playerTag, const std::string &sendString)
{
#ifdef _WIN32
	Connection connection = connections[playerTag - 1];

	uint32_t length = sendString.length();
	// Copy the string into a buffer. May want to get rid of this operation for performance purposes
	std::vector<char> buffer(sendString.begin(), sendString.end());

	DWORD charsWritten;
	bool success;

	success = WriteFile(connection.write, (char *)&length, sizeof(length), &charsWritten, NULL);
	if (!success || charsWritten == 0) {
		std::cout << "problem writing\n";
		throw 1;
	}
	success = WriteFile(connection.write, &buffer[0], buffer.size(), &charsWritten, NULL);
	if (!success || charsWritten == 0) {
		std::cout << "problem writing\n";
		throw 1;
	}
#else
	int connectionFd = connections[playerTag - 1];
	uint32_t length = sendString.length();
	// Copy the string into a buffer. May want to get rid of this operation for performance purposes
	std::vector<char> buffer(sendString.begin(), sendString.end());

	send(connectionFd, (char *)&length, sizeof(length), 0);
	send(connectionFd, &buffer[0], buffer.size(), 0);
#endif
}

std::string EnvironmentNetworking::getString(unsigned char playerTag)
{
#ifdef _WIN32
	Connection connection = connections[playerTag - 1];

	DWORD charsRead;
	bool success;

	uint32_t numChars;
	ReadFile(connection.read, (char *)&numChars, sizeof(numChars), &charsRead, NULL);
	if (!success || charsRead == 0)
	{
		std::cout << "problem reading\n";
		throw 1;
	}
	if (charsRead < sizeof(numChars))
	{
		std::cout << "Read too little. Read " << charsRead << " of " << sizeof(numChars) << "\n";
		throw 1;
	}

	std::vector<char> buffer(numChars);
	ReadFile(connection.read, &buffer[0], buffer.size(), &charsRead, NULL);
	if (!success || charsRead == 0)
	{
		std::cout << "problem reading\n";
		throw 1;
	}
	if (charsRead < buffer.size())
	{
		std::cout << "Read too little. Read " << charsRead << " of " << buffer.size() << "\n";
		throw 1;
	}

	// Copy the buffer into a string. May want to get rid of this for performance purposes
	return std::string(buffer.begin(), buffer.end());
#else
	int connectionFd = connections[playerTag - 1];
	uint32_t numChars;
	recv(connectionFd, (char *)&numChars, sizeof(numChars), 0);

	std::vector<char> buffer(numChars);
	recv(connectionFd, &buffer[0], buffer.size(), 0);

	// Copy the buffer into a string. May want to get rid of this for performance purposes
	return std::string(buffer.begin(), buffer.end());
	//return "Done";
#endif
}

void EnvironmentNetworking::createAndConnectSocket(int port)
{
#ifdef _WIN32
	// stdin write - write to this
	// stdout read - read from this
	Connection parentConnection, childConnection;

	SECURITY_ATTRIBUTES saAttr;
	saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
	saAttr.bInheritHandle = TRUE;
	saAttr.lpSecurityDescriptor = NULL;

	// Child stdout pipe
	if (!CreatePipe(&parentConnection.read, &childConnection.write, &saAttr, 0))
	{
		std::cout << "Could not create pipe\n";
		throw 1;
	}
	if (!SetHandleInformation(parentConnection.read, HANDLE_FLAG_INHERIT, 0)) throw 1;

	// Child stdin pipe
	if (!CreatePipe(&childConnection.read, &parentConnection.write, &saAttr, 0))
	{
		std::cout << "Could not create pipe\n";
		throw 1;
	}
	if (!SetHandleInformation(parentConnection.write, HANDLE_FLAG_INHERIT, 0)) throw 1;

	// MAKE SURE THIS MEMORY IS ERASED
	PROCESS_INFORMATION piProcInfo;
	ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION));

	STARTUPINFO siStartInfo;
	ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
	siStartInfo.cb = sizeof(STARTUPINFO);
	siStartInfo.hStdError = childConnection.write;
	siStartInfo.hStdOutput = childConnection.write;
	siStartInfo.hStdInput = childConnection.read;
	siStartInfo.dwFlags |= STARTF_USESTDHANDLES;

	bool success = CreateProcess(
		NULL,
		"../Debug/ExampleBot.exe",     // command line
		NULL,          // process security attributes
		NULL,          // primary thread security attributes
		TRUE,          // handles are inherited
		0,             // creation flags
		NULL,          // use parent's environment
		NULL,          // use parent's current directory
		&siStartInfo,  // STARTUPINFO pointer
		&piProcInfo
	);  // receives PROCESS_INFORMATION
	if(!success)
	{
		std::cout << "Could not start process\n";
		throw 1;
	}
	else
	{
		CloseHandle(piProcInfo.hProcess);
		CloseHandle(piProcInfo.hThread);
		connections.push_back(parentConnection);
	}
#else
	std::cout << "Waiting for player to connect on port " << port << ".\n";

	int socketFd = socket(AF_INET, SOCK_STREAM, 0);
	if (socketFd < 0)
	{
		std::cout << "ERROR opening socket\n";
		throw 1;
	}

	struct sockaddr_in serverAddr;
	memset(&serverAddr, 0, sizeof(serverAddr));
	serverAddr.sin_family = AF_INET;
	serverAddr.sin_addr.s_addr = INADDR_ANY;
	serverAddr.sin_port = htons(port);

	if (bind(socketFd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0)
	{
		std::cout << "ERROR on binding to port number " << port << "\n";
		throw 1;
	}

	listen(socketFd, 5);

	struct sockaddr_in clientAddr;
	socklen_t clientLength = sizeof(clientAddr);
	int connectionFd = accept(socketFd, (struct sockaddr *)&clientAddr, &clientLength);
	if (connectionFd < 0)
	{
		std::cout << "ERROR on accepting\n";
		throw 1;
	}

	std::cout << "Connected.\n";

	connections.push_back(connectionFd);
#endif
}

double EnvironmentNetworking::handleInitNetworking(unsigned char playerTag, std::string name, hlt::Map & m)
{
	sendString(playerTag, std::to_string(playerTag));
	sendString(playerTag, serializeMap(m));

	std::string str = "Init Message sent to player " + name + "\n";
	std::cout << str;

	std::string receiveString = "";

	clock_t initialTime = clock();

	receiveString = getString(playerTag);
	str = "Init Message received from player " + name + "\n";
	std::cout << str;

	clock_t finalTime = clock() - initialTime;
	double timeElapsed = float(finalTime) / CLOCKS_PER_SEC;

	if (receiveString != "Done") return FLT_MAX;
	return timeElapsed;
}

double EnvironmentNetworking::handleFrameNetworking(unsigned char playerTag, const hlt::Map & m, const std::vector<hlt::Message> &messagesForThisBot, std::set<hlt::Move> * moves, std::vector<hlt::Message> * messagesFromThisBot)
{
	// Send this bot the game map and the messages addressed to this bot
	sendString(playerTag, serializeMap(m));
	sendString(playerTag, serializeMessages(messagesForThisBot));

	moves->clear();

	clock_t initialTime = clock();

	*moves = deserializeMoveSet(getString(playerTag));
	*messagesFromThisBot = deserializeMessages(getString(playerTag));

	clock_t finalTime = clock() - initialTime;
	double timeElapsed = float(finalTime) / CLOCKS_PER_SEC;

	return timeElapsed;
}
<|endoftext|>


<commit_before>// ------------------------------------------------------------------
// pion-platform: a C++ framework for building lightweight HTTP interfaces
// ------------------------------------------------------------------
// Copyright (C) 2007 Atomic Labs, Inc.  (http://www.atomiclabs.com)
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file COPYING or copy at http://www.boost.org/LICENSE_1_0.txt
//

#ifndef _MSC_VER
	#include <fcntl.h>
	#include <unistd.h>
	#include <sys/stat.h>
#endif
#include <iostream>
#include "PlatformConfig.hpp"
#include "../../net/utils/ShutdownManager.hpp"

using namespace std;
using namespace pion;
using namespace pion::net;
using namespace pion::platform;
using namespace pion::server;

// some forward declarations of functions used by main()
void daemonize_server(void);
void argument_error(void);

/// main control function
int main (int argc, char *argv[])
{
	// get platform config file
	bool verbose_logging = false;
	bool run_as_daemon = false;
	std::string platform_config_file("/etc/pion/platform.xml");
	for (int argnum=1; argnum < argc; ++argnum) {
		if (argv[argnum][0] == '-') {
			if (argv[argnum][1] == 'v') {
				verbose_logging = true;
			} if (argv[argnum][1] == 'D') {
				run_as_daemon = true;
			} else if (argv[argnum][1] == 'c' && argv[argnum][2] == '\0' && argnum+1 < argc) {
				platform_config_file = argv[++argnum];
			} else {
				argument_error();
				return 1;
			}
		} else {
			argument_error();
			return 1;
		}
	}

	/// become a daemon if the -D option is given
	if (run_as_daemon)
		daemonize_server();

	// setup signal handler
#ifdef PION_WIN32
	SetConsoleCtrlHandler(console_ctrl_handler, TRUE);
#else
	signal(SIGCHLD, SIG_IGN);
	signal(SIGTSTP, SIG_IGN);
	signal(SIGTTOU, SIG_IGN);
	signal(SIGTTIN, SIG_IGN);
	signal(SIGHUP, SIG_IGN);
	signal(SIGINT, handle_signal);
	signal(SIGTERM, handle_signal);
#endif

	// initialize log system (use simple configuration)
	PionLogger pion_log(PION_GET_LOGGER("pion"));
	if (verbose_logging) {
		PION_LOG_SETLEVEL_DEBUG(pion_log);
	} else {
		PION_LOG_SETLEVEL_INFO(pion_log);
	}
	PION_LOG_CONFIG_BASIC;

	PlatformConfig platform_cfg;
	try {
		// load the platform configuration
		platform_cfg.setConfigFile(platform_config_file);
		platform_cfg.openConfigFile();

		// start the ReactionEngine
		platform_cfg.getReactionEngine().start();

		PION_LOG_INFO(pion_log, "Pion has started successfully");

		// wait for shutdown
		main_shutdown_manager.wait();

	} catch (std::exception& e) {
		PION_LOG_FATAL(pion_log, e.what());
	}

	PION_LOG_INFO(pion_log, "Pion is shutting down");

	return 0;
}

/// run server as a daemon
void daemonize_server(void)
{
#ifndef _MSC_VER
	// adopted from "Unix Daemon Server Programming"
	// http://www.enderunix.org/docs/eng/daemon.php

	// return early if already running as a daemon
	if(getppid()==1) return;

	// for out the process
	int i = fork();
	if (i<0) exit(1);	// error forking
	if (i>0) exit(0);	// exit if parent

	// child (daemon process) continues here after the fork...

	// obtain a new process group
	setsid();

	// close all descriptors
	for (i=getdtablesize();i>=0;--i) close(i);

	// bind stdio to /dev/null
	i=open("/dev/null",O_RDWR); dup(i); dup(i);

	// restrict file creation mode to 0750
	umask(027);
#endif
}

/// displays an error message if the arguments are invalid
void argument_error(void)
{
	std::cerr << "usage:   pion [-c SERVICE_CONFIG_FILE] [-D] [-v]" << std::endl;
}
<commit_msg>Removed 'verbose' command line option.  (There was a bug in it, but after talking with Mike, it seemed best to just remove it, now that a logging configuration file is being used.)<commit_after>// ------------------------------------------------------------------
// pion-platform: a C++ framework for building lightweight HTTP interfaces
// ------------------------------------------------------------------
// Copyright (C) 2007 Atomic Labs, Inc.  (http://www.atomiclabs.com)
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file COPYING or copy at http://www.boost.org/LICENSE_1_0.txt
//

#ifndef _MSC_VER
	#include <fcntl.h>
	#include <unistd.h>
	#include <sys/stat.h>
#endif
#include <iostream>
#include "PlatformConfig.hpp"
#include "../../net/utils/ShutdownManager.hpp"

using namespace std;
using namespace pion;
using namespace pion::net;
using namespace pion::platform;
using namespace pion::server;

// some forward declarations of functions used by main()
void daemonize_server(void);
void argument_error(void);

/// main control function
int main (int argc, char *argv[])
{
	// get platform config file
	bool run_as_daemon = false;
	std::string platform_config_file("/etc/pion/platform.xml");
	for (int argnum=1; argnum < argc; ++argnum) {
		if (argv[argnum][0] == '-') {
			if (argv[argnum][1] == 'D') {
				run_as_daemon = true;
			} else if (argv[argnum][1] == 'c' && argv[argnum][2] == '\0' && argnum+1 < argc) {
				platform_config_file = argv[++argnum];
			} else {
				argument_error();
				return 1;
			}
		} else {
			argument_error();
			return 1;
		}
	}

	/// become a daemon if the -D option is given
	if (run_as_daemon)
		daemonize_server();

	// setup signal handler
#ifdef PION_WIN32
	SetConsoleCtrlHandler(console_ctrl_handler, TRUE);
#else
	signal(SIGCHLD, SIG_IGN);
	signal(SIGTSTP, SIG_IGN);
	signal(SIGTTOU, SIG_IGN);
	signal(SIGTTIN, SIG_IGN);
	signal(SIGHUP, SIG_IGN);
	signal(SIGINT, handle_signal);
	signal(SIGTERM, handle_signal);
#endif

	// initialize log system (use simple configuration)
	PionLogger pion_log(PION_GET_LOGGER("pion"));

	// This level might be overridden if there is a LogConfig file specified in the platform
	// configuration (and if using a logging library that supports logging configuration.)
	PION_LOG_SETLEVEL_INFO(pion_log);

	PION_LOG_CONFIG_BASIC;

	PlatformConfig platform_cfg;
	try {
		// load the platform configuration
		platform_cfg.setConfigFile(platform_config_file);
		platform_cfg.openConfigFile();

		// start the ReactionEngine
		platform_cfg.getReactionEngine().start();

		PION_LOG_INFO(pion_log, "Pion has started successfully");

		// wait for shutdown
		main_shutdown_manager.wait();

	} catch (std::exception& e) {
		PION_LOG_FATAL(pion_log, e.what());
	}

	PION_LOG_INFO(pion_log, "Pion is shutting down");

	return 0;
}

/// run server as a daemon
void daemonize_server(void)
{
#ifndef _MSC_VER
	// adopted from "Unix Daemon Server Programming"
	// http://www.enderunix.org/docs/eng/daemon.php

	// return early if already running as a daemon
	if(getppid()==1) return;

	// for out the process
	int i = fork();
	if (i<0) exit(1);	// error forking
	if (i>0) exit(0);	// exit if parent

	// child (daemon process) continues here after the fork...

	// obtain a new process group
	setsid();

	// close all descriptors
	for (i=getdtablesize();i>=0;--i) close(i);

	// bind stdio to /dev/null
	i=open("/dev/null",O_RDWR); dup(i); dup(i);

	// restrict file creation mode to 0750
	umask(027);
#endif
}

/// displays an error message if the arguments are invalid
void argument_error(void)
{
	std::cerr << "usage:   pion [-c SERVICE_CONFIG_FILE] [-D] [-v]" << std::endl;
}
<|endoftext|>


<commit_before>///////////////////////////////////////////////////////////////////////////////
//
// File: NekManager.hpp
//
// For more information, please see: http://www.nektar.info
//
// The MIT License
//
// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
// Department of Aeronautics, Imperial College London (UK), and Scientific
// Computing and Imaging Institute, University of Utah (USA).
//
// License for the specific language governing rights and limitations under
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Description:
//
///////////////////////////////////////////////////////////////////////////////

#ifndef NEKTAR_LIB_UTILITIES_BASIC_UTILS_NEK_MANAGER_HPP
#define NEKTAR_LIB_UTILITIES_BASIC_UTILS_NEK_MANAGER_HPP

#include <utility>
#include <vector>
#include <algorithm>
#include <map>

#include <functional> // for bind1st
#include <iostream>

#include <boost/mem_fn.hpp>
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/call_traits.hpp>

#include <LibUtilities/BasicUtils/ErrorUtil.hpp>

using namespace std;

template <typename keyT, typename valueT,
    typename valueContainer = std::map<keyT, valueT>,
    typename creatorContainer = std::map<keyT, boost::function<valueT (const keyT& key)> > >
class NekManager
{
    public:
        typedef boost::function<valueT (const keyT& key)> CreateFunc;

        NekManager() :
            m_Values(),
            m_CreateFuncs()
        {
        };

        ~NekManager() {}

        void RegisterCreator(typename boost::call_traits<keyT>::const_reference key,
                             const CreateFunc& createFunc)
        {
            m_CreateFuncs[key] = createFunc;
        }

        void AddValue(typename boost::call_traits<keyT>::const_reference key,
                      typename boost::call_traits<valueT>::const_reference value)
        {
            typename valueContainer::iterator found = m_Values.find(key);
            if( found == m_Values.end() )
            {
                m_Values[key] = value;
            }
            else
            {
                std::string errorMessage = "Adding an object for key " +
                        boost::lexical_cast<std::string>(key) +
                        " to a NekManager, but a value for this key already exists.";

                throw std::runtime_error(errorMessage);
            }
        }

        typename boost::call_traits<valueT>::reference
        GetValue(typename boost::call_traits<keyT>::const_reference key)
        {
            typename valueContainer::iterator found = m_Values.find(key);
            if( found == m_Values.end() )
            {
                // No object, create a new one.
                typename creatorContainer::iterator keyFound = m_CreateFuncs.find(key);
                if( keyFound != m_CreateFuncs.end() )
                {
                    valueT newObj = (*keyFound).second(key);
                    m_Values[key] = newObj;
                    return m_Values[key];
                }
                else
                {
                    std::string errorMessage = "Attempting to obtain an object for key " +
                            boost::lexical_cast<std::string>(key) +
                            " in a NekManager but no create function has been registered";
                    throw std::runtime_error(errorMessage);
                }
            }
            else
            {
                return (*found).second;
            }
        }

    private:
        NekManager(const NekManager<keyT, valueT, valueContainer, creatorContainer>& rhs);
        NekManager<keyT, valueT, valueContainer, creatorContainer>& operator=(const NekManager<keyT, valueT, valueContainer, creatorContainer>& rhs);

        valueContainer m_Values;
        creatorContainer m_CreateFuncs;
};

#endif //NEKTAR_LIB_UTILITIES_BASIC_UTILS_NEK_MANAGER_HPP
<commit_msg>Added a global create function - the key specific create function is now an optional feature.<commit_after>///////////////////////////////////////////////////////////////////////////////
//
// File: NekManager.hpp
//
// For more information, please see: http://www.nektar.info
//
// The MIT License
//
// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
// Department of Aeronautics, Imperial College London (UK), and Scientific
// Computing and Imaging Institute, University of Utah (USA).
//
// License for the specific language governing rights and limitations under
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Description:
//
///////////////////////////////////////////////////////////////////////////////

#ifndef NEKTAR_LIB_UTILITIES_BASIC_UTILS_NEK_MANAGER_HPP
#define NEKTAR_LIB_UTILITIES_BASIC_UTILS_NEK_MANAGER_HPP

#include <algorithm>
#include <map>

#include <boost/function.hpp>
#include <boost/call_traits.hpp>

#include <LibUtilities/BasicUtils/ErrorUtil.hpp>

using namespace std;

template<typename KeyType, typename ValueType>
class NekManagerCreator
{
    public:
        ValueType operator()(const KeyType& key)
        {
            return ValueType::Create(key);
        }
};

template <typename KeyType, typename ValueType>
class NekManager
{
    public:
        typedef boost::function<ValueType (const KeyType& key)> CreateFuncType;
        typedef std::map<KeyType, ValueType> ValueContainer;
        typedef std::map<KeyType, CreateFuncType> CreateFuncContainer;

        NekManager() :
            m_values(),
            m_globalCreateFunc(NekManagerCreator<KeyType, ValueType>()),
            m_keySpecificCreateFuncs()
        {
        };

        explicit NekManager(CreateFuncType f) :
            m_values(),
            m_globalCreateFunc(f),
            m_keySpecificCreateFuncs()
        {
        }

        ~NekManager() {}

        void RegisterCreator(typename boost::call_traits<KeyType>::const_reference key,
                             const CreateFuncType& createFunc)
        {
            m_keySpecificCreateFuncs[key] = createFunc;
        }

        ValueType& operator[](typename boost::call_traits<KeyType>::const_reference key)
        {
            typename ValueContainer::iterator found = m_values.find(key);
            if( found != m_values.end() )
            {
                return (*found).second;
            }
            else
            {
                // No object, create a new one.
                CreateFuncType f = m_globalCreateFunc;
                typename CreateFuncContainer::iterator keyFound = m_keySpecificCreateFuncs.find(key);
                if( keyFound != m_keySpecificCreateFuncs.end() )
                {
                    f = (*keyFound).second;
                }

                ValueType newObj = f(key);
                m_values[key] = newObj;
                return m_values[key];
            }
        }

    private:
        NekManager(const NekManager<KeyType, ValueType>& rhs);
        NekManager<KeyType, ValueType>& operator=(const NekManager<KeyType, ValueType>& rhs);

        ValueContainer m_values;
        CreateFuncType m_globalCreateFunc;
        CreateFuncContainer m_keySpecificCreateFuncs;
};

#endif //NEKTAR_LIB_UTILITIES_BASIC_UTILS_NEK_MANAGER_HPP
<|endoftext|>


<commit_before>/*********************************************************************
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2019, Hamburg University
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Hamburg University nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *********************************************************************/

/* Author: Jonas Tietz */

#include "tf_publisher_capability.h"
#include <moveit/utils/message_checks.h>
#include <moveit/move_group/capability_names.h>
#include <tf2_ros/transform_broadcaster.h>
#include <tf2_eigen/tf2_eigen.h>
#include <moveit/robot_state/robot_state.h>
#include <moveit/robot_state/attached_body.h>

namespace move_group
{
TfPublisher::TfPublisher() : MoveGroupCapability("TfPublisher")
{
}

TfPublisher::~TfPublisher()
{
  keep_running_ = false;
  thread_.join();
}

namespace
{
void publishSubframes(tf2_ros::TransformBroadcaster& broadcaster, const moveit::core::FixedTransformsMap& subframes,
                      const std::string& parent_object, const std::string& parent_frame, const ros::Time& stamp)
{
  geometry_msgs::TransformStamped transform;
  for (auto& subframe : subframes)
  {
    transform = tf2::eigenToTransform(subframe.second);
    transform.child_frame_id = parent_object + "/" + subframe.first;
    transform.header.stamp = stamp;
    transform.header.frame_id = parent_frame;
    broadcaster.sendTransform(transform);
  }
}
}  // namespace

void TfPublisher::publishPlanningSceneFrames()
{
  tf2_ros::TransformBroadcaster broadcaster;
  geometry_msgs::TransformStamped transform;
  ros::Rate rate(rate_);

  while (keep_running_)
  {
    {
      ros::Time stamp = ros::Time::now();
      planning_scene_monitor::LockedPlanningSceneRO locked_planning_scene(context_->planning_scene_monitor_);
      collision_detection::WorldConstPtr world = locked_planning_scene->getWorld();
      std::string planning_frame = locked_planning_scene->getPlanningFrame();

      for (const auto& obj : *world)
      {
        std::string object_frame = prefix_ + obj.second->id_;
        transform = tf2::eigenToTransform(obj.second->shape_poses_[0]);
        transform.child_frame_id = object_frame;
        transform.header.stamp = stamp;
        transform.header.frame_id = planning_frame;
        broadcaster.sendTransform(transform);

        const moveit::core::FixedTransformsMap& subframes = obj.second->subframe_poses_;
        publishSubframes(broadcaster, subframes, object_frame, planning_frame, stamp);
      }

      const moveit::core::RobotState& rs = locked_planning_scene->getCurrentState();
      std::vector<const moveit::core::AttachedBody*> attached_collision_objects;
      rs.getAttachedBodies(attached_collision_objects);
      for (const moveit::core::AttachedBody* attached_body : attached_collision_objects)
      {
        std::string object_frame = prefix_ + attached_body->getName();
        transform = tf2::eigenToTransform(attached_body->getFixedTransforms()[0]);
        transform.child_frame_id = object_frame;
        transform.header.stamp = stamp;
        transform.header.frame_id = attached_body->getAttachedLinkName();
        broadcaster.sendTransform(transform);

        const moveit::core::FixedTransformsMap& subframes = attached_body->getSubframeTransforms();
        publishSubframes(broadcaster, subframes, object_frame, object_frame, stamp);
      }
    }

    rate.sleep();
  }
}

void TfPublisher::initialize()
{
  ros::NodeHandle nh = ros::NodeHandle("~");

  std::string prefix = nh.getNamespace() + "/";
  nh.param("planning_scene_frame_publishing_rate", rate_, 10);
  nh.param("planning_scene_tf_prefix", prefix_, prefix);
  keep_running_ = true;

  ROS_INFO("Initializing MoveGroupTfPublisher with a frame publishing rate of %d", rate_);
  thread_ = std::thread(&TfPublisher::publishPlanningSceneFrames, this);
}
}  // namespace move_group

#include <class_loader/class_loader.hpp>
CLASS_LOADER_REGISTER_CLASS(move_group::TfPublisher, move_group::MoveGroupCapability)
<commit_msg>fixup! Fix TfPublisher subframe publishing<commit_after>/*********************************************************************
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2019, Hamburg University
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Hamburg University nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *********************************************************************/

/* Author: Jonas Tietz */

#include "tf_publisher_capability.h"
#include <moveit/utils/message_checks.h>
#include <moveit/move_group/capability_names.h>
#include <tf2_ros/transform_broadcaster.h>
#include <tf2_eigen/tf2_eigen.h>
#include <moveit/robot_state/robot_state.h>
#include <moveit/robot_state/attached_body.h>

namespace move_group
{
TfPublisher::TfPublisher() : MoveGroupCapability("TfPublisher")
{
}

TfPublisher::~TfPublisher()
{
  keep_running_ = false;
  thread_.join();
}

namespace
{
void publishSubframes(tf2_ros::TransformBroadcaster& broadcaster, const moveit::core::FixedTransformsMap& subframes,
                      const std::string& parent_object, const std::string& parent_frame, const ros::Time& stamp)
{
  geometry_msgs::TransformStamped transform;
  for (auto& subframe : subframes)
  {
    transform = tf2::eigenToTransform(subframe.second);
    transform.child_frame_id = parent_object + "/" + subframe.first;
    transform.header.stamp = stamp;
    transform.header.frame_id = parent_frame;
    broadcaster.sendTransform(transform);
  }
}
}  // namespace

void TfPublisher::publishPlanningSceneFrames()
{
  tf2_ros::TransformBroadcaster broadcaster;
  geometry_msgs::TransformStamped transform;
  ros::Rate rate(rate_);

  while (keep_running_)
  {
    {
      ros::Time stamp = ros::Time::now();
      planning_scene_monitor::LockedPlanningSceneRO locked_planning_scene(context_->planning_scene_monitor_);
      collision_detection::WorldConstPtr world = locked_planning_scene->getWorld();
      std::string planning_frame = locked_planning_scene->getPlanningFrame();

      for (const auto& obj : *world)
      {
        std::string object_frame = prefix_ + obj.second->id_;
        transform = tf2::eigenToTransform(obj.second->shape_poses_[0]);
        transform.child_frame_id = object_frame;
        transform.header.stamp = stamp;
        transform.header.frame_id = planning_frame;
        broadcaster.sendTransform(transform);

        const moveit::core::FixedTransformsMap& subframes = obj.second->subframe_poses_;
        publishSubframes(broadcaster, subframes, object_frame, planning_frame, stamp);
      }

      const moveit::core::RobotState& rs = locked_planning_scene->getCurrentState();
      std::vector<const moveit::core::AttachedBody*> attached_collision_objects;
      rs.getAttachedBodies(attached_collision_objects);
      for (const moveit::core::AttachedBody* attached_body : attached_collision_objects)
      {
        std::string object_frame = prefix_ + attached_body->getName();
        transform = tf2::eigenToTransform(attached_body->getFixedTransforms()[0]);
        transform.child_frame_id = object_frame;
        transform.header.stamp = stamp;
        transform.header.frame_id = attached_body->getAttachedLinkName();
        broadcaster.sendTransform(transform);

        const moveit::core::FixedTransformsMap& subframes = attached_body->getSubframeTransforms();
        publishSubframes(broadcaster, subframes, object_frame, attached_body->getAttachedLinkName(), stamp);
      }
    }

    rate.sleep();
  }
}

void TfPublisher::initialize()
{
  ros::NodeHandle nh = ros::NodeHandle("~");

  std::string prefix = nh.getNamespace() + "/";
  nh.param("planning_scene_frame_publishing_rate", rate_, 10);
  nh.param("planning_scene_tf_prefix", prefix_, prefix);
  keep_running_ = true;

  ROS_INFO("Initializing MoveGroupTfPublisher with a frame publishing rate of %d", rate_);
  thread_ = std::thread(&TfPublisher::publishPlanningSceneFrames, this);
}
}  // namespace move_group

#include <class_loader/class_loader.hpp>
CLASS_LOADER_REGISTER_CLASS(move_group::TfPublisher, move_group::MoveGroupCapability)
<|endoftext|>


<commit_before>#include "P3dSymLoader.h"
#include "FilepathHelper.h"
#include "JsonSerializer.h"
#include "Exception.h"
#include "SymbolFactory.h"

#include <sm_const.h>
#include <ps_3d.h>
#include <sprite2/Particle3dSymbol.h>

#include <fstream>

namespace gum
{

void P3dSymLoader::Store(s2::Particle3dSymbol* sym) const
{
	int sz = SIZEOF_P3D_EMITTER_CFG + SIZEOF_P3D_SYMBOL * components.size();
	p3d_emitter_cfg* cfg = (p3d_emitter_cfg*) operator new(sz);
	memset(cfg, 0, sz);
	Store(cfg);
	sym->SetEmitterCfg(cfg);

	sym->SetLoop(loop);
	sym->SetLocal(local);
}

void P3dSymLoader::Store(p3d_emitter_cfg* cfg) const
{
	cfg->blend = blend;

	cfg->static_mode = static_mode;

	cfg->emission_time = emission_time;
	cfg->count = count;

	cfg->life = life * 0.001f;
	cfg->life_var = life_var * 0.001f;

	cfg->hori = hori;
	cfg->hori_var = hori_var;
	cfg->vert = vert;
	cfg->vert_var = vert_var;

	cfg->radial_spd = radial_spd;
	cfg->radial_spd_var = radial_spd_var;
	cfg->tangential_spd = tangential_spd;
	cfg->tangential_spd_var = tangential_spd_var;
	cfg->angular_spd = angular_spd;
	cfg->angular_spd_var = angular_spd_var;

	cfg->dis_region = dis_region;
	cfg->dis_region_var = dis_region_var;
	cfg->dis_spd = dis_spd;
	cfg->dis_spd_var = dis_spd_var;

	cfg->gravity = gravity;

	cfg->linear_acc = linear_acc;
	cfg->linear_acc_var = linear_acc_var;

	cfg->fadeout_time = fadeout_time;

	cfg->ground = ground;

	cfg->start_radius = start_radius;
	cfg->start_height = start_height;

	cfg->orient_to_movement = orient_to_movement;

	cfg->blend = blend;

	// todo dir
	cfg->dir.x = 0;
	cfg->dir.y = 0;
	cfg->dir.z = 1;

	cfg->sym_count = components.size();
	cfg->syms = (p3d_symbol*)(cfg+1);
	for (int i = 0, n = components.size(); i < n; ++i) {
		const P3dSymLoader::Component& src = components[i];
		p3d_symbol& dst = cfg->syms[i];

		dst.count = src.count;

		dst.scale_start = src.scale_start * 0.01f;
		dst.scale_end = src.scale_end * 0.01f;

		dst.angle = src.angle;
		dst.angle_var = src.angle_var;

		memcpy(&dst.mul_col_begin.r, &src.mul_col_begin.r, sizeof(dst.mul_col_begin));
		memcpy(&dst.mul_col_end.r, &src.mul_col_end.r, sizeof(dst.mul_col_end));
		memcpy(&dst.add_col_begin.r, &src.add_col_begin.r, sizeof(dst.add_col_begin));
		memcpy(&dst.add_col_end.r, &src.add_col_end.r, sizeof(dst.add_col_end));

// 		if (FilepathHelper::IsFileExist(src.bind_filepath)) {
// 			dst.bind_ps_cfg = PSConfigMgr::Instance()->GetConfig(src.bind_filepath);
// 		}

		dst.ud = LoadSymbol(src.filepath);
		if (!dst.ud) {
			throw Exception("Symbol doesn't exist: %s", src.filepath.c_str());
		}
	}
}

void P3dSymLoader::LoadJson(const std::string& filepath)
{
	Json::Value val;
	Json::Reader reader;
	std::locale::global(std::locale(""));
	std::ifstream fin(filepath.c_str());
	std::locale::global(std::locale("C"));
	reader.parse(fin, val);
	fin.close();

	name = val["name"].asString();

	loop = val["loop"].asBool();
	local = val["local"].asBool();

	static_mode = val["static_mode"].asBool();

	count = val["count"].asInt();
	emission_time = val["emission_time"].asInt() * 0.001f;

	if (val.isMember("life")) {
		life = static_cast<float>(val["life"]["center"].asInt());
		life_var = static_cast<float>(val["life"]["offset"].asInt());
	} else {
		int min = val["min_life"].asInt(),
			max = val["max_life"].asInt();
		life = (min + max) * 0.5f;
		life_var = (max - min) * 0.5f;
	}

	int min, max;
	min = val["min_hori"].asInt();
	max = val["max_hori"].asInt();
	hori = (min + max) * 0.5f * SM_DEG_TO_RAD;
	hori_var = (max - min) * 0.5f * SM_DEG_TO_RAD;

	min = val["min_vert"].asInt();
	max = val["max_vert"].asInt();
	vert = (min + max) * 0.5f * SM_DEG_TO_RAD;
	vert_var = (max - min) * 0.5f * SM_DEG_TO_RAD;

	if (val.isMember("radial_speed")) {
		radial_spd = static_cast<float>(val["radial_speed"]["center"].asInt());
		radial_spd_var = static_cast<float>(val["radial_speed"]["offset"].asInt());
	} else if (val.isMember("speed")) {
		radial_spd = static_cast<float>(val["speed"]["center"].asInt());
		radial_spd_var = static_cast<float>(val["speed"]["offset"].asInt());
	} else {
		int min, max;
		min = val["min_spd"].asInt();
		max = val["max_spd"].asInt();
		radial_spd = (min + max) * 0.5f;
		radial_spd_var = (max - min) * 0.5f;
	}

	tangential_spd = static_cast<float>(val["tangential_spd"]["center"].asInt());
	tangential_spd_var = static_cast<float>(val["tangential_spd"]["offset"].asInt());

	// todo
	radial_spd *= 0.25f;
	radial_spd_var *= 0.25f;

	if (val.isMember("angular_speed")) {
		angular_spd = val["angular_speed"]["center"].asInt() * SM_DEG_TO_RAD;
		angular_spd_var = val["angular_speed"]["offset"].asInt() * SM_DEG_TO_RAD;
	} else {
		int min, max;
		min = val["min_angular_spd"].asInt();
		max = val["max_angular_spd"].asInt();
		angular_spd = (min + max) * 0.5f * SM_DEG_TO_RAD;
		angular_spd_var = (max - min) * 0.5f * SM_DEG_TO_RAD;
	}

	dis_region = static_cast<float>(val["disturbance_radius"]["center"].asInt());
	dis_region_var = static_cast<float>(val["disturbance_radius"]["offset"].asInt());

	dis_spd = static_cast<float>(val["disturbance_spd"]["center"].asInt());
	dis_spd_var = static_cast<float>(val["disturbance_spd"]["offset"].asInt());

	gravity = static_cast<float>(val["gravity"].asInt());
	// todo
	gravity *= 0.3f;

	linear_acc = static_cast<float>(val["linear_acc"]["center"].asInt());
	linear_acc_var = static_cast<float>(val["linear_acc"]["offset"].asInt());

	inertia = static_cast<float>(val["inertia"].asInt());

	fadeout_time = val["fadeout_time"].asInt() * 0.001f;

	if (!val.isMember("ground")) {
		ground = P3D_GROUND_WITH_BOUNCE;
	} else {
		ground = val["ground"].asInt();
	}

	start_radius = abs(static_cast<float>(val["start_pos"]["radius"].asInt()));
	start_height = static_cast<float>(val["start_pos"]["height"].asInt());

	orient_to_movement = val["orient_to_movement"].asBool();
	orient_to_parent = val["orient_to_parent"].asBool();

	blend = val["blend"].asInt();

	std::string dir = FilepathHelper::Dir(filepath);
	for (int i = 0, n = val["components"].size(); i < n; ++i) {
		LoadComponent(dir, val["components"][i]);
	}
}

void P3dSymLoader::LoadComponent(const std::string& dir, const Json::Value& comp_val)
{
	Component comp;

	if (!comp_val.isMember("count")) {
		comp.count = 0;
	} else {
		comp.count = comp_val["count"].asInt();
	}

	comp.filepath = comp_val["filepath"].asString();
	comp.filepath = FilepathHelper::Absolute(dir, comp.filepath);

	if (comp_val.isMember("bind ps filepath")) {
		comp.bind_filepath = comp_val["bind ps filepath"].asString();
		if (!comp.bind_filepath.empty()) {
			comp.bind_filepath = FilepathHelper::Absolute(dir, comp.bind_filepath);
		}
	}

	comp.name = comp_val["name"].asString();

	if (comp_val.isMember("scale")) {
		comp.scale_start = comp_val["scale"]["start"].asInt();
		comp.scale_end = comp_val["scale"]["end"].asInt();
	} else {
		comp.scale_start = comp_val["start_scale"].asInt();
		comp.scale_end = comp_val["end_scale"].asInt();
	}

	if (comp_val.isMember("rotate")) {
		int min = comp_val["rotate"]["min"].asInt(),
			max = comp_val["rotate"]["max"].asInt();
		comp.angle = (min + max) * 0.5f;
		comp.angle_var = (max - min) * 0.5f;
	} else {
		comp.angle = comp.angle_var = 0;
	}

	if (comp_val.isMember("mul_col")) {
		comp.mul_col_begin.r = comp_val["mul_col"]["r"].asDouble() * 255;
		comp.mul_col_begin.g = comp_val["mul_col"]["g"].asDouble() * 255;
		comp.mul_col_begin.b = comp_val["mul_col"]["b"].asDouble() * 255;
		comp.mul_col_begin.a = 255;
		comp.mul_col_end = comp.mul_col_begin;
	} else {
		if (comp_val.isMember("mul_col_begin")) {
			JsonSerializer::Load(comp_val["mul_col_begin"], comp.mul_col_begin);
		} else {
			comp.mul_col_begin.r = comp.mul_col_begin.g = comp.mul_col_begin.b = comp.mul_col_begin.a = 255;
		}
		if (comp_val.isMember("mul_col_end")) {
			JsonSerializer::Load(comp_val["mul_col_end"], comp.mul_col_end);
		} else {
			comp.mul_col_end.r = comp.mul_col_end.g = comp.mul_col_end.b = comp.mul_col_end.a = 255;
		}
	}

	if (comp_val.isMember("add_col")) {
		comp.add_col_begin.r = comp_val["add_col"]["r"].asDouble() * 255;
		comp.add_col_begin.g = comp_val["add_col"]["g"].asDouble() * 255;
		comp.add_col_begin.b = comp_val["add_col"]["b"].asDouble() * 255;
		comp.add_col_end = comp.add_col_begin;
	} else {
		if (comp_val.isMember("add_col_begin")) {
			JsonSerializer::Load(comp_val["add_col_begin"], comp.add_col_begin);
		} else {
			comp.add_col_begin.r = comp.add_col_begin.g = comp.add_col_begin.b = comp.add_col_begin.a = 0;
		}
		if (comp_val.isMember("add_col_end")) {
			JsonSerializer::Load(comp_val["add_col_end"], comp.add_col_end);
		} else {
			comp.add_col_end.r = comp.add_col_end.g = comp.add_col_end.b = comp.add_col_end.a = 0;
		}
	}

	if (comp_val.isMember("alpha")) {
		float start = comp_val["alpha"]["start"].asInt() * 0.01f;
		float end = comp_val["alpha"]["end"].asInt() * 0.01f;
		comp.mul_col_begin.a *= start;
		comp.mul_col_end.a *= end;
		comp.alpha_start = 255 * start;
		comp.alpha_end = 255 * end;
	}

	if (comp_val.isMember("alpha2")) {
		comp.alpha_start = comp_val["alpha2"]["start"].asInt();
		comp.alpha_end = comp_val["alpha2"]["end"].asInt();
	}

	comp.start_z = comp_val["start_z"].asInt();

	components.push_back(comp);
}

s2::Symbol* P3dSymLoader::LoadSymbol(const std::string& filepath) const
{
	return SymbolFactory::Instance()->Create(filepath);
}

}<commit_msg>[FIXED] p3d sym loader<commit_after>#include "P3dSymLoader.h"
#include "FilepathHelper.h"
#include "JsonSerializer.h"
#include "Exception.h"
#include "SymbolFactory.h"

#include <sm_const.h>
#include <ps_3d.h>
#include <sprite2/Particle3dSymbol.h>

#include <fstream>

namespace gum
{

void P3dSymLoader::Store(s2::Particle3dSymbol* sym) const
{
	int sz = SIZEOF_P3D_EMITTER_CFG + SIZEOF_P3D_SYMBOL * components.size();
	p3d_emitter_cfg* cfg = (p3d_emitter_cfg*) operator new(sz);
	memset(cfg, 0, sz);
	Store(cfg);
	sym->SetEmitterCfg(cfg);

	sym->SetLoop(loop);
	sym->SetLocal(local);
}

void P3dSymLoader::Store(p3d_emitter_cfg* cfg) const
{
	cfg->blend = blend;

	cfg->static_mode = static_mode;

	cfg->emission_time = emission_time;
	cfg->count = count;

	cfg->life = life * 0.001f;
	cfg->life_var = life_var * 0.001f;

	cfg->hori = hori;
	cfg->hori_var = hori_var;
	cfg->vert = vert;
	cfg->vert_var = vert_var;

	cfg->radial_spd = radial_spd;
	cfg->radial_spd_var = radial_spd_var;
	cfg->tangential_spd = tangential_spd;
	cfg->tangential_spd_var = tangential_spd_var;
	cfg->angular_spd = angular_spd;
	cfg->angular_spd_var = angular_spd_var;

	cfg->dis_region = dis_region;
	cfg->dis_region_var = dis_region_var;
	cfg->dis_spd = dis_spd;
	cfg->dis_spd_var = dis_spd_var;

	cfg->gravity = gravity;

	cfg->linear_acc = linear_acc;
	cfg->linear_acc_var = linear_acc_var;

	cfg->fadeout_time = fadeout_time;

	cfg->ground = ground;

	cfg->start_radius = start_radius;
	cfg->start_height = start_height;

	cfg->orient_to_movement = orient_to_movement;

	cfg->blend = blend;

	// todo dir
	cfg->dir.x = 0;
	cfg->dir.y = 0;
	cfg->dir.z = 1;

	cfg->sym_count = components.size();
	cfg->syms = (p3d_symbol*)(cfg+1);
	for (int i = 0, n = components.size(); i < n; ++i) {
		const P3dSymLoader::Component& src = components[i];
		p3d_symbol& dst = cfg->syms[i];

		dst.count = src.count;

		dst.scale_start = src.scale_start * 0.01f;
		dst.scale_end = src.scale_end * 0.01f;

		dst.angle = src.angle * SM_DEG_TO_RAD;
		dst.angle_var = src.angle_var * SM_DEG_TO_RAD;

		memcpy(&dst.mul_col_begin.r, &src.mul_col_begin.r, sizeof(dst.mul_col_begin));
		memcpy(&dst.mul_col_end.r, &src.mul_col_end.r, sizeof(dst.mul_col_end));
		memcpy(&dst.add_col_begin.r, &src.add_col_begin.r, sizeof(dst.add_col_begin));
		memcpy(&dst.add_col_end.r, &src.add_col_end.r, sizeof(dst.add_col_end));

// 		if (FilepathHelper::IsFileExist(src.bind_filepath)) {
// 			dst.bind_ps_cfg = PSConfigMgr::Instance()->GetConfig(src.bind_filepath);
// 		}

		dst.ud = LoadSymbol(src.filepath);
		if (!dst.ud) {
			throw Exception("Symbol doesn't exist: %s", src.filepath.c_str());
		}
	}
}

void P3dSymLoader::LoadJson(const std::string& filepath)
{
	Json::Value val;
	Json::Reader reader;
	std::locale::global(std::locale(""));
	std::ifstream fin(filepath.c_str());
	std::locale::global(std::locale("C"));
	reader.parse(fin, val);
	fin.close();

	name = val["name"].asString();

	loop = val["loop"].asBool();
	local = val["local"].asBool();

	static_mode = val["static_mode"].asBool();

	count = val["count"].asInt();
	emission_time = val["emission_time"].asInt() * 0.001f;

	if (val.isMember("life")) {
		life = static_cast<float>(val["life"]["center"].asInt());
		life_var = static_cast<float>(val["life"]["offset"].asInt());
	} else {
		int min = val["min_life"].asInt(),
			max = val["max_life"].asInt();
		life = (min + max) * 0.5f;
		life_var = (max - min) * 0.5f;
	}

	int min, max;
	min = val["min_hori"].asInt();
	max = val["max_hori"].asInt();
	hori = (min + max) * 0.5f * SM_DEG_TO_RAD;
	hori_var = (max - min) * 0.5f * SM_DEG_TO_RAD;

	min = val["min_vert"].asInt();
	max = val["max_vert"].asInt();
	vert = (min + max) * 0.5f * SM_DEG_TO_RAD;
	vert_var = (max - min) * 0.5f * SM_DEG_TO_RAD;

	if (val.isMember("radial_speed")) {
		radial_spd = static_cast<float>(val["radial_speed"]["center"].asInt());
		radial_spd_var = static_cast<float>(val["radial_speed"]["offset"].asInt());
	} else if (val.isMember("speed")) {
		radial_spd = static_cast<float>(val["speed"]["center"].asInt());
		radial_spd_var = static_cast<float>(val["speed"]["offset"].asInt());
	} else {
		int min, max;
		min = val["min_spd"].asInt();
		max = val["max_spd"].asInt();
		radial_spd = (min + max) * 0.5f;
		radial_spd_var = (max - min) * 0.5f;
	}

	tangential_spd = static_cast<float>(val["tangential_spd"]["center"].asInt());
	tangential_spd_var = static_cast<float>(val["tangential_spd"]["offset"].asInt());

	// todo
	radial_spd *= 0.25f;
	radial_spd_var *= 0.25f;

	if (val.isMember("angular_speed")) {
		angular_spd = val["angular_speed"]["center"].asInt() * SM_DEG_TO_RAD;
		angular_spd_var = val["angular_speed"]["offset"].asInt() * SM_DEG_TO_RAD;
	} else {
		int min, max;
		min = val["min_angular_spd"].asInt();
		max = val["max_angular_spd"].asInt();
		angular_spd = (min + max) * 0.5f * SM_DEG_TO_RAD;
		angular_spd_var = (max - min) * 0.5f * SM_DEG_TO_RAD;
	}

	dis_region = static_cast<float>(val["disturbance_radius"]["center"].asInt());
	dis_region_var = static_cast<float>(val["disturbance_radius"]["offset"].asInt());

	dis_spd = static_cast<float>(val["disturbance_spd"]["center"].asInt());
	dis_spd_var = static_cast<float>(val["disturbance_spd"]["offset"].asInt());

	gravity = static_cast<float>(val["gravity"].asInt());
	// todo
	gravity *= 0.3f;

	linear_acc = static_cast<float>(val["linear_acc"]["center"].asInt());
	linear_acc_var = static_cast<float>(val["linear_acc"]["offset"].asInt());

	inertia = static_cast<float>(val["inertia"].asInt());

	fadeout_time = val["fadeout_time"].asInt() * 0.001f;

	if (!val.isMember("ground")) {
		ground = P3D_GROUND_WITH_BOUNCE;
	} else {
		ground = val["ground"].asInt();
	}

	start_radius = abs(static_cast<float>(val["start_pos"]["radius"].asInt()));
	start_height = static_cast<float>(val["start_pos"]["height"].asInt());

	orient_to_movement = val["orient_to_movement"].asBool();
	orient_to_parent = val["orient_to_parent"].asBool();

	blend = val["blend"].asInt();

	std::string dir = FilepathHelper::Dir(filepath);
	for (int i = 0, n = val["components"].size(); i < n; ++i) {
		LoadComponent(dir, val["components"][i]);
	}
}

void P3dSymLoader::LoadComponent(const std::string& dir, const Json::Value& comp_val)
{
	Component comp;

	if (!comp_val.isMember("count")) {
		comp.count = 0;
	} else {
		comp.count = comp_val["count"].asInt();
	}

	comp.filepath = comp_val["filepath"].asString();
	comp.filepath = FilepathHelper::Absolute(dir, comp.filepath);

	if (comp_val.isMember("bind ps filepath")) {
		comp.bind_filepath = comp_val["bind ps filepath"].asString();
		if (!comp.bind_filepath.empty()) {
			comp.bind_filepath = FilepathHelper::Absolute(dir, comp.bind_filepath);
		}
	}

	comp.name = comp_val["name"].asString();

	if (comp_val.isMember("scale")) {
		comp.scale_start = comp_val["scale"]["start"].asInt();
		comp.scale_end = comp_val["scale"]["end"].asInt();
	} else {
		comp.scale_start = comp_val["start_scale"].asInt();
		comp.scale_end = comp_val["end_scale"].asInt();
	}

	if (comp_val.isMember("rotate")) {
		int min = comp_val["rotate"]["min"].asInt(),
			max = comp_val["rotate"]["max"].asInt();
		comp.angle = (min + max) * 0.5f;
		comp.angle_var = (max - min) * 0.5f;
	} else {
		comp.angle = comp.angle_var = 0;
	}

	if (comp_val.isMember("mul_col")) {
		comp.mul_col_begin.r = comp_val["mul_col"]["r"].asDouble() * 255;
		comp.mul_col_begin.g = comp_val["mul_col"]["g"].asDouble() * 255;
		comp.mul_col_begin.b = comp_val["mul_col"]["b"].asDouble() * 255;
		comp.mul_col_begin.a = 255;
		comp.mul_col_end = comp.mul_col_begin;
	} else {
		if (comp_val.isMember("mul_col_begin")) {
			JsonSerializer::Load(comp_val["mul_col_begin"], comp.mul_col_begin);
		} else {
			comp.mul_col_begin.r = comp.mul_col_begin.g = comp.mul_col_begin.b = comp.mul_col_begin.a = 255;
		}
		if (comp_val.isMember("mul_col_end")) {
			JsonSerializer::Load(comp_val["mul_col_end"], comp.mul_col_end);
		} else {
			comp.mul_col_end.r = comp.mul_col_end.g = comp.mul_col_end.b = comp.mul_col_end.a = 255;
		}
	}

	if (comp_val.isMember("add_col")) {
		comp.add_col_begin.r = comp_val["add_col"]["r"].asDouble() * 255;
		comp.add_col_begin.g = comp_val["add_col"]["g"].asDouble() * 255;
		comp.add_col_begin.b = comp_val["add_col"]["b"].asDouble() * 255;
		comp.add_col_end = comp.add_col_begin;
	} else {
		if (comp_val.isMember("add_col_begin")) {
			JsonSerializer::Load(comp_val["add_col_begin"], comp.add_col_begin);
		} else {
			comp.add_col_begin.r = comp.add_col_begin.g = comp.add_col_begin.b = comp.add_col_begin.a = 0;
		}
		if (comp_val.isMember("add_col_end")) {
			JsonSerializer::Load(comp_val["add_col_end"], comp.add_col_end);
		} else {
			comp.add_col_end.r = comp.add_col_end.g = comp.add_col_end.b = comp.add_col_end.a = 0;
		}
	}

	if (comp_val.isMember("alpha")) {
		float start = comp_val["alpha"]["start"].asInt() * 0.01f;
		float end = comp_val["alpha"]["end"].asInt() * 0.01f;
		comp.mul_col_begin.a *= start;
		comp.mul_col_end.a *= end;
		comp.alpha_start = 255 * start;
		comp.alpha_end = 255 * end;
	}

	if (comp_val.isMember("alpha2")) {
		comp.alpha_start = comp_val["alpha2"]["start"].asInt();
		comp.alpha_end = comp_val["alpha2"]["end"].asInt();
	}

	comp.start_z = comp_val["start_z"].asInt();

	components.push_back(comp);
}

s2::Symbol* P3dSymLoader::LoadSymbol(const std::string& filepath) const
{
	return SymbolFactory::Instance()->Create(filepath);
}

}<|endoftext|>


<commit_before>/**
 * @file device_properties.hxx
 *
 * @brief
 *
 *
 */

 #pragma once
 #include <gunrock/util/meta.hxx>

namespace gunrock {
namespace util {

/**
 * @namespace properties
 * CUDA device properties namespace.
 */
namespace properties {}
}
}<commit_msg>:wastebasket: Trashing my ideas for device_properties.hxx<commit_after>/**
 * @file device_properties.hxx
 *
 * @brief
 *
 *
 */

#pragma once
#include <gunrock/util/meta.hxx>
#include <map>

namespace gunrock {
namespace util {

enum architecture_t
{
  hopper = 900, // Unknown
  ampere = 800, // (CUDA 11 and later)
  turing = 750, // (CUDA 10 and later)

  volta_j = 720, // Jetson
  volta = 700,   // (CUDA 9 and later)

  pascal_j = 620, // Jetson
  pascal_g = 610,
  pascal = 600, // (CUDA 8 and later)

  maxwell_j = 530, // Jetson
  maxwell_g = 520, // GTX
  maxwell = 500,   // (CUDA 6 and later)

  kepler_r = 370,
  kepler_p = 350,
  kepler_j = 320,
  kepler = 300, // (CUDA 5 and later)

  fermi_ = 210,
  fermi = 200, // (CUDA 3.2 - CUDA 8) deprecated
  def = 1,
  unknown = 0
}; // enum architecture_t

/**
 * @namespace properties
 * CUDA device properties namespace.
 *
 * @todo Let's rely on #defines right now, till we find a better way.
 */
namespace properties {

typedef unsigned architecture_idx_t;

/**
 * @todo there's no constexpr for std::map, I need to find a better way to do
 * this. Right now, we are using hardcoded indexes for each architecture. But
 * they are not intuitive. For example, pascal's major number is 6 and minor
 * are 6.1, 6.2, but they are mapped to infex 10, 11 and 12.
 *
 */

constexpr architecture_idx_t
get_current_arch_idx()
{
  // architecture_t::default
  architecture_idx_t gunrock_sm_idx = 1;
#ifdef __CUDA_ARCH__
#if GUNROCK_CUDA_ARCH == architecture_t::ampere;
  gunrock_sm_idx = 16;
#elif GUNROCK_CUDA_ARCH == architecture_t::turing;
  gunrock_sm_idx = 15;
#elif GUNROCK_CUDA_ARCH == architecture_t::volta_j;
  gunrock_sm_idx = 14;
#elif GUNROCK_CUDA_ARCH >= architecture_t::volta;
  gunrock_sm_idx = 13;
#elif GUNROCK_CUDA_ARCH == architecture_t::pascal_j;
  gunrock_sm_idx = 12;
#elif GUNROCK_CUDA_ARCH >= architecture_t::pascal_g;
  gunrock_sm_idx = 11;
#elif GUNROCK_CUDA_ARCH >= architecture_t::pascal;
  gunrock_sm_idx = 10;
#elif GUNROCK_CUDA_ARCH == architecture_t::maxwell_j;
  gunrock_sm_idx = 9;
#elif GUNROCK_CUDA_ARCH >= architecture_t::maxwell_g;
  gunrock_sm_idx = 8;
#elif GUNROCK_CUDA_ARCH >= architecture_t::maxwell;
  gunrock_sm_idx = 7;
#elif GUNROCK_CUDA_ARCH == architecture_t::kepler_r;
  gunrock_sm_idx = 6;
#elif GUNROCK_CUDA_ARCH >= architecture_t::kepler_p;
  gunrock_sm_idx = 5;
#elif GUNROCK_CUDA_ARCH >= architecture_t::kepler_j;
  gunrock_sm_idx = 4;
#elif GUNROCK_CUDA_ARCH == architecture_t::kepler;
  gunrock_sm_idx = 3;
#else
#error "Gunrock: SM arch 2.1 or below is unsupported."
#endif
#else // __CUDA_ARCH__
  gunrock_sm_idx = 0;
#endif

  return gunrock_sm_idx;
}

template<typename property_t, size_t N>
constexpr property_t
get_property(
  const std::array<std::pair<const architecture_t, property_t>, N>& database,
  architecture_t arch_idx = get_current_arch_idx())
{

  return database[arch_idx].second;
}

constexpr unsigned
maximum_threads_per_warp()
{
  const std::array<std::pair<const architecture_t, unsigned>, 1> max_threads{
    { { architecture_t::def, 32 } }
  };

  return get_property(max_threads, architecture_t::def);
}

constexpr size_t
sm_memory_bank_stride_size()
{
  const std::array<std::pair<const architecture_t, size_t>, 1> strides{
    { { architecture_t::def, 4 } }
  };

  return get_property(strides, architecture_t::def);
}

constexpr unsigned
memory_banks_per_sm()
{
  const std::array<std::pair<const architecture_t, unsigned>, 1> banks{
    { { architecture_t::def, 32 } }
  };

  return get_property(banks, architecture_t::def);
}

/**
 * @todo how to handle configurable shmem?
 */
constexpr size_t
maximum_shared_memory_per_sm()
{
  enum : size_t
  {
    KiB = 1024
  };

  const std::array<std::pair<const architecture_t, unsigned>, 14> shared_memory{
    { { architecture_t::ampere, 48 * KiB }, // XXX
      { architecture_t::turing, 64 * KiB },

      { architecture_t::volta_j, 96 * KiB }, // XXX
      { architecture_t::volta, 96 * KiB },

      { architecture_t::pascal_j, 96 * KiB }, // XXX
      { architecture_t::pascal_g, 96 * KiB },
      { architecture_t::pascal, 64 * KiB },

      { architecture_t::maxwell_j, 48 * KiB }, // XXX
      { architecture_t::maxwell_g, 96 * KiB },
      { architecture_t::maxwell, 64 * KiB },

      { architecture_t::kepler_r, 112 * KiB }, // Configurable?
      { architecture_t::kepler_p, 48 * KiB },
      { architecture_t::kepler_j, 48 * KiB }, // XXX
      { architecture_t::kepler, 48 * KiB } }
  };

  return get_property(shared_memory);
}

constexpr unsigned
physical_threads_per_sm()
{
  const std::array<std::pair<const architecture_t, unsigned>, 14> threads_sm{
    { { architecture_t::ampere, 48 }, // XXX
      { architecture_t::turing, 1024 },

      { architecture_t::volta_j, 2048 }, // XXX
      { architecture_t::volta, 2048 },

      { architecture_t::pascal_j, 2048 }, // XXX
      { architecture_t::pascal_g, 2048 },
      { architecture_t::pascal, 2048 },

      { architecture_t::maxwell_j, 2048 }, // XXX
      { architecture_t::maxwell_g, 2048 },
      { architecture_t::maxwell, 2048 },

      { architecture_t::kepler_r, 2048 },
      { architecture_t::kepler_p, 2048 },
      { architecture_t::kepler_j, 2048 }, // XXX
      { architecture_t::kepler, 2048 } }
  };

  return get_property(threads_sm);
}

unsigned
maximum_threads_per_cta() const
{
  static const std::map<architecture_t, unsigned> threads_cta{
    { architecture_t::def, 1024 }
  };

  return get_property(threads_cta, architecture_t::def);
}

unsigned
maximum_ctas_per_sm() const
{
  static const std::map<architecture_t, unsigned> ctas{
    { architecture_t::ampere, 48 }, // XXX
    { architecture_t::turing, 16 },

    { architecture_t::volta_j, 32 }, // XXX
    { architecture_t::volta, 32 },

    { architecture_t::pascal_j, 32 }, // XXX
    { architecture_t::pascal_g, 32 },  { architecture_t::pascal, 32 },

    { architecture_t::maxwell_j, 32 }, // XXX
    { architecture_t::maxwell_g, 32 }, { architecture_t::maxwell, 32 },

    { architecture_t::kepler_r, 16 },  { architecture_t::kepler_p, 16 },
    { architecture_t::kepler_j, 16 }, // XXX
    { architecture_t::kepler, 16 }
  };

  return get_property(ctas);
}

unsigned
maximum_registers_per_sm() const
{
  static const std::map<architecture_t, unsigned> registers{
    { architecture_t::def, 64 * 1024 }
  };

  return get_property(registers, architecture_t::def);
}

} // namespace properties

} // namespace util
} // namespace gunrock<|endoftext|>


<commit_before>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_EVALUATION_INTERFACE_HH
#define DUNE_GDT_EVALUATION_INTERFACE_HH

#include <memory>

#include <dune/stuff/common/disable_warnings.hh>
# include <dune/common/dynmatrix.hh>
# include <dune/common/fvector.hh>
#include <dune/stuff/common/reenable_warnings.hh>

#include <dune/stuff/functions/interfaces.hh>
#include <dune/stuff/common/crtp.hh>

namespace Dune {
namespace GDT {
namespace LocalEvaluation {

/**
 *  \brief  Interface for local evaluations that depend on a codim 0 entity.
 *  \tparam numArguments  The number of local bases.
 *  \note   All evaluations have to be copyable!
 */
template< class Traits, int numArguments >
class Codim0Interface
{
  static_assert(AlwaysFalse< Traits >::value, "There is no interface for this numArguments!");
};

/**
 *  \brief  Interface for unary codim 0 evaluations.
 */
template< class Traits >
class Codim0Interface< Traits, 1 >
  : public Stuff::CRTPInterface< Codim0Interface< Traits, 1 >, Traits >
{
public:
  typedef typename Traits::derived_type           derived_type;
  typedef typename Traits::EntityType             EntityType;
  typedef typename Traits::LocalfunctionTupleType LocalfunctionTupleType;
  typedef typename Traits::DomainFieldType        DomainFieldType;
  static const unsigned int dimDomain = Traits::dimDomain;

  LocalfunctionTupleType localFunctions(const EntityType& entity) const
  {
    CHECK_CRTP(this->as_imp(*this).localFunctions(entity));
    return this->as_imp(*this).localFunctions(entity);
  }

  /**
   *  \brief  Computes the needed integration order.
   *  \tparam R   RangeFieldType
   *  \tparam r   dimRange of the testBase
   *  \tparam rC  dimRangeRows of the testBase
   */
  template< class R, int r, int rC >
  size_t order(const LocalfunctionTupleType& localFunctions,
               const Stuff::LocalfunctionSetInterface
                   < EntityType, DomainFieldType, dimDomain, R, r, rC >& testBase) const
  {
    CHECK_CRTP(this->as_imp(*this).order(localFunctions, testBase));
    return this->as_imp(*this).order(localFunctions, testBase);
  }

  /**
   *  \brief  Computes a unary codim 0 evaluation.
   *  \tparam R   RangeFieldType
   *  \tparam r   dimRange of the testBase
   *  \tparam rC  dimRangeRows of the testBase
   *  \attention ret is assumed to be zero!
   */
  template< class R, int r, int rC >
  void evaluate(const LocalfunctionTupleType& localFunctions,
                const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain, R, r, rC >& testBase,
                const Dune::FieldVector< DomainFieldType, dimDomain >& localPoint,
                Dune::DynamicVector< R >& ret) const
  {
    CHECK_AND_CALL_CRTP(this->as_imp(*this).evaluate(localFunctions, testBase, localPoint, ret));
  }
}; // class Codim0Interface< Traits, 1 >

/**
 *  \brief  Interface for binary codim 0 evaluations.
 **/
template< class Traits >
class Codim0Interface< Traits, 2 >
  : public Stuff::CRTPInterface< Codim0Interface< Traits, 2 >, Traits >
{
public:
  typedef typename Traits::derived_type           derived_type;
  typedef typename Traits::EntityType             EntityType;
  typedef typename Traits::LocalfunctionTupleType LocalfunctionTupleType;
  typedef typename Traits::DomainFieldType        DomainFieldType;
  static const unsigned int dimDomain = Traits::dimDomain;

  /**
   *  \brief  Computes the needed integration order.
   *  \tparam R       RangeFieldType
   *  \tparam r{T,A}  dimRange of the {testBase,ansatzBase}
   *  \tparam rC{T,A} dimRangeRows of the {testBase,ansatzBase}
   */
  template< class R, int rT, int rCT, int rA, int rCA >
  size_t order(const LocalfunctionTupleType& localFunctions,
               const Stuff::LocalfunctionSetInterface
                   < EntityType, DomainFieldType, dimDomain, R, rT, rCT >& testBase,
               const Stuff::LocalfunctionSetInterface
                   < EntityType, DomainFieldType, dimDomain, R, rA, rCA >& ansatzBase) const
  {
    CHECK_CRTP(this->as_imp(*this).order(localFunctions, testBase, ansatzBase));
    return this->as_imp(*this).order(localFunctions, testBase, ansatzBase);
  }

  /**
   *  \brief  Computes a binary codim 0 evaluation.
   *  \tparam R         RangeFieldType
   *  \tparam r{L,T,A}  dimRange of the {localFunction,testBase,ansatzBase}
   *  \tparam rC{L,T,A} dimRangeRows of the {localFunction,testBase,ansatzBase}
   *  \attention ret is assumed to be zero!
   */
  template< class R, int rT, int rCT, int rA, int rCA >
  void evaluate(const LocalfunctionTupleType& localFunctions,
                const Stuff::LocalfunctionSetInterface
                    < EntityType, DomainFieldType, dimDomain, R, rT, rCT >& testBase,
                const Stuff::LocalfunctionSetInterface
                    < EntityType, DomainFieldType, dimDomain, R, rA, rCA >& ansatzBase,
                const Dune::FieldVector< DomainFieldType, dimDomain >& localPoint,
                Dune::DynamicMatrix< R >& ret) const
  {
    CHECK_AND_CALL_CRTP(this->as_imp(*this).evaluate(localFunctions, testBase, ansatzBase, localPoint, ret));
  }
}; // class Codim0Interface< Traits, 2 >

/**
 *  \brief  Interface for local evaluations that depend on an intersection.
 *  \tparam numArguments  The number of local bases.
 *  \note   All evaluations have to be copyable!
 */
template< class Traits, int numArguments >
class Codim1Interface
{
  static_assert(AlwaysFalse< Traits >::value, "There is no interface for this numArguments!");
};

/**
 *  \brief  Interface for unary codim 1 evaluations.
 */
template< class Traits >
class Codim1Interface< Traits, 1 >
    : public Stuff::CRTPInterface< Codim1Interface< Traits, 1 >, Traits >
{
public:
  typedef typename Traits::derived_type           derived_type;
  typedef typename Traits::EntityType             EntityType;
  typedef typename Traits::LocalfunctionTupleType LocalfunctionTupleType;
  typedef typename Traits::DomainFieldType        DomainFieldType;
  static const unsigned int dimDomain = Traits::dimDomain;

  /**
   *  \brief  Computes the needed integration order.
   *  \tparam R   RangeFieldType
   *  \tparam r   dimRange of the testBase
   *  \tparam rC  dimRangeRows of the testBase
   */
  template< class R, int r, int rC >
  size_t order(const LocalfunctionTupleType& localFunctions,
               const Stuff::LocalfunctionSetInterface
                   < EntityType, DomainFieldType, dimDomain, R, r, rC >& testBase) const
  {
    CHECK_CRTP(this->as_imp(*this).order(localFunctions, testBase));
    return this->as_imp(*this).order(localFunctions, testBase);
  }

  /**
   *  \brief  Computes a binary codim 1 evaluation.
   *  \tparam IntersectionType    A model of Dune::Intersection< ... >
   *  \tparam R                   RangeFieldType
   *  \tparam r                   dimRange of the testBase
   *  \tparam rC                  dimRangeRows of the testBase
   *  \attention ret is assumed to be zero!
   */
  template< class IntersectionType, class R, int r, int rC >
  void evaluate(const LocalfunctionTupleType& localFunctions,
                const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain, R, r, rC >& testBase,
                const IntersectionType& intersection,
                const Dune::FieldVector< DomainFieldType, dimDomain - 1 >& localPoint,
                Dune::DynamicVector< R >& ret) const
  {
    CHECK_AND_CALL_CRTP(this->as_imp(*this).evaluate(localFunctions, testBase, intersection, localPoint, ret));
  }
}; // class Codim1Interface< Traits, 1 >

/**
 *  \brief  Interface for binary codim 1 evaluations.
 */
template< class Traits >
class Codim1Interface< Traits, 2 >
  : public Stuff::CRTPInterface< Codim1Interface< Traits, 2 >, Traits >
{
public:
  typedef typename Traits::derived_type           derived_type;
  typedef typename Traits::EntityType             EntityType;
  typedef typename Traits::LocalfunctionTupleType LocalfunctionTupleType;
  typedef typename Traits::DomainFieldType        DomainFieldType;
  static const unsigned int dimDomain = Traits::dimDomain;

  /**
   *  \brief  Computes the needed integration order.
   *  \tparam R                   RangeFieldType
   *  \tparam r{T,A}              dimRange of the {testBase,ansatzBase}
   *  \tparam rC{T,A}             dimRangeRows of the {testBase,ansatzBase}
   */
  template< class R, int rT, int rCT, int rA, int rCA >
  size_t order(const LocalfunctionTupleType& localFunctions,
               const Stuff::LocalfunctionSetInterface
                   < EntityType, DomainFieldType, dimDomain, R, rT, rCT >& testBase,
               const Stuff::LocalfunctionSetInterface
                   < EntityType, DomainFieldType, dimDomain, R, rA, rCA >& ansatzBase) const
  {
    CHECK_CRTP(this->as_imp(*this).order(localFunctions, testBase, ansatzBase));
    return this->as_imp(*this).order(localFunctions, testBase, ansatzBase);
  }

  /**
   *  \brief  Computes a binary codim 1 evaluation.
   *  \tparam IntersectionType    A model of Dune::Intersection< ... >
   *  \tparam R                   RangeFieldType
   *  \tparam r{T,A}              dimRange of the {testBase*,ansatzBase*}
   *  \tparam rC{T,A}             dimRangeRows of the {testBase*,ansatzBase*}
   *  \attention ret is assumed to be zero!
   */
  template< class IntersectionType, class R, int rT, int rCT, int rA, int rCA >
  void evaluate(const LocalfunctionTupleType& localFunctions,
                const Stuff::LocalfunctionSetInterface
                    < EntityType, DomainFieldType, dimDomain, R, rT, rCT >& testBase,
                const Stuff::LocalfunctionSetInterface
                    < EntityType, DomainFieldType, dimDomain, R, rA, rCA >& ansatzBase,
                const IntersectionType& intersection,
                const Dune::FieldVector< DomainFieldType, dimDomain - 1 >& localPoint,
                Dune::DynamicMatrix< R >& ret) const
  {
    CHECK_AND_CALL_CRTP(this->as_imp(*this).evaluate(localFunctions, testBase, ansatzBase, intersection, localPoint,
                                                     ret));
  }
}; // class Codim1Interface< Traits, 2 >

/**
 *  \brief  Interface for quaternary codim 1 evaluations.
 */
template< class Traits >
class Codim1Interface< Traits, 4 >
  : public Stuff::CRTPInterface< Codim1Interface< Traits, 4 >, Traits >
{
public:
  typedef typename Traits::derived_type           derived_type;
  typedef typename Traits::EntityType             EntityType;
  typedef typename Traits::LocalfunctionTupleType LocalfunctionTupleType;
  typedef typename Traits::DomainFieldType        DomainFieldType;
  static const unsigned int dimDomain = Traits::dimDomain;

  /**
   *  \brief  Computes the needed integration order.
   *  \tparam R                     RangeFieldType
   *  \tparam r{T,A}                dimRange of the {testBase*,ansatzBase*}
   *  \tparam rC{T,A}               dimRangeRows of the {testBase*,ansatzBase*}
   */
  template< class R, int rT, int rCT, int rA, int rCA >
  size_t order(const LocalfunctionTupleType localFunctionsEntity,
               const LocalfunctionTupleType localFunctionsNeighbor,
               const Stuff::LocalfunctionSetInterface
                   < EntityType, DomainFieldType, dimDomain, R, rT, rCT >& testBaseEntity,
               const Stuff::LocalfunctionSetInterface
                   < EntityType, DomainFieldType, dimDomain, R, rA, rCA >& ansatzBaseEntity,
               const Stuff::LocalfunctionSetInterface
                   < EntityType, DomainFieldType, dimDomain, R, rT, rCT >& testBaseNeighbor,
               const Stuff::LocalfunctionSetInterface
                   < EntityType, DomainFieldType, dimDomain, R, rA, rCA >& ansatzBaseNeighbor) const
  {
    CHECK_CRTP(this->as_imp(*this).order(localFunctionsEntity, localFunctionsNeighbor,
                                         testBaseEntity, ansatzBaseEntity,
                                         testBaseNeighbor, ansatzBaseNeighbor));
    return this->as_imp(*this).order(localFunctionsEntity, localFunctionsNeighbor,
                                     testBaseEntity, ansatzBaseEntity,
                                     testBaseNeighbor, ansatzBaseNeighbor);
  }

  /**
   *  \brief  Computes a quaternary codim 1 evaluation.
   *  \tparam IntersectionType      A model of Dune::Intersection< ... >
   *  \tparam R                     RangeFieldType
   *  \tparam r{T,A}                dimRange of the {testBase*,ansatzBase*}
   *  \tparam rC{T,A}               dimRangeRows of the {testBase*,ansatzBase*}
   *  \attention entityEntityRet, entityEntityRet, entityEntityRet and neighborEntityRet are assumed to be zero!
   */
  template< class IntersectionType, class R, int rT, int rCT, int rA, int rCA >
  void evaluate(const LocalfunctionTupleType& localFunctionsEntity,
                const LocalfunctionTupleType& localFunctionsNeighbor,
                const Stuff::LocalfunctionSetInterface
                    < EntityType, DomainFieldType, dimDomain, R, rT, rCT >& testBaseEntity,
                const Stuff::LocalfunctionSetInterface
                    < EntityType, DomainFieldType, dimDomain, R, rA, rCA >& ansatzBaseEntity,
                const Stuff::LocalfunctionSetInterface
                    < EntityType, DomainFieldType, dimDomain, R, rT, rCT >& testBaseNeighbor,
                const Stuff::LocalfunctionSetInterface
                    < EntityType, DomainFieldType, dimDomain, R, rA, rCA >& ansatzBaseNeighbor,
                const IntersectionType& intersection,
                const Dune::FieldVector< DomainFieldType, dimDomain - 1 >& localPoint,
                Dune::DynamicMatrix< R >& entityEntityRet,
                Dune::DynamicMatrix< R >& neighborNeighborRet,
                Dune::DynamicMatrix< R >& entityNeighborRet,
                Dune::DynamicMatrix< R >& neighborEntityRet) const
  {
    CHECK_AND_CALL_CRTP(this->as_imp(*this).evaluate(localFunctionsEntity,
                                                     localFunctionsNeighbor,
                                                     testBaseEntity, ansatzBaseEntity,
                                                     testBaseNeighbor, ansatzBaseNeighbor,
                                                     intersection,
                                                     localPoint,
                                                     entityEntityRet, neighborNeighborRet,
                                                     entityNeighborRet, neighborEntityRet));
  }
}; // class Codim1Interface< Traits, 4 >

} // namespace LocalEvaluation
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_EVALUATION_INTERFACE_HH
<commit_msg>[localeval] more as_imp(*this) cleanups<commit_after>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_EVALUATION_INTERFACE_HH
#define DUNE_GDT_EVALUATION_INTERFACE_HH

#include <memory>

#include <dune/stuff/common/disable_warnings.hh>
# include <dune/common/dynmatrix.hh>
# include <dune/common/fvector.hh>
#include <dune/stuff/common/reenable_warnings.hh>

#include <dune/stuff/functions/interfaces.hh>
#include <dune/stuff/common/crtp.hh>

namespace Dune {
namespace GDT {
namespace LocalEvaluation {

/**
 *  \brief  Interface for local evaluations that depend on a codim 0 entity.
 *  \tparam numArguments  The number of local bases.
 *  \note   All evaluations have to be copyable!
 */
template< class Traits, int numArguments >
class Codim0Interface
{
  static_assert(AlwaysFalse< Traits >::value, "There is no interface for this numArguments!");
};

/**
 *  \brief  Interface for unary codim 0 evaluations.
 */
template< class Traits >
class Codim0Interface< Traits, 1 >
  : public Stuff::CRTPInterface< Codim0Interface< Traits, 1 >, Traits >
{
public:
  typedef typename Traits::derived_type           derived_type;
  typedef typename Traits::EntityType             EntityType;
  typedef typename Traits::LocalfunctionTupleType LocalfunctionTupleType;
  typedef typename Traits::DomainFieldType        DomainFieldType;
  static const unsigned int dimDomain = Traits::dimDomain;

  LocalfunctionTupleType localFunctions(const EntityType& entity) const
  {
    CHECK_CRTP(this->as_imp().localFunctions(entity));
    return this->as_imp().localFunctions(entity);
  }

  /**
   *  \brief  Computes the needed integration order.
   *  \tparam R   RangeFieldType
   *  \tparam r   dimRange of the testBase
   *  \tparam rC  dimRangeRows of the testBase
   */
  template< class R, int r, int rC >
  size_t order(const LocalfunctionTupleType& localFunctions,
               const Stuff::LocalfunctionSetInterface
                   < EntityType, DomainFieldType, dimDomain, R, r, rC >& testBase) const
  {
    CHECK_CRTP(this->as_imp().order(localFunctions, testBase));
    return this->as_imp().order(localFunctions, testBase);
  }

  /**
   *  \brief  Computes a unary codim 0 evaluation.
   *  \tparam R   RangeFieldType
   *  \tparam r   dimRange of the testBase
   *  \tparam rC  dimRangeRows of the testBase
   *  \attention ret is assumed to be zero!
   */
  template< class R, int r, int rC >
  void evaluate(const LocalfunctionTupleType& localFunctions,
                const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain, R, r, rC >& testBase,
                const Dune::FieldVector< DomainFieldType, dimDomain >& localPoint,
                Dune::DynamicVector< R >& ret) const
  {
    CHECK_AND_CALL_CRTP(this->as_imp().evaluate(localFunctions, testBase, localPoint, ret));
  }
}; // class Codim0Interface< Traits, 1 >

/**
 *  \brief  Interface for binary codim 0 evaluations.
 **/
template< class Traits >
class Codim0Interface< Traits, 2 >
  : public Stuff::CRTPInterface< Codim0Interface< Traits, 2 >, Traits >
{
public:
  typedef typename Traits::derived_type           derived_type;
  typedef typename Traits::EntityType             EntityType;
  typedef typename Traits::LocalfunctionTupleType LocalfunctionTupleType;
  typedef typename Traits::DomainFieldType        DomainFieldType;
  static const unsigned int dimDomain = Traits::dimDomain;

  /**
   *  \brief  Computes the needed integration order.
   *  \tparam R       RangeFieldType
   *  \tparam r{T,A}  dimRange of the {testBase,ansatzBase}
   *  \tparam rC{T,A} dimRangeRows of the {testBase,ansatzBase}
   */
  template< class R, int rT, int rCT, int rA, int rCA >
  size_t order(const LocalfunctionTupleType& localFunctions,
               const Stuff::LocalfunctionSetInterface
                   < EntityType, DomainFieldType, dimDomain, R, rT, rCT >& testBase,
               const Stuff::LocalfunctionSetInterface
                   < EntityType, DomainFieldType, dimDomain, R, rA, rCA >& ansatzBase) const
  {
    CHECK_CRTP(this->as_imp().order(localFunctions, testBase, ansatzBase));
    return this->as_imp().order(localFunctions, testBase, ansatzBase);
  }

  /**
   *  \brief  Computes a binary codim 0 evaluation.
   *  \tparam R         RangeFieldType
   *  \tparam r{L,T,A}  dimRange of the {localFunction,testBase,ansatzBase}
   *  \tparam rC{L,T,A} dimRangeRows of the {localFunction,testBase,ansatzBase}
   *  \attention ret is assumed to be zero!
   */
  template< class R, int rT, int rCT, int rA, int rCA >
  void evaluate(const LocalfunctionTupleType& localFunctions,
                const Stuff::LocalfunctionSetInterface
                    < EntityType, DomainFieldType, dimDomain, R, rT, rCT >& testBase,
                const Stuff::LocalfunctionSetInterface
                    < EntityType, DomainFieldType, dimDomain, R, rA, rCA >& ansatzBase,
                const Dune::FieldVector< DomainFieldType, dimDomain >& localPoint,
                Dune::DynamicMatrix< R >& ret) const
  {
    CHECK_AND_CALL_CRTP(this->as_imp().evaluate(localFunctions, testBase, ansatzBase, localPoint, ret));
  }
}; // class Codim0Interface< Traits, 2 >

/**
 *  \brief  Interface for local evaluations that depend on an intersection.
 *  \tparam numArguments  The number of local bases.
 *  \note   All evaluations have to be copyable!
 */
template< class Traits, int numArguments >
class Codim1Interface
{
  static_assert(AlwaysFalse< Traits >::value, "There is no interface for this numArguments!");
};

/**
 *  \brief  Interface for unary codim 1 evaluations.
 */
template< class Traits >
class Codim1Interface< Traits, 1 >
    : public Stuff::CRTPInterface< Codim1Interface< Traits, 1 >, Traits >
{
public:
  typedef typename Traits::derived_type           derived_type;
  typedef typename Traits::EntityType             EntityType;
  typedef typename Traits::LocalfunctionTupleType LocalfunctionTupleType;
  typedef typename Traits::DomainFieldType        DomainFieldType;
  static const unsigned int dimDomain = Traits::dimDomain;

  /**
   *  \brief  Computes the needed integration order.
   *  \tparam R   RangeFieldType
   *  \tparam r   dimRange of the testBase
   *  \tparam rC  dimRangeRows of the testBase
   */
  template< class R, int r, int rC >
  size_t order(const LocalfunctionTupleType& localFunctions,
               const Stuff::LocalfunctionSetInterface
                   < EntityType, DomainFieldType, dimDomain, R, r, rC >& testBase) const
  {
    CHECK_CRTP(this->as_imp().order(localFunctions, testBase));
    return this->as_imp().order(localFunctions, testBase);
  }

  /**
   *  \brief  Computes a binary codim 1 evaluation.
   *  \tparam IntersectionType    A model of Dune::Intersection< ... >
   *  \tparam R                   RangeFieldType
   *  \tparam r                   dimRange of the testBase
   *  \tparam rC                  dimRangeRows of the testBase
   *  \attention ret is assumed to be zero!
   */
  template< class IntersectionType, class R, int r, int rC >
  void evaluate(const LocalfunctionTupleType& localFunctions,
                const Stuff::LocalfunctionSetInterface< EntityType, DomainFieldType, dimDomain, R, r, rC >& testBase,
                const IntersectionType& intersection,
                const Dune::FieldVector< DomainFieldType, dimDomain - 1 >& localPoint,
                Dune::DynamicVector< R >& ret) const
  {
    CHECK_AND_CALL_CRTP(this->as_imp().evaluate(localFunctions, testBase, intersection, localPoint, ret));
  }
}; // class Codim1Interface< Traits, 1 >

/**
 *  \brief  Interface for binary codim 1 evaluations.
 */
template< class Traits >
class Codim1Interface< Traits, 2 >
  : public Stuff::CRTPInterface< Codim1Interface< Traits, 2 >, Traits >
{
public:
  typedef typename Traits::derived_type           derived_type;
  typedef typename Traits::EntityType             EntityType;
  typedef typename Traits::LocalfunctionTupleType LocalfunctionTupleType;
  typedef typename Traits::DomainFieldType        DomainFieldType;
  static const unsigned int dimDomain = Traits::dimDomain;

  /**
   *  \brief  Computes the needed integration order.
   *  \tparam R                   RangeFieldType
   *  \tparam r{T,A}              dimRange of the {testBase,ansatzBase}
   *  \tparam rC{T,A}             dimRangeRows of the {testBase,ansatzBase}
   */
  template< class R, int rT, int rCT, int rA, int rCA >
  size_t order(const LocalfunctionTupleType& localFunctions,
               const Stuff::LocalfunctionSetInterface
                   < EntityType, DomainFieldType, dimDomain, R, rT, rCT >& testBase,
               const Stuff::LocalfunctionSetInterface
                   < EntityType, DomainFieldType, dimDomain, R, rA, rCA >& ansatzBase) const
  {
    CHECK_CRTP(this->as_imp().order(localFunctions, testBase, ansatzBase));
    return this->as_imp().order(localFunctions, testBase, ansatzBase);
  }

  /**
   *  \brief  Computes a binary codim 1 evaluation.
   *  \tparam IntersectionType    A model of Dune::Intersection< ... >
   *  \tparam R                   RangeFieldType
   *  \tparam r{T,A}              dimRange of the {testBase*,ansatzBase*}
   *  \tparam rC{T,A}             dimRangeRows of the {testBase*,ansatzBase*}
   *  \attention ret is assumed to be zero!
   */
  template< class IntersectionType, class R, int rT, int rCT, int rA, int rCA >
  void evaluate(const LocalfunctionTupleType& localFunctions,
                const Stuff::LocalfunctionSetInterface
                    < EntityType, DomainFieldType, dimDomain, R, rT, rCT >& testBase,
                const Stuff::LocalfunctionSetInterface
                    < EntityType, DomainFieldType, dimDomain, R, rA, rCA >& ansatzBase,
                const IntersectionType& intersection,
                const Dune::FieldVector< DomainFieldType, dimDomain - 1 >& localPoint,
                Dune::DynamicMatrix< R >& ret) const
  {
    CHECK_AND_CALL_CRTP(this->as_imp().evaluate(localFunctions, testBase, ansatzBase, intersection, localPoint,
                                                     ret));
  }
}; // class Codim1Interface< Traits, 2 >

/**
 *  \brief  Interface for quaternary codim 1 evaluations.
 */
template< class Traits >
class Codim1Interface< Traits, 4 >
  : public Stuff::CRTPInterface< Codim1Interface< Traits, 4 >, Traits >
{
public:
  typedef typename Traits::derived_type           derived_type;
  typedef typename Traits::EntityType             EntityType;
  typedef typename Traits::LocalfunctionTupleType LocalfunctionTupleType;
  typedef typename Traits::DomainFieldType        DomainFieldType;
  static const unsigned int dimDomain = Traits::dimDomain;

  /**
   *  \brief  Computes the needed integration order.
   *  \tparam R                     RangeFieldType
   *  \tparam r{T,A}                dimRange of the {testBase*,ansatzBase*}
   *  \tparam rC{T,A}               dimRangeRows of the {testBase*,ansatzBase*}
   */
  template< class R, int rT, int rCT, int rA, int rCA >
  size_t order(const LocalfunctionTupleType localFunctionsEntity,
               const LocalfunctionTupleType localFunctionsNeighbor,
               const Stuff::LocalfunctionSetInterface
                   < EntityType, DomainFieldType, dimDomain, R, rT, rCT >& testBaseEntity,
               const Stuff::LocalfunctionSetInterface
                   < EntityType, DomainFieldType, dimDomain, R, rA, rCA >& ansatzBaseEntity,
               const Stuff::LocalfunctionSetInterface
                   < EntityType, DomainFieldType, dimDomain, R, rT, rCT >& testBaseNeighbor,
               const Stuff::LocalfunctionSetInterface
                   < EntityType, DomainFieldType, dimDomain, R, rA, rCA >& ansatzBaseNeighbor) const
  {
    CHECK_CRTP(this->as_imp().order(localFunctionsEntity, localFunctionsNeighbor,
                                         testBaseEntity, ansatzBaseEntity,
                                         testBaseNeighbor, ansatzBaseNeighbor));
    return this->as_imp().order(localFunctionsEntity, localFunctionsNeighbor,
                                     testBaseEntity, ansatzBaseEntity,
                                     testBaseNeighbor, ansatzBaseNeighbor);
  }

  /**
   *  \brief  Computes a quaternary codim 1 evaluation.
   *  \tparam IntersectionType      A model of Dune::Intersection< ... >
   *  \tparam R                     RangeFieldType
   *  \tparam r{T,A}                dimRange of the {testBase*,ansatzBase*}
   *  \tparam rC{T,A}               dimRangeRows of the {testBase*,ansatzBase*}
   *  \attention entityEntityRet, entityEntityRet, entityEntityRet and neighborEntityRet are assumed to be zero!
   */
  template< class IntersectionType, class R, int rT, int rCT, int rA, int rCA >
  void evaluate(const LocalfunctionTupleType& localFunctionsEntity,
                const LocalfunctionTupleType& localFunctionsNeighbor,
                const Stuff::LocalfunctionSetInterface
                    < EntityType, DomainFieldType, dimDomain, R, rT, rCT >& testBaseEntity,
                const Stuff::LocalfunctionSetInterface
                    < EntityType, DomainFieldType, dimDomain, R, rA, rCA >& ansatzBaseEntity,
                const Stuff::LocalfunctionSetInterface
                    < EntityType, DomainFieldType, dimDomain, R, rT, rCT >& testBaseNeighbor,
                const Stuff::LocalfunctionSetInterface
                    < EntityType, DomainFieldType, dimDomain, R, rA, rCA >& ansatzBaseNeighbor,
                const IntersectionType& intersection,
                const Dune::FieldVector< DomainFieldType, dimDomain - 1 >& localPoint,
                Dune::DynamicMatrix< R >& entityEntityRet,
                Dune::DynamicMatrix< R >& neighborNeighborRet,
                Dune::DynamicMatrix< R >& entityNeighborRet,
                Dune::DynamicMatrix< R >& neighborEntityRet) const
  {
    CHECK_AND_CALL_CRTP(this->as_imp().evaluate(localFunctionsEntity,
                                                     localFunctionsNeighbor,
                                                     testBaseEntity, ansatzBaseEntity,
                                                     testBaseNeighbor, ansatzBaseNeighbor,
                                                     intersection,
                                                     localPoint,
                                                     entityEntityRet, neighborNeighborRet,
                                                     entityNeighborRet, neighborEntityRet));
  }
}; // class Codim1Interface< Traits, 4 >

} // namespace LocalEvaluation
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_EVALUATION_INTERFACE_HH
<|endoftext|>