<commit_before>/***************************************************************************
 *   Copyright (C) 1998-2010 by authors (see AUTHORS.txt )                 *
 *                                                                         *
 *   This file is part of LuxRays.                                         *
 *                                                                         *
 *   LuxRays is free software; you can redistribute it and/or modify       *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 3 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   LuxRays is distributed in the hope that it will be useful,            *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
 *                                                                         *
 *   LuxRays website: http://www.luxrender.net                             *
 ***************************************************************************/

#if !defined(LUXRAYS_DISABLE_OPENCL)

#include <cstdio>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <iomanip>
#include <string.h>
#include <string>
#include <sstream>
#include <stdexcept>

#include <boost/thread/mutex.hpp>

#include "smalllux.h"

#include "pathocl/pathocl.h"
#include "pathocl/kernels/kernels.h"
#include "renderconfig.h"
#include "luxrays/core/geometry/transform.h"
#include "luxrays/accelerators/mqbvhaccel.h"
#include "luxrays/accelerators/bvhaccel.h"
#include "luxrays/opencl/intersectiondevice.h"

//------------------------------------------------------------------------------
// PathOCLRenderEngine
//------------------------------------------------------------------------------

PathOCLRenderEngine::PathOCLRenderEngine(RenderConfig *rcfg, Film *flm, boost::mutex *flmMutex) :
		OCLRenderEngine(rcfg, flm, flmMutex) {
	const Properties &cfg = renderConfig->cfg;
	compiledScene = NULL;

	//--------------------------------------------------------------------------
	// Allocate devices
	//--------------------------------------------------------------------------

	std::vector<IntersectionDevice *> devs = ctx->AddIntersectionDevices(selectedDeviceDescs);

	// Check if I have to disable image storage and set max. QBVH stack size
	const bool forcedDisableImageStorage = (renderConfig->scene->GetAccelType() == 2);
	const size_t qbvhStackSize = cfg.GetInt("accelerator.qbvh.stacksize.max", 24);
	SLG_LOG("OpenCL Devices used:");
	for (size_t i = 0; i < devs.size(); ++i) {
		SLG_LOG("[" << devs[i]->GetName() << "]");
		devs[i]->SetMaxStackSize(qbvhStackSize);
		intersectionDevices.push_back(devs[i]);

		OpenCLIntersectionDevice *oclIntersectionDevice = (OpenCLIntersectionDevice *)(devs[i]);
		oclIntersectionDevice->DisableImageStorage(forcedDisableImageStorage);
		// Disable the support for hybrid rendering
		oclIntersectionDevice->SetDataParallelSupport(false);
	}

	// Set the LuxRays SataSet
	ctx->SetDataSet(renderConfig->scene->dataSet);

	//--------------------------------------------------------------------------
	// Rendering parameters
	//--------------------------------------------------------------------------

	taskCount = RoundUpPow2(cfg.GetInt("opencl.task.count", 65536));
	SLG_LOG("[PathOCLRenderThread] OpenCL task count: " << taskCount);

	if (cfg.IsDefined("opencl.memory.maxpagesize"))
		maxMemPageSize = cfg.GetSize("opencl.memory.maxpagesize", 512 * 1024 * 1024);
	else {
		// Look for the max. page size allowed
		maxMemPageSize = ((OpenCLIntersectionDevice *)(intersectionDevices[0]))->GetDeviceDesc()->GetMaxMemoryAllocSize();
		for (u_int i = 1; i < intersectionDevices.size(); ++i)
			maxMemPageSize = Min(maxMemPageSize, ((OpenCLIntersectionDevice *)(intersectionDevices[i]))->GetDeviceDesc()->GetMaxMemoryAllocSize());
	}
	SLG_LOG("[PathOCLRenderThread] OpenCL max. page memory size: " << maxMemPageSize / 1024 << "Kbytes");

	maxPathDepth = cfg.GetInt("path.maxdepth", 5);
	maxDiffusePathVertexCount = cfg.GetInt("path.maxdiffusebounce", 5);
	rrDepth = cfg.GetInt("path.russianroulette.depth", 3);
	rrImportanceCap = cfg.GetFloat("path.russianroulette.cap", 0.125f);
	epsilon = cfg.GetFloat("scene.epsilon", .0001f);

	//--------------------------------------------------------------------------
	// Sampler
	//--------------------------------------------------------------------------

	const string samplerTypeName = cfg.GetString("path.sampler.type", "INLINED_RANDOM");
	if (samplerTypeName.compare("INLINED_RANDOM") == 0)
		sampler = new PathOCL::InlinedRandomSampler();
	else if (samplerTypeName.compare("RANDOM") == 0)
		sampler = new PathOCL::RandomSampler();
	else if (samplerTypeName.compare("STRATIFIED") == 0) {
		const unsigned int xSamples = cfg.GetInt("path.sampler.xsamples", 3);
		const unsigned int ySamples = cfg.GetInt("path.sampler.ysamples", 3);

		sampler = new PathOCL::StratifiedSampler(xSamples, ySamples);
	} else if (samplerTypeName.compare("METROPOLIS") == 0) {
		const float rate = cfg.GetFloat("path.sampler.largesteprate", .4f);
		const float reject = cfg.GetFloat("path.sampler.maxconsecutivereject", 512);
		const float mutationrate = cfg.GetFloat("path.sampler.imagemutationrate", .1f);

		sampler = new PathOCL::MetropolisSampler(rate, reject, mutationrate);
	} else
		throw std::runtime_error("Unknown path.sampler.type");

	//--------------------------------------------------------------------------
	// Filter
	//--------------------------------------------------------------------------

	const string filterType = cfg.GetString("path.filter.type", "NONE");
	const float filterWidthX = cfg.GetFloat("path.filter.width.x", 1.5f);
	const float filterWidthY = cfg.GetFloat("path.filter.width.y", 1.5f);
	if ((filterWidthX <= 0.f) || (filterWidthX > 1.5f))
		throw std::runtime_error("path.filter.width.x must be between 0.0 and 1.5");
	if ((filterWidthY <= 0.f) || (filterWidthY > 1.5f))
		throw std::runtime_error("path.filter.width.y must be between 0.0 and 1.5");

	if (filterType.compare("NONE") == 0)
		filter = new PathOCL::NoneFilter();
	else if (filterType.compare("BOX") == 0)
		filter = new PathOCL::BoxFilter(filterWidthX, filterWidthY);
	else if (filterType.compare("GAUSSIAN") == 0) {
		const float alpha = cfg.GetFloat("path.filter.alpha", 2.f);
		filter = new PathOCL::GaussianFilter(filterWidthX, filterWidthY, alpha);
	} else if (filterType.compare("MITCHELL") == 0) {
		const float B = cfg.GetFloat("path.filter.B", 1.f / 3.f);
		const float C = cfg.GetFloat("path.filter.C", 1.f / 3.f);
		filter = new PathOCL::MitchellFilter(filterWidthX, filterWidthY, B, C);
	} else
		throw std::runtime_error("Unknown path.filter.type");

	usePixelAtomics = (cfg.GetInt("path.pixelatomics.enable", 0) != 0);

	const unsigned int seedBase = (unsigned int)(WallClockTime() / 1000.0);

	film->EnableOverlappedScreenBufferUpdate(true);

	//--------------------------------------------------------------------------
	// Create and start render threads
	//--------------------------------------------------------------------------

	const size_t renderThreadCount = intersectionDevices.size();
	SLG_LOG("Starting "<< renderThreadCount << " PathOCL render threads");
	for (size_t i = 0; i < renderThreadCount; ++i) {
		PathOCLRenderThread *t = new PathOCLRenderThread(i,
			seedBase + i * taskCount, i / (float)renderThreadCount,
			(OpenCLIntersectionDevice *)(intersectionDevices[i]),
			this);
		renderThreads.push_back(t);
	}
}

PathOCLRenderEngine::~PathOCLRenderEngine() {
	if (editMode)
		EndEdit(EditActionList());
	if (started)
		Stop();

	for (size_t i = 0; i < renderThreads.size(); ++i)
		delete renderThreads[i];

	delete sampler;
	delete filter;
}

void PathOCLRenderEngine::StartLockLess() {
	compiledScene = new CompiledScene(renderConfig->scene, film, maxMemPageSize);

	for (size_t i = 0; i < renderThreads.size(); ++i)
		renderThreads[i]->Start();
}

void PathOCLRenderEngine::StopLockLess() {
	for (size_t i = 0; i < renderThreads.size(); ++i)
		renderThreads[i]->Interrupt();
	for (size_t i = 0; i < renderThreads.size(); ++i)
		renderThreads[i]->Stop();

	delete compiledScene;
	compiledScene = NULL;
}

void PathOCLRenderEngine::BeginEditLockLess() {
	for (size_t i = 0; i < renderThreads.size(); ++i)
		renderThreads[i]->Interrupt();
	for (size_t i = 0; i < renderThreads.size(); ++i)
		renderThreads[i]->BeginEdit();
}

void PathOCLRenderEngine::EndEditLockLess(const EditActionList &editActions) {
	compiledScene->Recompile(editActions);

	for (size_t i = 0; i < renderThreads.size(); ++i)
		renderThreads[i]->EndEdit(editActions);
}

void PathOCLRenderEngine::UpdateFilmLockLess() {
	boost::unique_lock<boost::mutex> lock(*filmMutex);

	const unsigned int imgWidth = film->GetWidth();
	const unsigned int imgHeight = film->GetHeight();

	film->Reset();

	const bool isAlphaChannelEnabled = film->IsAlphaChannelEnabled();

	switch (film->GetFilterType()) {
		case FILTER_GAUSSIAN: {
			for (unsigned int y = 0; y < imgHeight; ++y) {
				unsigned int pGPU = 1 + (y + 1) * (imgWidth + 2);

				for (unsigned int x = 0; x < imgWidth; ++x) {
					Spectrum c;
					float alpha = 0.0f;
					float count = 0.f;
					for (size_t i = 0; i < renderThreads.size(); ++i) {
						if (renderThreads[i]->frameBuffer) {
							c += renderThreads[i]->frameBuffer[pGPU].c;
							count += renderThreads[i]->frameBuffer[pGPU].count;
						}

						if (renderThreads[i]->alphaFrameBuffer)
							alpha += renderThreads[i]->alphaFrameBuffer[pGPU].alpha;
					}

					if ((count > 0) && !c.IsNaN()) {
						c /= count;
						film->AddSampleCount(1.f);
						// -.5f is to align correctly the pixel after the splat
						film->SplatFiltered(PER_PIXEL_NORMALIZED, x - .5f, y - .5f, c);

						if (isAlphaChannelEnabled && !isnan(alpha))
							film->SplatFilteredAlpha(x - .5f, y - .5f, alpha / count);
					}

					++pGPU;
				}
			}
			break;
		}
		case FILTER_NONE: {
			for (unsigned int y = 0; y < imgHeight; ++y) {
				unsigned int pGPU = 1 + (y + 1) * (imgWidth + 2);

				for (unsigned int x = 0; x < imgWidth; ++x) {
					Spectrum c;
					float alpha = 0.0f;
					float count = 0.f;
					for (size_t i = 0; i < renderThreads.size(); ++i) {
						if (renderThreads[i]->frameBuffer) {
							c += renderThreads[i]->frameBuffer[pGPU].c;
							count += renderThreads[i]->frameBuffer[pGPU].count;
						}

						if (renderThreads[i]->alphaFrameBuffer)
							alpha += renderThreads[i]->alphaFrameBuffer[pGPU].alpha;
					}

					if ((count > 0) && !c.IsNaN()) {
						film->AddSampleCount(1.f);
						film->AddRadiance(PER_PIXEL_NORMALIZED, x, y, c / count, count);

						if (isAlphaChannelEnabled && !isnan(alpha))
							film->AddAlpha(x, y, alpha / count, 1.f);
					}

					++pGPU;
				}
			}
			break;
		}
		default:
			assert (false);
			break;
	}
}

void PathOCLRenderEngine::UpdateCounters() {
	// Update the sample count statistic
	unsigned long long totalCount = 0;
	for (size_t i = 0; i < renderThreads.size(); ++i) {
		PathOCL::GPUTaskStats *stats = renderThreads[i]->gpuTaskStats;

		for (size_t i = 0; i < taskCount; ++i)
			totalCount += stats[i].sampleCount;
	}

	samplesCount = totalCount;

	// Update the ray count statistic
	totalCount = 0.0;
	for (size_t i = 0; i < intersectionDevices.size(); ++i)
		totalCount += intersectionDevices[i]->GetTotalRaysCount();
	raysCount = totalCount;
}

#endif
<commit_msg>PathOCL: sampler.* parameters are now accepted too<commit_after>/***************************************************************************
 *   Copyright (C) 1998-2010 by authors (see AUTHORS.txt )                 *
 *                                                                         *
 *   This file is part of LuxRays.                                         *
 *                                                                         *
 *   LuxRays is free software; you can redistribute it and/or modify       *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 3 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   LuxRays is distributed in the hope that it will be useful,            *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
 *                                                                         *
 *   LuxRays website: http://www.luxrender.net                             *
 ***************************************************************************/

#if !defined(LUXRAYS_DISABLE_OPENCL)

#include <cstdio>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <iomanip>
#include <string.h>
#include <string>
#include <sstream>
#include <stdexcept>

#include <boost/thread/mutex.hpp>

#include "smalllux.h"

#include "pathocl/pathocl.h"
#include "pathocl/kernels/kernels.h"
#include "renderconfig.h"
#include "luxrays/core/geometry/transform.h"
#include "luxrays/accelerators/mqbvhaccel.h"
#include "luxrays/accelerators/bvhaccel.h"
#include "luxrays/opencl/intersectiondevice.h"

//------------------------------------------------------------------------------
// PathOCLRenderEngine
//------------------------------------------------------------------------------

PathOCLRenderEngine::PathOCLRenderEngine(RenderConfig *rcfg, Film *flm, boost::mutex *flmMutex) :
		OCLRenderEngine(rcfg, flm, flmMutex) {
	const Properties &cfg = renderConfig->cfg;
	compiledScene = NULL;

	//--------------------------------------------------------------------------
	// Allocate devices
	//--------------------------------------------------------------------------

	std::vector<IntersectionDevice *> devs = ctx->AddIntersectionDevices(selectedDeviceDescs);

	// Check if I have to disable image storage and set max. QBVH stack size
	const bool forcedDisableImageStorage = (renderConfig->scene->GetAccelType() == 2);
	const size_t qbvhStackSize = cfg.GetInt("accelerator.qbvh.stacksize.max", 24);
	SLG_LOG("OpenCL Devices used:");
	for (size_t i = 0; i < devs.size(); ++i) {
		SLG_LOG("[" << devs[i]->GetName() << "]");
		devs[i]->SetMaxStackSize(qbvhStackSize);
		intersectionDevices.push_back(devs[i]);

		OpenCLIntersectionDevice *oclIntersectionDevice = (OpenCLIntersectionDevice *)(devs[i]);
		oclIntersectionDevice->DisableImageStorage(forcedDisableImageStorage);
		// Disable the support for hybrid rendering
		oclIntersectionDevice->SetDataParallelSupport(false);
	}

	// Set the LuxRays SataSet
	ctx->SetDataSet(renderConfig->scene->dataSet);

	//--------------------------------------------------------------------------
	// Rendering parameters
	//--------------------------------------------------------------------------

	taskCount = RoundUpPow2(cfg.GetInt("opencl.task.count", 65536));
	SLG_LOG("[PathOCLRenderThread] OpenCL task count: " << taskCount);

	if (cfg.IsDefined("opencl.memory.maxpagesize"))
		maxMemPageSize = cfg.GetSize("opencl.memory.maxpagesize", 512 * 1024 * 1024);
	else {
		// Look for the max. page size allowed
		maxMemPageSize = ((OpenCLIntersectionDevice *)(intersectionDevices[0]))->GetDeviceDesc()->GetMaxMemoryAllocSize();
		for (u_int i = 1; i < intersectionDevices.size(); ++i)
			maxMemPageSize = Min(maxMemPageSize, ((OpenCLIntersectionDevice *)(intersectionDevices[i]))->GetDeviceDesc()->GetMaxMemoryAllocSize());
	}
	SLG_LOG("[PathOCLRenderThread] OpenCL max. page memory size: " << maxMemPageSize / 1024 << "Kbytes");

	maxPathDepth = cfg.GetInt("path.maxdepth", 5);
	maxDiffusePathVertexCount = cfg.GetInt("path.maxdiffusebounce", 5);
	rrDepth = cfg.GetInt("path.russianroulette.depth", 3);
	rrImportanceCap = cfg.GetFloat("path.russianroulette.cap", 0.125f);
	epsilon = cfg.GetFloat("scene.epsilon", .0001f);

	//--------------------------------------------------------------------------
	// Sampler
	//--------------------------------------------------------------------------

	const string samplerTypeName = cfg.GetString("sampler.type",
			cfg.GetString("path.sampler.type", "INLINED_RANDOM"));
	if (samplerTypeName.compare("INLINED_RANDOM") == 0)
		sampler = new PathOCL::InlinedRandomSampler();
	else if (samplerTypeName.compare("RANDOM") == 0)
		sampler = new PathOCL::RandomSampler();
	else if (samplerTypeName.compare("STRATIFIED") == 0) {
		const unsigned int xSamples = cfg.GetInt("path.sampler.xsamples", 3);
		const unsigned int ySamples = cfg.GetInt("path.sampler.ysamples", 3);

		sampler = new PathOCL::StratifiedSampler(xSamples, ySamples);
	} else if (samplerTypeName.compare("METROPOLIS") == 0) {
		const float rate = cfg.GetFloat("sampler.largesteprate",
				cfg.GetFloat("path.sampler.largesteprate", .4f));
		const float reject = cfg.GetFloat("sampler.maxconsecutivereject",
				cfg.GetFloat("path.sampler.maxconsecutivereject", 512));
		const float mutationrate = cfg.GetFloat("sampler.imagemutationrate",
				cfg.GetFloat("path.sampler.imagemutationrate", .1f));

		sampler = new PathOCL::MetropolisSampler(rate, reject, mutationrate);
	} else
		throw std::runtime_error("Unknown path.sampler.type");

	//--------------------------------------------------------------------------
	// Filter
	//--------------------------------------------------------------------------

	const string filterType = cfg.GetString("path.filter.type", "NONE");
	const float filterWidthX = cfg.GetFloat("path.filter.width.x", 1.5f);
	const float filterWidthY = cfg.GetFloat("path.filter.width.y", 1.5f);
	if ((filterWidthX <= 0.f) || (filterWidthX > 1.5f))
		throw std::runtime_error("path.filter.width.x must be between 0.0 and 1.5");
	if ((filterWidthY <= 0.f) || (filterWidthY > 1.5f))
		throw std::runtime_error("path.filter.width.y must be between 0.0 and 1.5");

	if (filterType.compare("NONE") == 0)
		filter = new PathOCL::NoneFilter();
	else if (filterType.compare("BOX") == 0)
		filter = new PathOCL::BoxFilter(filterWidthX, filterWidthY);
	else if (filterType.compare("GAUSSIAN") == 0) {
		const float alpha = cfg.GetFloat("path.filter.alpha", 2.f);
		filter = new PathOCL::GaussianFilter(filterWidthX, filterWidthY, alpha);
	} else if (filterType.compare("MITCHELL") == 0) {
		const float B = cfg.GetFloat("path.filter.B", 1.f / 3.f);
		const float C = cfg.GetFloat("path.filter.C", 1.f / 3.f);
		filter = new PathOCL::MitchellFilter(filterWidthX, filterWidthY, B, C);
	} else
		throw std::runtime_error("Unknown path.filter.type");

	usePixelAtomics = (cfg.GetInt("path.pixelatomics.enable", 0) != 0);

	const unsigned int seedBase = (unsigned int)(WallClockTime() / 1000.0);

	film->EnableOverlappedScreenBufferUpdate(true);

	//--------------------------------------------------------------------------
	// Create and start render threads
	//--------------------------------------------------------------------------

	const size_t renderThreadCount = intersectionDevices.size();
	SLG_LOG("Starting "<< renderThreadCount << " PathOCL render threads");
	for (size_t i = 0; i < renderThreadCount; ++i) {
		PathOCLRenderThread *t = new PathOCLRenderThread(i,
			seedBase + i * taskCount, i / (float)renderThreadCount,
			(OpenCLIntersectionDevice *)(intersectionDevices[i]),
			this);
		renderThreads.push_back(t);
	}
}

PathOCLRenderEngine::~PathOCLRenderEngine() {
	if (editMode)
		EndEdit(EditActionList());
	if (started)
		Stop();

	for (size_t i = 0; i < renderThreads.size(); ++i)
		delete renderThreads[i];

	delete sampler;
	delete filter;
}

void PathOCLRenderEngine::StartLockLess() {
	compiledScene = new CompiledScene(renderConfig->scene, film, maxMemPageSize);

	for (size_t i = 0; i < renderThreads.size(); ++i)
		renderThreads[i]->Start();
}

void PathOCLRenderEngine::StopLockLess() {
	for (size_t i = 0; i < renderThreads.size(); ++i)
		renderThreads[i]->Interrupt();
	for (size_t i = 0; i < renderThreads.size(); ++i)
		renderThreads[i]->Stop();

	delete compiledScene;
	compiledScene = NULL;
}

void PathOCLRenderEngine::BeginEditLockLess() {
	for (size_t i = 0; i < renderThreads.size(); ++i)
		renderThreads[i]->Interrupt();
	for (size_t i = 0; i < renderThreads.size(); ++i)
		renderThreads[i]->BeginEdit();
}

void PathOCLRenderEngine::EndEditLockLess(const EditActionList &editActions) {
	compiledScene->Recompile(editActions);

	for (size_t i = 0; i < renderThreads.size(); ++i)
		renderThreads[i]->EndEdit(editActions);
}

void PathOCLRenderEngine::UpdateFilmLockLess() {
	boost::unique_lock<boost::mutex> lock(*filmMutex);

	const unsigned int imgWidth = film->GetWidth();
	const unsigned int imgHeight = film->GetHeight();

	film->Reset();

	const bool isAlphaChannelEnabled = film->IsAlphaChannelEnabled();

	switch (film->GetFilterType()) {
		case FILTER_GAUSSIAN: {
			for (unsigned int y = 0; y < imgHeight; ++y) {
				unsigned int pGPU = 1 + (y + 1) * (imgWidth + 2);

				for (unsigned int x = 0; x < imgWidth; ++x) {
					Spectrum c;
					float alpha = 0.0f;
					float count = 0.f;
					for (size_t i = 0; i < renderThreads.size(); ++i) {
						if (renderThreads[i]->frameBuffer) {
							c += renderThreads[i]->frameBuffer[pGPU].c;
							count += renderThreads[i]->frameBuffer[pGPU].count;
						}

						if (renderThreads[i]->alphaFrameBuffer)
							alpha += renderThreads[i]->alphaFrameBuffer[pGPU].alpha;
					}

					if ((count > 0) && !c.IsNaN()) {
						c /= count;
						film->AddSampleCount(1.f);
						// -.5f is to align correctly the pixel after the splat
						film->SplatFiltered(PER_PIXEL_NORMALIZED, x - .5f, y - .5f, c);

						if (isAlphaChannelEnabled && !isnan(alpha))
							film->SplatFilteredAlpha(x - .5f, y - .5f, alpha / count);
					}

					++pGPU;
				}
			}
			break;
		}
		case FILTER_NONE: {
			for (unsigned int y = 0; y < imgHeight; ++y) {
				unsigned int pGPU = 1 + (y + 1) * (imgWidth + 2);

				for (unsigned int x = 0; x < imgWidth; ++x) {
					Spectrum c;
					float alpha = 0.0f;
					float count = 0.f;
					for (size_t i = 0; i < renderThreads.size(); ++i) {
						if (renderThreads[i]->frameBuffer) {
							c += renderThreads[i]->frameBuffer[pGPU].c;
							count += renderThreads[i]->frameBuffer[pGPU].count;
						}

						if (renderThreads[i]->alphaFrameBuffer)
							alpha += renderThreads[i]->alphaFrameBuffer[pGPU].alpha;
					}

					if ((count > 0) && !c.IsNaN()) {
						film->AddSampleCount(1.f);
						film->AddRadiance(PER_PIXEL_NORMALIZED, x, y, c / count, count);

						if (isAlphaChannelEnabled && !isnan(alpha))
							film->AddAlpha(x, y, alpha / count, 1.f);
					}

					++pGPU;
				}
			}
			break;
		}
		default:
			assert (false);
			break;
	}
}

void PathOCLRenderEngine::UpdateCounters() {
	// Update the sample count statistic
	unsigned long long totalCount = 0;
	for (size_t i = 0; i < renderThreads.size(); ++i) {
		PathOCL::GPUTaskStats *stats = renderThreads[i]->gpuTaskStats;

		for (size_t i = 0; i < taskCount; ++i)
			totalCount += stats[i].sampleCount;
	}

	samplesCount = totalCount;

	// Update the ray count statistic
	totalCount = 0.0;
	for (size_t i = 0; i < intersectionDevices.size(); ++i)
		totalCount += intersectionDevices[i]->GetTotalRaysCount();
	raysCount = totalCount;
}

#endif
<|endoftext|>


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

#ifndef DUNE_GDT_ASSEMLBER_LOCAL_CODIM0_HH
#define DUNE_GDT_ASSEMLBER_LOCAL_CODIM0_HH

#include <vector>

#include <dune/common/dynmatrix.hh>
#include <dune/common/dynvector.hh>

#include <dune/stuff/common/matrix.hh>
#include <dune/stuff/la/container/interfaces.hh>

#include <dune/gdt/localoperator/interface.hh>
#include <dune/gdt/localfunctional/interface.hh>
#include <dune/gdt/space/interface.hh>

namespace Dune {
namespace GDT {
namespace LocalAssembler {

// forward, to be used in the traits
template <class LocalOperatorImp>
class Codim0Matrix;

template <class LocalOperatorImp>
class Codim0MatrixTraits
{
public:
  typedef Codim0Matrix<LocalOperatorImp> derived_type;
  typedef LocalOperator::Codim0Interface<typename LocalOperatorImp::Traits> LocalOperatorType;
}; // class LocalAssemblerCodim0MatrixTraits

template <class LocalOperatorImp>
class Codim0Matrix
{
public:
  typedef Codim0MatrixTraits<LocalOperatorImp> Traits;
  typedef typename Traits::LocalOperatorType LocalOperatorType;

  Codim0Matrix(const LocalOperatorType& op)
    : localOperator_(op)
  {
  }

  const LocalOperatorType& localOperator() const
  {
    return localOperator_;
  }

private:
  static const size_t numTmpObjectsRequired_ = 1;

public:
  std::vector<size_t> numTmpObjectsRequired() const
  {
    return {numTmpObjectsRequired_, localOperator_.numTmpObjectsRequired()};
  }

  /**
   *  \tparam T           Traits of the SpaceInterface implementation, representing the type of testSpace
   *  \tparam A           Traits of the SpaceInterface implementation, representing the type of ansatzSpace
   *  \tparam EntityType  A model of Dune::Entity< 0 >
   *  \tparam M           Traits of the Dune::Stuff::LA::Container::MatrixInterface implementation, representing the
   * type of systemMatrix
   *  \tparam R           RangeFieldType, i.e. double
   */
  template <class T, class A, class EntityType, class M, class R>
  void assembleLocal(const SpaceInterface<T>& testSpace, const SpaceInterface<A>& ansatzSpace, const EntityType& entity,
                     Dune::Stuff::LA::MatrixInterface<M>& systemMatrix,
                     std::vector<std::vector<Dune::DynamicMatrix<R>>>& tmpLocalMatricesContainer,
                     std::vector<Dune::DynamicVector<size_t>>& tmpIndicesContainer) const
  {
    // check
    assert(tmpLocalMatricesContainer.size() >= 1);
    assert(tmpLocalMatricesContainer[0].size() >= numTmpObjectsRequired_);
    assert(tmpLocalMatricesContainer[1].size() >= localOperator_.numTmpObjectsRequired());
    assert(tmpIndicesContainer.size() >= 2);
    // get and clear matrix
    Dune::DynamicMatrix<R>& localMatrix = tmpLocalMatricesContainer[0][0];
    Dune::Stuff::Common::clear(localMatrix);
    auto& tmpOperatorMatrices = tmpLocalMatricesContainer[1];
    // apply local operator (result is in localMatrix)
    localOperator_.apply(
        testSpace.base_function_set(entity), ansatzSpace.base_function_set(entity), localMatrix, tmpOperatorMatrices);
    // write local matrix to global
    Dune::DynamicVector<size_t>& globalRows = tmpIndicesContainer[0];
    Dune::DynamicVector<size_t>& globalCols = tmpIndicesContainer[1];
    const size_t rows                       = testSpace.mapper().numDofs(entity);
    const size_t cols = ansatzSpace.mapper().numDofs(entity);
    assert(globalRows.size() >= rows);
    assert(globalCols.size() >= cols);
    testSpace.mapper().globalIndices(entity, globalRows);
    ansatzSpace.mapper().globalIndices(entity, globalCols);
    for (size_t ii = 0; ii < rows; ++ii) {
      const auto& localRow  = localMatrix[ii];
      const size_t globalII = globalRows[ii];
      for (size_t jj = 0; jj < cols; ++jj) {
        const size_t globalJJ = globalCols[jj];
        systemMatrix.add_to_entry(globalII, globalJJ, localRow[jj]);
      }
    } // write local matrix to global
  } // ... assembleLocal(...)

private:
  const LocalOperatorType& localOperator_;
}; // class LocalAssemblerCodim0Matrix

// forward, to be used in the traits
template <class LocalOperatorImp>
class Codim0Vector;

template <class LocalFunctionalImp>
class Codim0VectorTraits
{
public:
  typedef Codim0Vector<LocalFunctionalImp> derived_type;
  typedef LocalFunctional::Codim0Interface<typename LocalFunctionalImp::Traits> LocalFunctionalType;
}; // class LocalAssemblerCodim0MatrixTraits

template <class LocalFunctionalImp>
class Codim0Vector
{
public:
  typedef Codim0VectorTraits<LocalFunctionalImp> Traits;
  typedef typename Traits::LocalFunctionalType LocalFunctionalType;

  Codim0Vector(const LocalFunctionalType& func)
    : localFunctional_(func)
  {
  }

  const LocalFunctionalType& localFunctional() const
  {
    return localFunctional_;
  }

private:
  static const size_t numTmpObjectsRequired_ = 1;

public:
  std::vector<size_t> numTmpObjectsRequired() const
  {
    return {numTmpObjectsRequired_, localFunctional_.numTmpObjectsRequired()};
  }

  /**
   *  \tparam T           Traits of the SpaceInterface implementation, representing the type of testSpace
   *  \tparam EntityType  A model of Dune::Entity< 0 >
   *  \tparam V           Traits of the Dune::Stuff::LA::Container::VectorInterface implementation, representing the
   * type of systemVector
   *  \tparam R           RangeFieldType, i.e. double
   */
  template <class T, class EntityType, class V, class R>
  void assembleLocal(const SpaceInterface<T>& testSpace, const EntityType& entity,
                     Dune::Stuff::LA::VectorInterface<V>& systemVector,
                     std::vector<std::vector<Dune::DynamicVector<R>>>& tmpLocalVectorContainer,
                     Dune::DynamicVector<size_t>& tmpIndices) const
  {
    // check
    assert(tmpLocalVectorContainer.size() >= 1);
    assert(tmpLocalVectorContainer[0].size() >= numTmpObjectsRequired_);
    assert(tmpLocalVectorContainer[1].size() >= localFunctional_.numTmpObjectsRequired());
    // get and clear vector
    auto& localVector = tmpLocalVectorContainer[0][0];
    Dune::Stuff::Common::clear(localVector);
    auto& tmpFunctionalVectors = tmpLocalVectorContainer[1];
    // apply local functional (result is in localVector)
    localFunctional_.apply(testSpace.base_function_set(entity), localVector, tmpFunctionalVectors);
    // write local vector to global
    const size_t size = testSpace.mapper().numDofs(entity);
    assert(tmpIndices.size() >= size);
    testSpace.mapper().globalIndices(entity, tmpIndices);
    for (size_t ii = 0; ii < size; ++ii) {
      systemVector.add_to_entry(tmpIndices[ii], localVector[ii]);
    } // write local matrix to global
  } // ... assembleLocal(...)

private:
  const LocalFunctionalType& localFunctional_;
}; // class Codim0Vector

} // namespace LocalAssembler
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_ASSEMLBER_LOCAL_CODIM0_HH
<commit_msg>[assembler.local.codim0] minor fix<commit_after>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Albrecht
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_ASSEMLBER_LOCAL_CODIM0_HH
#define DUNE_GDT_ASSEMLBER_LOCAL_CODIM0_HH

#include <vector>

#include <dune/common/dynmatrix.hh>
#include <dune/common/dynvector.hh>

#include <dune/stuff/common/matrix.hh>
#include <dune/stuff/la/container/interfaces.hh>

#include <dune/gdt/localoperator/interface.hh>
#include <dune/gdt/localfunctional/interface.hh>
#include <dune/gdt/space/interface.hh>

namespace Dune {
namespace GDT {
namespace LocalAssembler {

// forward, to be used in the traits
template <class LocalOperatorImp>
class Codim0Matrix;

template <class LocalOperatorImp>
class Codim0MatrixTraits
{
public:
  typedef Codim0Matrix<LocalOperatorImp> derived_type;
  typedef LocalOperator::Codim0Interface<typename LocalOperatorImp::Traits> LocalOperatorType;
}; // class LocalAssemblerCodim0MatrixTraits

template <class LocalOperatorImp>
class Codim0Matrix
{
public:
  typedef Codim0MatrixTraits<LocalOperatorImp> Traits;
  typedef typename Traits::LocalOperatorType LocalOperatorType;

  Codim0Matrix(const LocalOperatorType& op)
    : localOperator_(op)
  {
  }

  const LocalOperatorType& localOperator() const
  {
    return localOperator_;
  }

private:
  static const size_t numTmpObjectsRequired_ = 1;

public:
  std::vector<size_t> numTmpObjectsRequired() const
  {
    return {numTmpObjectsRequired_, localOperator_.numTmpObjectsRequired()};
  }

  /**
   *  \tparam T           Traits of the SpaceInterface implementation, representing the type of testSpace
   *  \tparam A           Traits of the SpaceInterface implementation, representing the type of ansatzSpace
   *  \tparam EntityType  A model of Dune::Entity< 0 >
   *  \tparam M           Traits of the Dune::Stuff::LA::Container::MatrixInterface implementation, representing the
   * type of systemMatrix
   *  \tparam R           RangeFieldType, i.e. double
   */
  template <class T, class A, class EntityType, class M, class R>
  void assembleLocal(const SpaceInterface<T>& testSpace, const SpaceInterface<A>& ansatzSpace, const EntityType& entity,
                     Dune::Stuff::LA::MatrixInterface<M>& systemMatrix,
                     std::vector<std::vector<Dune::DynamicMatrix<R>>>& tmpLocalMatricesContainer,
                     std::vector<Dune::DynamicVector<size_t>>& tmpIndicesContainer) const
  {
    // check
    assert(tmpLocalMatricesContainer.size() >= 1);
    assert(tmpLocalMatricesContainer[0].size() >= numTmpObjectsRequired_);
    assert(tmpLocalMatricesContainer[1].size() >= localOperator_.numTmpObjectsRequired());
    assert(tmpIndicesContainer.size() >= 2);
    // get and clear matrix
    Dune::DynamicMatrix<R>& localMatrix = tmpLocalMatricesContainer[0][0];
    Dune::Stuff::Common::clear(localMatrix);
    auto& tmpOperatorMatrices = tmpLocalMatricesContainer[1];
    // apply local operator (result is in localMatrix)
    localOperator_.apply(
        testSpace.base_function_set(entity), ansatzSpace.base_function_set(entity), localMatrix, tmpOperatorMatrices);
    // write local matrix to global
    Dune::DynamicVector<size_t>& globalRows = tmpIndicesContainer[0];
    Dune::DynamicVector<size_t>& globalCols = tmpIndicesContainer[1];
    const size_t rows                       = testSpace.mapper().numDofs(entity);
    const size_t cols = ansatzSpace.mapper().numDofs(entity);
    assert(globalRows.size() >= rows);
    assert(globalCols.size() >= cols);
    testSpace.mapper().globalIndices(entity, globalRows);
    ansatzSpace.mapper().globalIndices(entity, globalCols);
    for (size_t ii = 0; ii < rows; ++ii) {
      const auto& localRow  = localMatrix[ii];
      const size_t globalII = globalRows[ii];
      for (size_t jj = 0; jj < cols; ++jj) {
        const size_t globalJJ = globalCols[jj];
        systemMatrix.add_to_entry(globalII, globalJJ, localRow[jj]);
      }
    } // write local matrix to global
  } // ... assembleLocal(...)

private:
  const LocalOperatorType& localOperator_;
}; // class LocalAssemblerCodim0Matrix

// forward, to be used in the traits
template <class LocalOperatorImp>
class Codim0Vector;

template <class LocalFunctionalImp>
class Codim0VectorTraits
{
public:
  typedef Codim0Vector<LocalFunctionalImp> derived_type;
  typedef LocalFunctional::Codim0Interface<typename LocalFunctionalImp::Traits> LocalFunctionalType;
}; // class LocalAssemblerCodim0MatrixTraits

template <class LocalFunctionalImp>
class Codim0Vector
{
public:
  typedef Codim0VectorTraits<LocalFunctionalImp> Traits;
  typedef typename Traits::LocalFunctionalType LocalFunctionalType;

  Codim0Vector(const LocalFunctionalType& func)
    : localFunctional_(func)
  {
  }

  const LocalFunctionalType& localFunctional() const
  {
    return localFunctional_;
  }

private:
  static const size_t numTmpObjectsRequired_ = 1;

public:
  std::vector<size_t> numTmpObjectsRequired() const
  {
    return {numTmpObjectsRequired_, localFunctional_.numTmpObjectsRequired()};
  }

  /**
   *  \tparam T           Traits of the SpaceInterface implementation, representing the type of testSpace
   *  \tparam EntityType  A model of Dune::Entity< 0 >
   *  \tparam V           Traits of the Dune::Stuff::LA::Container::VectorInterface implementation, representing the
   * type of systemVector
   *  \tparam R           RangeFieldType, i.e. double
   */
  template <class T, class EntityType, class V, class R>
  void assembleLocal(const SpaceInterface<T>& testSpace, const EntityType& entity,
                     Dune::Stuff::LA::VectorInterface<V>& systemVector,
                     std::vector<std::vector<Dune::DynamicVector<R>>>& tmpLocalVectorContainer,
                     Dune::DynamicVector<size_t>& tmpIndices) const
  {
    // check
    assert(tmpLocalVectorContainer.size() >= 2);
    assert(tmpLocalVectorContainer[0].size() >= numTmpObjectsRequired_);
    assert(tmpLocalVectorContainer[1].size() >= localFunctional_.numTmpObjectsRequired());
    // get and clear vector
    auto& localVector = tmpLocalVectorContainer[0][0];
    Dune::Stuff::Common::clear(localVector);
    auto& tmpFunctionalVectors = tmpLocalVectorContainer[1];
    // apply local functional (result is in localVector)
    localFunctional_.apply(testSpace.base_function_set(entity), localVector, tmpFunctionalVectors);
    // write local vector to global
    const size_t size = testSpace.mapper().numDofs(entity);
    assert(tmpIndices.size() >= size);
    testSpace.mapper().globalIndices(entity, tmpIndices);
    for (size_t ii = 0; ii < size; ++ii) {
      systemVector.add_to_entry(tmpIndices[ii], localVector[ii]);
    } // write local matrix to global
  } // ... assembleLocal(...)

private:
  const LocalFunctionalType& localFunctional_;
}; // class Codim0Vector

} // namespace LocalAssembler
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_ASSEMLBER_LOCAL_CODIM0_HH
<|endoftext|>


<commit_before>// This file is part of the dune-pymor project:
//   https://github.com/pyMor/dune-pymor
// Copyright Holders: Felix Albrecht, Stephan Rave
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_PYMOR_OPERATORS_INTERFACES_HH
#define DUNE_PYMOR_OPERATORS_INTERFACES_HH

#include <dune/pymor/common/exceptions.hh>
#include <dune/pymor/parameters/base.hh>
#include <dune/pymor/la/container/interfaces.hh>
#include <dune/pymor/la/container.hh>

namespace Dune {
namespace Pymor {

class OperatorInterface
  : public Parametric
{
public:
  template< class... Args >
  OperatorInterface(Args&& ...args)
    : Parametric(std::forward< Args >(args)...)
  {}

  virtual ~OperatorInterface() {}

  virtual bool linear() const = 0;

  virtual unsigned int dim_source() const = 0;

  virtual unsigned int dim_range() const = 0;

  virtual std::string type_source() const = 0;

  virtual std::string type_range() const = 0;

  virtual void apply(const LA::VectorInterface* /*source*/,
                     LA::VectorInterface* /*range*/,
                     const Parameter /*mu*/ = Parameter()) const throw (Exception::types_are_not_compatible,
                                                                        Exception::you_have_to_implement_this,
                                                                        Exception::sizes_do_not_match,
                                                                        Exception::wrong_parameter_type,
                                                                        Exception::requirements_not_met) = 0;

  virtual LA::VectorInterface* apply(const LA::VectorInterface* source, const Parameter mu = Parameter()) const
    throw (Exception::types_are_not_compatible,
           Exception::you_have_to_implement_this,
           Exception::sizes_do_not_match,
           Exception::wrong_parameter_type)
  {
    DUNE_PYMOR_THROW(Exception::types_are_not_compatible,
                     "source (" << source->type() << ") is not a compatible type_source (" << type_source() << ")!");
    LA::VectorInterface* ret = LA::createVector(type_range(), dim_range());
    apply(source, ret, mu);
    return ret;
  }

  virtual double apply2(const LA::VectorInterface* range,
                        const LA::VectorInterface* source,
                        const Parameter mu = Parameter()) const throw (Exception::types_are_not_compatible,
                                                                       Exception::sizes_do_not_match,
                                                                       Exception::wrong_parameter_type)
  {
    std::stringstream msg;
    size_t throw_up = 0;
    if (source->type() != type_source()) {
      msg << "source (" << source->type() << ") is not a compatible type_source (" << type_source() << ")";
      ++throw_up;
    }
    if (range->type() != type_range()) {
      if (throw_up)
        msg << " and ";
      msg << "range (" << range->type() << ") is not a compatible type_range (" << type_range() << ")";
    }
    if (throw_up) DUNE_PYMOR_THROW(Exception::types_are_not_compatible, msg.str() << "!");
    if (source->dim() != dim_source())
      DUNE_PYMOR_THROW(Exception::sizes_do_not_match,
                       "dim of source (" << source->dim() << ") does not match dim_source of this (" << dim_source()
                       << ")!");
    if (range->dim() != dim_range())
      DUNE_PYMOR_THROW(Exception::sizes_do_not_match,
                       "dim of range (" << range->dim() << ") does not match dim_range of this (" << dim_range()
                       << ")!");
    LA::VectorInterface* tmp = apply(source, mu);
    return range->dot(tmp);
  }

  virtual OperatorInterface* freeze_parameter(const Parameter /*mu*/ = Parameter()) const
    throw (Exception::this_is_not_parametric, Exception::you_have_to_implement_this)
  {
    DUNE_PYMOR_THROW(Exception::you_have_to_implement_this, "you really do!");
  }
}; // class OperatorInterface

} // namespace Pymor
} // namespace Dune

#endif // DUNE_PYMOR_OPERATORS_INTERFACES_HH
<commit_msg>[operators.interface] removed 'range = apply(source)'<commit_after>// This file is part of the dune-pymor project:
//   https://github.com/pyMor/dune-pymor
// Copyright Holders: Felix Albrecht, Stephan Rave
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_PYMOR_OPERATORS_INTERFACES_HH
#define DUNE_PYMOR_OPERATORS_INTERFACES_HH

#include <dune/pymor/common/exceptions.hh>
#include <dune/pymor/parameters/base.hh>
#include <dune/pymor/la/container/interfaces.hh>
#include <dune/pymor/la/container.hh>

namespace Dune {
namespace Pymor {

class OperatorInterface
  : public Parametric
{
public:
  template< class... Args >
  OperatorInterface(Args&& ...args)
    : Parametric(std::forward< Args >(args)...)
  {}

  virtual ~OperatorInterface() {}

  virtual bool linear() const = 0;

  virtual unsigned int dim_source() const = 0;

  virtual unsigned int dim_range() const = 0;

  virtual std::string type_source() const = 0;

  virtual std::string type_range() const = 0;

  virtual void apply(const LA::VectorInterface* /*source*/,
                     LA::VectorInterface* /*range*/,
                     const Parameter /*mu*/ = Parameter()) const throw (Exception::types_are_not_compatible,
                                                                        Exception::you_have_to_implement_this,
                                                                        Exception::sizes_do_not_match,
                                                                        Exception::wrong_parameter_type,
                                                                        Exception::requirements_not_met) = 0;

  virtual double apply2(const LA::VectorInterface* range,
                        const LA::VectorInterface* source,
                        const Parameter mu = Parameter()) const throw (Exception::types_are_not_compatible,
                                                                       Exception::sizes_do_not_match,
                                                                       Exception::wrong_parameter_type)
  {
    std::stringstream msg;
    size_t throw_up = 0;
    if (source->type() != type_source()) {
      msg << "source (" << source->type() << ") is not a compatible type_source (" << type_source() << ")";
      ++throw_up;
    }
    if (range->type() != type_range()) {
      if (throw_up)
        msg << " and ";
      msg << "range (" << range->type() << ") is not a compatible type_range (" << type_range() << ")";
    }
    if (throw_up) DUNE_PYMOR_THROW(Exception::types_are_not_compatible, msg.str() << "!");
    if (source->dim() != dim_source())
      DUNE_PYMOR_THROW(Exception::sizes_do_not_match,
                       "dim of source (" << source->dim() << ") does not match dim_source of this (" << dim_source()
                       << ")!");
    if (range->dim() != dim_range())
      DUNE_PYMOR_THROW(Exception::sizes_do_not_match,
                       "dim of range (" << range->dim() << ") does not match dim_range of this (" << dim_range()
                       << ")!");
    LA::VectorInterface* tmp = LA::createVector(type_range(), dim_range());
    apply(source, tmp, mu);
    return range->dot(tmp);
  }

  virtual OperatorInterface* freeze_parameter(const Parameter /*mu*/ = Parameter()) const
    throw (Exception::this_is_not_parametric, Exception::you_have_to_implement_this)
  {
    DUNE_PYMOR_THROW(Exception::you_have_to_implement_this, "you really do!");
  }
}; // class OperatorInterface

} // namespace Pymor
} // namespace Dune

#endif // DUNE_PYMOR_OPERATORS_INTERFACES_HH
<|endoftext|>


<commit_before>// This file is part of the dune-stuff project:
//   https://github.com/wwu-numerik/dune-stuff
// Copyright holders: Rene Milk, Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_STUFF_FEM_FUNCTIONS_CUSTOMPROJECTION_HH
#define DUNE_STUFF_FEM_FUNCTIONS_CUSTOMPROJECTION_HH

#if HAVE_DUNE_FEM

#include <dune/fem/quadrature/cachingquadrature.hh>
#include <dune/fem/function/common/discretefunction.hh>
#include <dune/fem/function/common/gridfunctionadapter.hh>
#include <dune/fem/operator/common/operator.hh>

#include <dune/stuff/common/math.hh>
#include <dune/stuff/fem/namespace.hh>

#include "localmassmatrix.hh"

namespace Dune {
namespace Stuff {
namespace Fem {

  /** A custom projection of an analytical function that uses a non-standard evalute signature:\n
     *
template < class IntersectionIteratorType >\n
     *  void evaluate( const DomainType& arg, RangeType& ret, const IntersectionIteratorType& faceIter ) const
\n
     * \note example being our boundary functions
     * \note output currently somewhat meaningless
     * \see analyticaldata.hh
     **/
class CustomProjection
{
public:
  template< class OriginFunctionType, class DestinationFunctionType >
  static void project(const OriginFunctionType& f, DestinationFunctionType& discFunc) {
    typedef Dune::Fem::CachingQuadrature< typename DestinationFunctionType::DiscreteFunctionSpaceType::GridPartType, 1 >
        FaceQuadratureType;
    const auto& space_ = discFunc.space();
    const auto& gridPart_ = space_.gridPart();
    typename DestinationFunctionType::DiscreteFunctionSpaceType::RangeType phi(0.0);

    for (const auto& e : space_)
    {
      auto lf = discFunc.localFunction(e);
      auto baseFunctionset = space_.baseFunctionSet(e);
      size_t intersection_count = 0;
      const auto intItEnd = gridPart_.iend(e);
      for (auto intIt = gridPart_.ibegin(e);
           intIt != intItEnd;
           ++intIt)
      {
        intersection_count++;
        FaceQuadratureType faceQuadrature(gridPart_,
                                          *intIt,
                                          ( 4 * space_.order() ) + 1,
                                          FaceQuadratureType::INSIDE);
        typename DestinationFunctionType::RangeType ret;
        for (size_t qP = 0; qP < faceQuadrature.nop(); ++qP)
        {
          const double intel
            = faceQuadrature.weight(qP) * e.geometry().integrationElement( faceQuadrature.point(qP) ); // general case

          if ( intIt->boundary() )
          {
            f.evaluate(faceQuadrature.point(qP), ret, *intIt);

            for (size_t i = 0; i < baseFunctionset.size(); ++i)
            {
              baseFunctionset.evaluate(i, faceQuadrature[qP], phi);
              lf[i] += intel * (ret * phi);
            }
          }
        }
      }
    }
  } // project
};

//! basically the fem L2Projection with a function evaluate that converts between compatible types instead of failing
class BetterL2Projection
{
protected:
  template< class FunctionType >
  struct DefaultEvaluationFunctor;

public:
  template< class FunctionImp, class DiscreteFunctionImp >
  static void project(const FunctionImp& func,
                      DiscreteFunctionImp& discFunc,
                      int polOrd = -1)
  {
    static_assert(!(Conversion< FunctionImp, Dune::Fem::IsDiscreteFunction >::exists),
                       "TimeAwareL2Projection_not_implemented_for_discrete_source_functions");
    DefaultEvaluationFunctor< FunctionImp > functor(func);
    projectCommon(functor, discFunc, polOrd);
  }

  template< class TimeProviderType, class FunctionImp, class DiscreteFunctionImp >
  static void project(const TimeProviderType& timeProvider,
                      const FunctionImp& func,
                      DiscreteFunctionImp& discFunc,
                      int polOrd = -1)
  {
    static_assert(!(Conversion< FunctionImp, Dune::Fem::IsDiscreteFunction >::exists),
                       "TimeAwareL2Projection_not_implemented_for_discrete_source_functions");
    TimeEvaluationFunctor< FunctionImp, TimeProviderType > functor(func, timeProvider);
    projectCommon(functor, discFunc, polOrd);
  }

protected:
  template< class FunctionType >
  struct DefaultEvaluationFunctor
  {
    const FunctionType& function_;
    DefaultEvaluationFunctor(const FunctionType& function)
      : function_(function)
    {}

    void evaluate(const typename FunctionType::DomainType& arg, typename FunctionType::RangeType& ret) const {
      function_.evaluate(arg, ret);
    }
  };
  template< class FunctionType, class TimeProviderType >
  struct TimeEvaluationFunctor
  {
    const FunctionType& function_;
    const TimeProviderType& timeProvider_;
    TimeEvaluationFunctor(const FunctionType& function,
                          const TimeProviderType& timeProvider)
      : function_(function)
        , timeProvider_(timeProvider)
    {}
    void evaluate(const typename FunctionType::DomainType& arg, typename FunctionType::RangeType& ret) const {
      function_.evaluate(timeProvider_.subTime(), arg, ret);
    }
  };
  template< class FunctionType >
  struct TimeEvaluationFunctor< FunctionType, double >
  {
    const FunctionType& function_;
    const double time_;
    TimeEvaluationFunctor(const FunctionType& function,
                          const double time)
      : function_(function)
        , time_(time)
    {}
    void evaluate(const typename FunctionType::DomainType& arg, typename FunctionType::RangeType& ret) const {
      function_.evaluate(time_, arg, ret);
    }
  };

  template< class DiscreteFunctionImp, class EvaluationFunctorType >
  static void projectCommon(const EvaluationFunctorType& evalutionFunctor,
                            DiscreteFunctionImp& discFunc,
                            int polOrd = -1) {
    typedef typename DiscreteFunctionImp::DiscreteFunctionSpaceType  DiscreteFunctionSpaceType;
    typedef typename DiscreteFunctionSpaceType::Traits::GridPartType GridPartType;
    typedef Dune::Fem::CachingQuadrature< GridPartType, 0 > QuadratureType;

    typename DiscreteFunctionSpaceType::RangeType ret(0.0);
    typename DiscreteFunctionSpaceType::RangeType phi(0.0);
    const auto& space = discFunc.space();
    const auto quadOrd = std::max(2 * space.order() + 2, polOrd);
    const Dune::Fem::LocalMassMatrix< DiscreteFunctionSpaceType, QuadratureType > massMatrix(space, quadOrd);
    const bool affineMapping = massMatrix.affine();
    discFunc.clear();

    for (const auto& en : space)
    {
      const auto& geo = en.geometry();
      const QuadratureType quad(en, quadOrd);
      auto lf = discFunc.localFunction(en);
      const auto& baseset = lf.baseFunctionSet();
      const auto quadNop = quad.nop();
      const auto numDofs = lf.numDofs();
      for (decltype(quadNop) qP = 0; qP < quadNop; ++qP)
      {
        const double intel = (affineMapping) ?
                             quad.weight(qP) : // affine case
                             quad.weight(qP) * geo.integrationElement( quad.point(qP) ); // general case

        const auto x = geo.global( quad.point(qP) );
        evalutionFunctor.evaluate(x, ret);
        for (decltype(numDofs) i = 0; i < numDofs; ++i)
        {
          baseset.evaluate(i, quad[qP], phi);
          lf[i] += intel * (ret * phi);
        }
      }
      // in case of non-linear mapping apply inverse
      if (!affineMapping)
      {
        massMatrix.applyInverse(en, lf);
      }
    }
  } // projectCommon
};

namespace Experimental {

template< int dim, class RangeType, class JacobianRangeType >
struct GradientJacobianToLaplacian
  : public RangeType
{
  GradientJacobianToLaplacian(const JacobianRangeType& /*jacobian*/) {
    // Dune::CompileTimeChecker< ( dim == 1 || dim > 3 ) > NotImplemented;
    static_assert( (dim == 1 || dim > 3), "GradientJacobianToLaplacian not implemented for this dimension!" );
  }
};

template< class RangeType, class JacobianRangeType >
struct GradientJacobianToLaplacian< 2, RangeType, JacobianRangeType >
  : public RangeType
{
  GradientJacobianToLaplacian(const JacobianRangeType& jacobian) {
    (*this)[0] = jacobian[0][0];
    (*this)[1] = jacobian[3][1];
  }
};

template< class RangeType, class JacobianRangeType >
struct GradientJacobianToLaplacian< 3, RangeType, JacobianRangeType >
  : public RangeType
{
  GradientJacobianToLaplacian(const JacobianRangeType& jacobian) {
    (*this)[0] = jacobian[0][0];
    (*this)[1] = jacobian[4][1];
    (*this)[2] = jacobian[8][2];
  }
};

template< class TimeProviderType,
          class DiscreteVelocityFunctionType,
          class SigmaFunctionType >
class GradientAdapterFunction
  : public SigmaFunctionType
{
protected:
  typedef GradientAdapterFunction< TimeProviderType,
                                   DiscreteVelocityFunctionType,
                                   SigmaFunctionType >
  ThisType;
  typedef SigmaFunctionType
  BaseType;
  const TimeProviderType& timeProvider_;

public:
  GradientAdapterFunction(const TimeProviderType& timeProvider,
                          const DiscreteVelocityFunctionType& velocity,
                          SigmaFunctionType& dummy,
                          int polOrd = -1)
    : BaseType( "grad", dummy.space() )
      , timeProvider_(timeProvider) {
    typedef SigmaFunctionType
    DiscreteFunctionType;
    typedef typename SigmaFunctionType::DiscreteFunctionSpaceType
    DiscreteFunctionSpaceType;
    typedef typename DiscreteFunctionType::LocalFunctionType
    LocalFuncType;
    typedef typename DiscreteFunctionSpaceType::Traits::GridPartType
    GridPartType;
    typedef typename DiscreteFunctionSpaceType::Traits::IteratorType
    Iterator;
    typedef typename DiscreteFunctionSpaceType::BaseFunctionSetType
    BaseFunctionSetType;
//    typedef typename GridPartType::IntersectionIteratorType
//    IntersectionIteratorType;
    typedef typename DiscreteVelocityFunctionType::LocalFunctionType
    LocalFType;

    const DiscreteFunctionSpaceType space( velocity.space().gridPart() );
    const GridPartType& gridPart = space.gridPart();
    // type of quadrature
    typedef Dune::Fem::CachingQuadrature< GridPartType, 0 > VolumeQuadratureType;
//    typedef Dune::Fem::CachingQuadrature< GridPartType, 1 > FaceQuadratureType;
    // type of local mass matrix
    typedef Dune::Stuff::Fem::LocalMassMatrix< DiscreteFunctionSpaceType, VolumeQuadratureType > LocalMassMatrixType;

    const auto quadOrd = std::max(2 * space.order() + 2, polOrd);

    // create local mass matrix object
    LocalMassMatrixType massMatrix(space, quadOrd);

    // check whether geometry mappings are affine or not
    const bool affineMapping = massMatrix.affine();

    // clear destination
    BaseType::clear();

    const Iterator endit = space.end();
    for (Iterator it = space.begin(); it != endit; ++it)
    {
      // get entity
      const typename GridPartType::GridType::template Codim< 0 >::Entity& entity = *it;
      // get geometry
      typedef  typename GridPartType::GridType::template Codim< 0 >::Geometry
      Geometry;
      const Geometry& geo = entity.geometry();

      // get quadrature
      VolumeQuadratureType quad(entity, quadOrd);

      // get local function of destination
      LocalFuncType self_local = BaseType::localFunction(entity);
      // get local function of argument
      const LocalFType velocity_local = velocity.localFunction(entity);

      // get base function set
      const BaseFunctionSetType& baseset = self_local.baseFunctionSet();

      const auto quadNop = quad.nop();
      const auto numDofs = self_local.numDofs();

      // volume part
      for (decltype(quadNop) qP = 0; qP < quadNop; ++qP)
      {
        const typename DiscreteFunctionSpaceType::DomainType xLocal = quad.point(qP);

        const double intel = (affineMapping) ?
                             quad.weight(qP) : // affine case
                             quad.weight(qP) * geo.integrationElement(xLocal); // general case

        typename DiscreteFunctionSpaceType::DomainType
        xWorld = geo.global(xLocal);

        // evaluate function
        typename DiscreteVelocityFunctionType::DiscreteFunctionSpaceType::RangeType
        velocity_eval;
        velocity_local.evaluate(quad[qP], velocity_eval);

        typename DiscreteVelocityFunctionType::DiscreteFunctionSpaceType::JacobianRangeType
        velocity_jacobian_eval;
        velocity_local.jacobian(quad[qP], velocity_jacobian_eval);

        // do projection
        for (int i = 0; i < numDofs; ++i)
        {
          typename DiscreteFunctionType::DiscreteFunctionSpaceType::RangeType phi(0.0);
          baseset.evaluate(i, quad[qP], phi);
          self_local[i] += intel * ( Dune::Stuff::Common::colonProduct(velocity_jacobian_eval, phi) );
        }
      }

      // in case of non-linear mapping apply inverse
      if (!affineMapping)
      {
        massMatrix.applyInverse(entity, self_local);
      }
    }
  }
};

} // namespace Experimental

} // namespace Fem
} // namespace Stuff
} // namespace Dune

#endif // HAVE_DUNE_FEM

#endif // DUNE_STUFF_FEM_FUNCTIONS_CUSTOMPROJECTION_HH
<commit_msg>[fem.customprojection] refs #10<commit_after>// This file is part of the dune-stuff project:
//   https://github.com/wwu-numerik/dune-stuff
// Copyright holders: Rene Milk, Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_STUFF_FEM_FUNCTIONS_CUSTOMPROJECTION_HH
#define DUNE_STUFF_FEM_FUNCTIONS_CUSTOMPROJECTION_HH

#if HAVE_DUNE_FEM

#include <dune/fem/quadrature/cachingquadrature.hh>
#include <dune/fem/function/common/discretefunction.hh>
#include <dune/fem/function/common/gridfunctionadapter.hh>
#include <dune/fem/operator/common/operator.hh>

#include <dune/stuff/common/math.hh>
#include <dune/stuff/fem/namespace.hh>

#include "localmassmatrix.hh"

namespace Dune {
namespace Stuff {
namespace Fem {

  /** A custom projection of an analytical function that uses a non-standard evalute signature:\n
     *
template < class IntersectionIteratorType >\n
     *  void evaluate( const DomainType& arg, RangeType& ret, const IntersectionIteratorType& faceIter ) const
\n
     * \note example being our boundary functions
     * \note output currently somewhat meaningless
     * \see analyticaldata.hh
     **/
class CustomProjection
{
public:
  template< class OriginFunctionType, class DestinationFunctionType >
  static void project(const OriginFunctionType& f, DestinationFunctionType& discFunc) {
    typedef Dune::Fem::CachingQuadrature< typename DestinationFunctionType::DiscreteFunctionSpaceType::GridPartType, 1 >
        FaceQuadratureType;
    const auto& space_ = discFunc.space();
    const auto& gridPart_ = space_.gridPart();
    typename DestinationFunctionType::DiscreteFunctionSpaceType::RangeType phi(0.0);

    for (const auto& e : space_)
    {
      auto lf = discFunc.localFunction(e);
      auto baseFunctionset = space_.baseFunctionSet(e);
      size_t intersection_count = 0;
      const auto intItEnd = gridPart_.iend(e);
      for (auto intIt = gridPart_.ibegin(e);
           intIt != intItEnd;
           ++intIt)
      {
        intersection_count++;
        FaceQuadratureType faceQuadrature(gridPart_,
                                          *intIt,
                                          ( 4 * space_.order() ) + 1,
                                          FaceQuadratureType::INSIDE);
        typename DestinationFunctionType::RangeType ret;
        for (size_t qP = 0; qP < faceQuadrature.nop(); ++qP)
        {
          const double intel
            = faceQuadrature.weight(qP) * e.geometry().integrationElement( faceQuadrature.point(qP) ); // general case

          if ( intIt->boundary() )
          {
            f.evaluate(faceQuadrature.point(qP), ret, *intIt);

            for (size_t i = 0; i < baseFunctionset.size(); ++i)
            {
              baseFunctionset.evaluate(i, faceQuadrature[qP], phi);
              lf[i] += intel * (ret * phi);
            }
          }
        }
      }
    }
  } // project
};

//! basically the fem L2Projection with a function evaluate that converts between compatible types instead of failing
class BetterL2Projection
{
protected:
  template< class FunctionType >
  struct DefaultEvaluationFunctor;

public:
  template< class FunctionImp, class DiscreteFunctionImp >
  static void project(const FunctionImp& func,
                      DiscreteFunctionImp& discFunc,
                      int polOrd = -1)
  {
    static_assert(!(Conversion< FunctionImp, Dune::Fem::IsDiscreteFunction >::exists),
                       "TimeAwareL2Projection_not_implemented_for_discrete_source_functions");
    DefaultEvaluationFunctor< FunctionImp > functor(func);
    projectCommon(functor, discFunc, polOrd);
  }

  template< class TimeProviderType, class FunctionImp, class DiscreteFunctionImp >
  static void project(const TimeProviderType& timeProvider,
                      const FunctionImp& func,
                      DiscreteFunctionImp& discFunc,
                      int polOrd = -1)
  {
    static_assert(!(Conversion< FunctionImp, Dune::Fem::IsDiscreteFunction >::exists),
                       "TimeAwareL2Projection_not_implemented_for_discrete_source_functions");
    TimeEvaluationFunctor< FunctionImp, TimeProviderType > functor(func, timeProvider);
    projectCommon(functor, discFunc, polOrd);
  }

protected:
  template< class FunctionType >
  struct DefaultEvaluationFunctor
  {
    const FunctionType& function_;
    DefaultEvaluationFunctor(const FunctionType& function)
      : function_(function)
    {}

    void evaluate(const typename FunctionType::DomainType& arg, typename FunctionType::RangeType& ret) const {
      function_.evaluate(arg, ret);
    }
  };
  template< class FunctionType, class TimeProviderType >
  struct TimeEvaluationFunctor
  {
    const FunctionType& function_;
    const TimeProviderType& timeProvider_;
    TimeEvaluationFunctor(const FunctionType& function,
                          const TimeProviderType& timeProvider)
      : function_(function)
        , timeProvider_(timeProvider)
    {}
    void evaluate(const typename FunctionType::DomainType& arg, typename FunctionType::RangeType& ret) const {
      function_.evaluate(timeProvider_.subTime(), arg, ret);
    }
  };
  template< class FunctionType >
  struct TimeEvaluationFunctor< FunctionType, double >
  {
    const FunctionType& function_;
    const double time_;
    TimeEvaluationFunctor(const FunctionType& function,
                          const double time)
      : function_(function)
        , time_(time)
    {}
    void evaluate(const typename FunctionType::DomainType& arg, typename FunctionType::RangeType& ret) const {
      function_.evaluate(time_, arg, ret);
    }
  };

  template< class DiscreteFunctionImp, class EvaluationFunctorType >
  static void projectCommon(const EvaluationFunctorType& evalutionFunctor,
                            DiscreteFunctionImp& discFunc,
                            int polOrd = -1) {
    typedef typename DiscreteFunctionImp::DiscreteFunctionSpaceType  DiscreteFunctionSpaceType;
    typedef typename DiscreteFunctionSpaceType::Traits::GridPartType GridPartType;
    typedef Dune::Fem::CachingQuadrature< GridPartType, 0 > QuadratureType;

    typename DiscreteFunctionSpaceType::RangeType ret(0.0);
    typename DiscreteFunctionSpaceType::RangeType phi(0.0);
    const auto& space = discFunc.space();
    const auto quadOrd = std::max(2 * space.order() + 2, polOrd);
    const Dune::Fem::LocalMassMatrix< DiscreteFunctionSpaceType, QuadratureType > massMatrix(space, quadOrd);
    const bool affineMapping = massMatrix.affine();
    discFunc.clear();

    for (const auto& en : space)
    {
      const auto& geo = en.geometry();
      const QuadratureType quad(en, quadOrd);
      auto lf = discFunc.localFunction(en);
      const auto& baseset = lf.baseFunctionSet();
      const auto quadNop = quad.nop();
      const auto numDofs = lf.numDofs();
      for (decltype(quadNop) qP = 0; qP < quadNop; ++qP)
      {
        const double intel = (affineMapping) ?
                             quad.weight(qP) : // affine case
                             quad.weight(qP) * geo.integrationElement( quad.point(qP) ); // general case

        const auto x = geo.global( quad.point(qP) );
        evalutionFunctor.evaluate(x, ret);
        for (decltype(numDofs) i = 0; i < numDofs; ++i)
        {
          baseset.evaluate(i, quad[qP], phi);
          lf[i] += intel * (ret * phi);
        }
      }
      // in case of non-linear mapping apply inverse
      if (!affineMapping)
      {
        massMatrix.applyInverse(en, lf);
      }
    }
  } // projectCommon
};

namespace Experimental {

template< int dim, class RangeType, class JacobianRangeType >
struct GradientJacobianToLaplacian
  : public RangeType
{
  GradientJacobianToLaplacian(const JacobianRangeType& /*jacobian*/) {
    // Dune::CompileTimeChecker< ( dim == 1 || dim > 3 ) > NotImplemented;
    static_assert( (dim == 1 || dim > 3), "GradientJacobianToLaplacian not implemented for this dimension!" );
  }
};

template< class RangeType, class JacobianRangeType >
struct GradientJacobianToLaplacian< 2, RangeType, JacobianRangeType >
  : public RangeType
{
  GradientJacobianToLaplacian(const JacobianRangeType& jacobian) {
    (*this)[0] = jacobian[0][0];
    (*this)[1] = jacobian[3][1];
  }
};

template< class RangeType, class JacobianRangeType >
struct GradientJacobianToLaplacian< 3, RangeType, JacobianRangeType >
  : public RangeType
{
  GradientJacobianToLaplacian(const JacobianRangeType& jacobian) {
    (*this)[0] = jacobian[0][0];
    (*this)[1] = jacobian[4][1];
    (*this)[2] = jacobian[8][2];
  }
};

template< class TimeProviderType,
          class DiscreteVelocityFunctionType,
          class SigmaFunctionType >
class GradientAdapterFunction
  : public SigmaFunctionType
{
protected:
  typedef GradientAdapterFunction< TimeProviderType,
                                   DiscreteVelocityFunctionType,
                                   SigmaFunctionType >
  ThisType;
  typedef SigmaFunctionType
  BaseType;
  const TimeProviderType& timeProvider_;

public:
  GradientAdapterFunction(const TimeProviderType& timeProvider,
                          const DiscreteVelocityFunctionType& velocity,
                          SigmaFunctionType& dummy,
                          int polOrd = -1)
    : BaseType( "grad", dummy.space() )
      , timeProvider_(timeProvider) {
    typedef SigmaFunctionType
    DiscreteFunctionType;
    typedef typename SigmaFunctionType::DiscreteFunctionSpaceType
    DiscreteFunctionSpaceType;
    typedef typename DiscreteFunctionType::LocalFunctionType
    LocalFuncType;
    typedef typename DiscreteFunctionSpaceType::Traits::GridPartType
    GridPartType;
    typedef typename DiscreteFunctionSpaceType::Traits::IteratorType
    Iterator;
    typedef typename DiscreteFunctionSpaceType::BaseFunctionSetType
    BaseFunctionSetType;
//    typedef typename GridPartType::IntersectionIteratorType
//    IntersectionIteratorType;
    typedef typename DiscreteVelocityFunctionType::LocalFunctionType
    LocalFType;

    const DiscreteFunctionSpaceType space( velocity.space().gridPart() );
    const GridPartType& gridPart = space.gridPart();
    // type of quadrature
    typedef Dune::Fem::CachingQuadrature< GridPartType, 0 > VolumeQuadratureType;
//    typedef Dune::Fem::CachingQuadrature< GridPartType, 1 > FaceQuadratureType;
    // type of local mass matrix
    typedef Dune::Stuff::Fem::LocalMassMatrix< DiscreteFunctionSpaceType, VolumeQuadratureType > LocalMassMatrixType;

    const auto quadOrd = std::max(2 * space.order() + 2, polOrd);

    // create local mass matrix object
    LocalMassMatrixType massMatrix(space, quadOrd);

    // check whether geometry mappings are affine or not
    const bool affineMapping = massMatrix.affine();

    // clear destination
    BaseType::clear();

    const Iterator endit = space.end();
    for (Iterator it = space.begin(); it != endit; ++it)
    {
      // get entity
      const typename GridPartType::GridType::template Codim< 0 >::Entity& entity = *it;
      // get geometry
      typedef  typename GridPartType::GridType::template Codim< 0 >::Geometry
      Geometry;
      const Geometry& geo = entity.geometry();

      // get quadrature
      VolumeQuadratureType quad(entity, quadOrd);

      // get local function of destination
      LocalFuncType self_local = BaseType::localFunction(entity);
      // get local function of argument
      const LocalFType velocity_local = velocity.localFunction(entity);

      // get base function set
      const BaseFunctionSetType& baseset = self_local.baseFunctionSet();

      const auto quadNop = quad.nop();
      const auto numDofs = self_local.numDofs();

      // volume part
      for (decltype(quadNop) qP = 0; qP < quadNop; ++qP)
      {
        const typename DiscreteFunctionSpaceType::DomainType xLocal = quad.point(qP);

        const double intel = (affineMapping) ?
                             quad.weight(qP) : // affine case
                             quad.weight(qP) * geo.integrationElement(xLocal); // general case

        typename DiscreteFunctionSpaceType::DomainType
        xWorld = geo.global(xLocal);

        // evaluate function
        typename DiscreteVelocityFunctionType::DiscreteFunctionSpaceType::RangeType
        velocity_eval;
        velocity_local.evaluate(quad[qP], velocity_eval);

        typename DiscreteVelocityFunctionType::DiscreteFunctionSpaceType::JacobianRangeType
        velocity_jacobian_eval;
        velocity_local.jacobian(quad[qP], velocity_jacobian_eval);

        // do projection
        for (decltype(numDofs) i = 0; i < numDofs; ++i)
        {
          typename DiscreteFunctionType::DiscreteFunctionSpaceType::RangeType phi(0.0);
          baseset.evaluate(i, quad[qP], phi);
          self_local[i] += intel * ( Dune::Stuff::Common::colonProduct(velocity_jacobian_eval, phi) );
        }
      }

      // in case of non-linear mapping apply inverse
      if (!affineMapping)
      {
        massMatrix.applyInverse(entity, self_local);
      }
    }
  }
};

} // namespace Experimental

} // namespace Fem
} // namespace Stuff
} // namespace Dune

#endif // HAVE_DUNE_FEM

#endif // DUNE_STUFF_FEM_FUNCTIONS_CUSTOMPROJECTION_HH
<|endoftext|>


<commit_before>#include "platform.h"
#include <iostream>
using namespace std;

Platform::Platform() {
	//TODO: 初始化各个玩家
	initLevels();
	initCards();

}

void Platform::initLevels() {
	// http://zh.wikipedia.org/wiki/%E8%B0%81%E6%98%AF%E7%89%9B%E5%A4%B4%E7%8E%8B
	for (int i = 1; i <= MAX_CARD; ++i) {
		if ( (i - 5) % 5 == 0) {
			level.insert(pair <int, int>(i, 2));
			continue;
		}
		if (i % 10 == 0) {
			level.insert(pair <int, int>(i, 3));
			continue;
		}
		if (i % 11 == 0) {
			level.insert(pair <int, int>(i, 5));
			continue;
		}
		if (i == 55) {
			level.insert(pair <int, int>(i, 7));
			continue;
		}
		level.insert(pair <int, int>(i, 1));
	}
	// for (auto iter = level.begin(); iter != level.end(); ++iter) {
	// 	cout << iter->first << ' ' << iter->second<<endl;
	// }
}

void Platform::initCards() {
	for (int i = 1; i <= MAX_CARD; ++i)
		cards.push_back(i);
	random_shuffle(cards.begin(), cards.end());

	auto iter = cards.begin();

	int avaliableCount = MAX_CARD - 4;
	extraCards.resize(avaliableCount % player_count);
	copy(iter, iter + avaliableCount % player_count, extraCards.begin());
	printVector(extraCards);
	iter += avaliableCount % player_count;

	//TODO 伪造数据
	for (int i = 0; i != player_count; ++i) {
		vector<int> tempCards(avaliableCount / player_count);
		copy(iter, iter + avaliableCount / player_count, tempCards.begin());
		userCards.insert(pair <string, vector<int>> ("name" + i, tempCards));
		iter = iter + avaliableCount / player_count;
	}

	while (iter != cards.end()) {
		heapCards.push_back(*iter);
		++iter;
	}
	printVector(heapCards);
}

void Platform::printVector(vector<int> vec) {
	for (auto ai = vec.begin(); ai != vec.end(); ++ai)
		cout << *ai << ' ';
	cout << endl;
}<commit_msg>忘了提交了什么<commit_after>#include "platform.h"
#include <iostream>
using namespace std;

Platform::Platform() {
	//TODO: 初始化各个玩家
	initLevels();
	initCards();

}

void Platform::initLevels() {
	// http://zh.wikipedia.org/wiki/%E8%B0%81%E6%98%AF%E7%89%9B%E5%A4%B4%E7%8E%8B
	for (int i = 1; i <= MAX_CARD; ++i) {
		if ( (i - 5) % 5 == 0) {
			level.insert(pair <int, int>(i, 2));
			continue;
		}
		if (i % 10 == 0) {
			level.insert(pair <int, int>(i, 3));
			continue;
		}
		if (i % 11 == 0) {
			level.insert(pair <int, int>(i, 5));
			continue;
		}
		if (i == 55) {
			level.insert(pair <int, int>(i, 7));
			continue;
		}
		level.insert(pair <int, int>(i, 1));
	}
	// for (auto iter = level.begin(); iter != level.end(); ++iter) {
	// 	cout << iter->first << ' ' << iter->second<<endl;
	// }
}

void Platform::initCards() {
	for (int i = 1; i <= MAX_CARD; ++i)
		cards.push_back(i);
	random_shuffle(cards.begin(), cards.end());

	auto iter = cards.begin();

	int avaliableCount = MAX_CARD - 4;
	extraCards.resize(avaliableCount % player_count);
	copy(iter, iter + avaliableCount % player_count, extraCards.begin());
	iter += avaliableCount % player_count;

	//TODO 伪造数据
	for (int i = 0; i != player_count; ++i) {
		vector<int> tempCards(avaliableCount / player_count);
		copy(iter, iter + avaliableCount / player_count, tempCards.begin());
		userCards.insert(pair <string, vector<int>> ("name" + i, tempCards));
		iter = iter + avaliableCount / player_count;
	}

	while (iter != cards.end()) {
		heapCards.push_back(*iter);
		++iter;
	}
}

void Platform::printVector(vector<int> vec) {
	for (auto ai = vec.begin(); ai != vec.end(); ++ai)
		cout << *ai << ' ';
	cout << endl;
}<|endoftext|>


<commit_before>// -*- mode: c++; coding: utf-8 -*-
#pragma once
#ifndef GRN_HPP_
#define GRN_HPP_

#include <boost/graph/adjacency_list.hpp>

#include <boost/graph/graphviz.hpp>
#include <boost/graph/graphml.hpp>

/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////
namespace wtl {
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////

//typedef boost::property<boost::vertex_priority_t, double> VertexProperty;
typedef boost::property<boost::vertex_potential_t, double> VertexProperty;
typedef boost::property<boost::edge_weight_t, double> EdgeProperty;
typedef boost::property<boost::graph_name_t, double> GraphProperty;

typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::bidirectionalS,
                       VertexProperty, EdgeProperty, GraphProperty> Graph;
typedef boost::graph_traits<Graph>::vertex_descriptor Vertex;
typedef boost::graph_traits<Graph>::edge_descriptor Edge;

Graph make_graph(const std::vector<std::vector<double> >& adj_matrix) {
    const size_t order = adj_matrix.size();
    std::vector<std::pair<size_t, size_t> > adj_list;
    std::vector<double> weights;
    for (size_t i=0; i<order; ++i) {
        const auto& row = adj_matrix[i];
        for (size_t j=0; j<order; ++j) {
            if (row[j] != 0.0) {
                adj_list.push_back({j, i});
                weights.push_back(row[j]);
            }
        }
    }
    Graph graph(adj_list.begin(), adj_list.end(), weights.begin(), order);
    return graph;
}

template <class Graph>
class weight_label_writer {
  public:
    weight_label_writer(const Graph& g) : graph_(g) {}

    template <class VertexOrEdge>
    void operator()(std::ostream& ost, const VertexOrEdge& edge) const {
        write(ost, boost::get(boost::edge_weight, graph_, edge));
    }

  private:
    template <class Edge, class Weight>
    void write(std::ostream& ost, const Weight& weight) const {
        ost << "[weight=" << weight << "]";
    }

    const Graph& graph_;
};

/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////
} // namespace wtl
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////

#endif // GRN_HPP_
<commit_msg>complete grn.hpp for now<commit_after>// -*- mode: c++; coding: utf-8 -*-
#pragma once
#ifndef GRN_HPP_
#define GRN_HPP_

#include <string>
#include <sstream>

#include <boost/graph/adjacency_list.hpp>

#include <boost/graph/graphviz.hpp>
#include <boost/graph/graphml.hpp>

/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////

enum vertex_input_t {vertex_input};
enum graph_frequency_t {graph_frequency};

namespace boost {
    BOOST_INSTALL_PROPERTY(vertex, input);
    BOOST_INSTALL_PROPERTY(graph, frequency);
}

/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////
namespace wtl {
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////

typedef boost::property<vertex_input_t, double> VertexProperty;
typedef boost::property<boost::edge_weight_t, double> EdgeProperty;

typedef std::map<std::string, std::string> AttrMap;

typedef boost::property<boost::graph_graph_attribute_t, AttrMap,
        boost::property<boost::graph_vertex_attribute_t, AttrMap,
        boost::property<boost::graph_edge_attribute_t, AttrMap> > > GraphProperty;

typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::bidirectionalS,
                       boost::no_property, EdgeProperty, GraphProperty> Graph;
//                       VertexProperty, EdgeProperty, GraphProperty> Graph;

Graph make_graph(const std::vector<std::vector<double> >& adj_matrix) {
    const size_t order = adj_matrix.size();
    std::vector<std::pair<size_t, size_t> > adj_list;
    std::vector<double> weights;
    for (size_t i=0; i<order; ++i) {
        const auto& row = adj_matrix[i];
        for (size_t j=0; j<order; ++j) {
            if (row[j] != 0.0) {
                adj_list.push_back({j, i});
                weights.push_back(row[j]);
            }
        }
    }
    Graph graph(adj_list.begin(), adj_list.end(), weights.begin(), order);
    return graph;
}

template <class Values>
class property_writer {
  public:
    property_writer(const Values& v, const std::string& key)
        : values_(v), key_(key) {}

    template <class VertexOrEdge>
    void operator()(std::ostream& ost, const VertexOrEdge& voe) const {
        ost << "[" << key_ << "=" << boost::get(values_, voe) << "]";
    }
  private:
    const Values values_;
    const std::string key_;
};
template <class Values> inline
property_writer<Values>
make_property_writer(const Values& values, const std::string& key="label") {
    return property_writer<Values>(values, key);
}

inline std::string str_graphviz(Graph& graph) {
    std::ostringstream oss;
    boost::write_graphviz(oss, graph,
        boost::default_writer(),
//        make_property_writer(boost::get(VertexProperty::tag_type(), graph), "input"),
        make_property_writer(boost::get(boost::edge_weight, graph), "weight"),
        boost::make_graph_attributes_writer(graph)
        );
    return oss.str();
}

template <class GraphType> inline
std::string str_graphml(GraphType& graph) {
    std::ostringstream oss;
    boost::dynamic_properties dp;
    dp.property("node_id", boost::get(boost::vertex_index, graph));
    dp.property("input", boost::get(GraphType::vertex_property_type::tag_type(), graph));
    dp.property("weight", boost::get(GraphType::edge_property_type::tag_type(), graph));
    boost::write_graphml(oss, graph, dp);
    return oss.str();
}

template <class GraphType, class V> inline
void put_vertices_property(GraphType* g, const V& values) {
    for (size_t i=0; i<values.size(); ++i) {
        boost::put(GraphType::vertex_property_type::tag_type(),
                   *g, boost::vertex(i, *g), values[i]);
    }
}

template <class GraphType, class Value> inline
void insert_graphattr(GraphType* graph, const std::string& key, const Value& value) {
    auto attrmap = boost::get_property(*graph, boost::graph_graph_attribute);
    attrmap[key] = std::to_string(value);
    boost::set_property(*graph, boost::graph_graph_attribute, attrmap);
}

std::string dot_grn(const std::vector<std::vector<double> >& adj_matrix,
//                    const std::vector<double>& receptors,
                    const size_t frequency) {
    Graph graph = make_graph(adj_matrix);
//    put_vertices_property(&graph, receptors);
    insert_graphattr(&graph, "freqency", frequency);
    return str_graphviz(graph);
}

/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////
} // namespace wtl
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////

#endif // GRN_HPP_
<|endoftext|>


<commit_before>#include "event.h"
#include <stdlib.h>
#include <sys/epoll.h>
#include <stdio.h>

event::event(int fd)
: fd_(fd)
{
     struct epoll_event ev;
     events_ = new struct epoll_event[1];
     int listen_sock, conn_sock, nfds, epollfd;

     /* Set up listening socket, 'listen_sock' (socket(),
        bind(), listen()) */

     data_ = epoll_create(10);
     if (epollfd == -1)
     {
         perror("epoll_create");
         exit(EXIT_FAILURE);
     }

     ev.events = EPOLLIN;
     ev.data.fd = fd;
     if (epoll_ctl(data_, EPOLL_CTL_ADD, fd, &ev) == -1) {
         perror("epoll_ctl: listen_sock");
         exit(EXIT_FAILURE);
     }

}

event::~event()
{
    delete [](struct epoll_event*)events_;
}

bool event::wait(uint32_t timeout_usec)
{
    auto nfds = epoll_wait(data_, static_cast<struct epoll_event*>(events_), 10, -1);
    if (nfds == -1) {
        perror("epoll_pwait");
        exit(EXIT_FAILURE);
    }
}
<commit_msg>update event::wait<commit_after>#include "event.h"
#include <stdlib.h>
#include <sys/epoll.h>
#include <stdio.h>

event::event(int fd)
: fd_(fd)
{
     struct epoll_event ev;
     events_ = new struct epoll_event[1];
     int listen_sock, conn_sock, nfds, epollfd;

     /* Set up listening socket, 'listen_sock' (socket(),
        bind(), listen()) */

     data_ = epoll_create(10);
     if (epollfd == -1)
     {
         perror("epoll_create");
         exit(EXIT_FAILURE);
     }

     ev.events = EPOLLIN;
     ev.data.fd = fd;
     if (epoll_ctl(data_, EPOLL_CTL_ADD, fd, &ev) == -1) {
         perror("epoll_ctl: listen_sock");
         exit(EXIT_FAILURE);
     }

}

event::~event()
{
    delete [](struct epoll_event*)events_;
}

bool event::wait(uint32_t timeout_usec)
{
    auto nfds = epoll_wait(data_, static_cast<struct epoll_event*>(events_), 10, -1);
    if (nfds == -1) {
        perror("epoll_pwait");
        exit(EXIT_FAILURE);
    }
    return nfds > 0;
}
<|endoftext|>