<commit_before>#include <iostream>

#include <CL/cl.hpp>
#include <EasyCl.h>
#include <fstream>

using namespace EasyCl;
using namespace std;

//////////////////////////////////////////////////////////////////////////
//DeviceManager								//
//////////////////////////////////////////////////////////////////////////

SourceCode::SourceCode(string path)
{
	load(path);
}

SourceCode::SourceCode()
{
}

int SourceCode::load(string path)
{
	isGood = false;

	ifstream file(path);
	if(file.good() == false)
	{
		cout << "Failed to load " << path << " ." << endl;
		return 0;
	}

	string sourceCode(
            istreambuf_iterator<char>(file),
            (istreambuf_iterator<char>()));

	source = cl::Program::Sources(1, make_pair(sourceCode.c_str(), sourceCode.length()+1));
	code = sourceCode;
	isGood = true;

	return 1;
}

bool SourceCode::good()
{
	return isGood;
}

//////////////////////////////////////////////////////////////////////////
//ComputeDevice								//
//////////////////////////////////////////////////////////////////////////

ComputeDevice::ComputeDevice(cl::Device dev,cl::Context con)
{
	device = dev;
	context = con;
	commandQueue = cl::CommandQueue(context, device);
}

//////////////////////////////////////////////////////////////////////////
//ComputeDeviceList							//
//////////////////////////////////////////////////////////////////////////

bool ComputeDevice::avliable()
{
	int inQueueComunt = commandQueue.getInfo<CL_QUEUE_REFERENCE_COUNT>();
	if(inQueueComunt == 0)
		return false;
	return true;
}

ComputeDevice* ComputeDeviceList::defaultDevice(cl_device_type deviceType)
{
	if(deviceType == CL_DEVICE_TYPE_ALL)
		return &devices[0];

	int deviceCount = devices.size();
	for(int i=0;i<deviceCount;i++)
	{
		cl_device_type type = devices[i].device.getInfo<CL_DEVICE_TYPE>();
		//NOTE: I shouldn't need deviceType == CL_DEVICE_TYPE_ALL here. Just for completeness.
		if((type & deviceType) != 0 || deviceType == CL_DEVICE_TYPE_ALL)
			return &devices[i];
	}

	return NULL;
}

ComputeDeviceList ComputeDeviceList::findDevice(string keyWord,cl_device_type deviceType)
{
	int deviceCount = devices.size();
	ComputeDeviceList list;
	for(int i=0;i<deviceCount;i++)
	{
		cl_device_type type = devices[i].device.getInfo<CL_DEVICE_TYPE>();
		if((type & deviceType) || deviceType == CL_DEVICE_TYPE_ALL)
			if(devices[i].device.getInfo<CL_DEVICE_NAME>().find(keyWord) != string::npos)
				list.devices.push_back(devices[i]);
	}

	return list;
}

//////////////////////////////////////////////////////////////////////////
//ComputeDevice								//
//////////////////////////////////////////////////////////////////////////

Software::Software(ComputeDevice* dev, SourceCode sou)
{
	//cl_int err = this->errorCode;
	device = dev;
	sourceCode = sou;

	program = cl::Program(device->context, sourceCode.source,&errorCode);
	if(errorCode != CL_SUCCESS)
	{
		cout << "Error while creating Software/cl::Program , code " << errorCode << endl;
		isGood = false;
	}
	else
		isGood = true;
}

Software::Software()
{
}

Software::~Software()
{
	int size = buffers.size();
	for(int i=0;i<size;i++)
		if(buffers[i] != NULL)
			delete buffers[i];
}

cl_int Software::build(string options)
{
	//HACK: This is a nasty way to make cl::Program::build() only build for one device
	vector<cl::Device> devs;
	devs.push_back(device->device);

	cl_int result = program.build(devs,options.c_str());
	if(result != CL_SUCCESS)
	{
		cl_int err = 0;
		//NOTE 2015/5/9 : nVidia OpenCL compiler SUCKS. the error message is mostly misleading.
		//Go for AMD or Intel if possible. Really.
		cout << program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(devs[0],&err) << endl;

		cout << "Error occured while compiling OpenCL program" << endl
			<< "Error Code: " << result << endl;
		return result;
	}
	return result;
}

bool Software::good()
{
	return isGood;
}

cl_int Software::getError()
{
	return errorCode;
}

cl_int Software::createBuffer(cl_mem_flags flags, size_t size, void* ptr,int& index)
{
	int buffersListSize = buffers.size();
	int emptyIndex = -1;
	for(int i=0;i<buffersListSize;i++)
		if(buffers[i] == NULL)
		{
			emptyIndex = i;
			break;
		}

	cl_int err = 0;
	cl::Buffer* newBuffer = new cl::Buffer(device->context,flags,size,ptr,&err);
	if(err != CL_SUCCESS)
	{
		cout << "Error creating cl::Buffer , code " << err << endl;
		return err;
	}
	if(ptr != NULL)
	{
		err = device->commandQueue.enqueueWriteBuffer(*newBuffer,CL_TRUE,0,size, ptr);
		if(err != CL_SUCCESS)
		{
			cout << "Error uploading data to device , code " << err << endl;
			delete newBuffer;
			return err;
		}
	}

	if(emptyIndex >= 0)
	{
		buffers[emptyIndex] = newBuffer;
		index = emptyIndex;
	}
	else
	{
		index = buffers.size();
		buffers.push_back(newBuffer);
	}
	return err;

}

void Software::releaseBuffer(int index)
{
	delete buffers[index];
	buffers[index] = NULL;
}

//////////////////////////////////////////////////////////////////////////
//DeviceManager								//
//////////////////////////////////////////////////////////////////////////

Kernel::Kernel(Software program, string funcName)
{
	software = program;
	cl_int err = 0;

	kernel = cl::Kernel(software.program, funcName.c_str(),&err);

	if(err != CL_SUCCESS)
	{
		cout << "Error creating kernel " << funcName << ", code " << err << endl;
		return;
	}

	int argCount = kernel.getInfo<CL_KERNEL_NUM_ARGS>();
	buffers = new cl::Buffer* [argCount];
	delProtect = new bool[argCount];
	for(int i=0;i<argCount;i++)
		buffers[i] = NULL, delProtect[i] = false;
}

Kernel::~Kernel()
{
	int argCount = kernel.getInfo<CL_KERNEL_NUM_ARGS>();
	for(int i=0;i<argCount;i++)
		if(buffers[i] != NULL && delProtect[i] == false)
		{
			//cout << this << " -> " << &buffers[i] << " : " << i << endl;
			delete buffers[i];
		}
	delete [] buffers;
	delete [] delProtect;
}

cl_int Kernel::setArgBuffer(int index, cl_mem_flags flags, size_t size, void* ptr)
{
	if(buffers[index] != NULL && delProtect[index] == false)
		delete buffers[index];

	cl_int err = 0;
	buffers[index] = new cl::Buffer(software.device->context,flags,size,ptr,&err);

	if(err != CL_SUCCESS)
	{
		cout << "Error creating cl::Buffer , code " << err << endl;
		return err;
	}

	if(ptr != NULL)
	{
		cl::Event event;
		err = software.device->commandQueue.enqueueWriteBuffer(*buffers[index],CL_TRUE,0,size, ptr,NULL,&event);
		if(err != CL_SUCCESS)
		{
			cout << "Error uploading data to device , code " << err << endl;
			//delete buffers[index];
			return err;
		}
		event.wait();
	}

	err = kernel.setArg(index, *buffers[index]);
	if(err != CL_SUCCESS)
	{
		cout << "Error set argumant to kernel , code " << err << endl;
		delete buffers[index];
		return err;
	}
	delProtect[index] = false;

	return err;
}

cl_int Kernel::setArg(int index, cl::Buffer& buf)
{
	if(buffers[index] != NULL && delProtect[index] == false)
		delete buffers[index];
	delProtect[index] = true;
	buffers[index] = &buf;
	cl_int err = kernel.setArg(index,buf);
	if(err != CL_SUCCESS)
	{
		cout << "Error set argumant to kernel , code " << err << endl;
		return err;
	}
	return err;
}

cl_int Kernel::enqueueNDRange(cl::NDRange offset, cl::NDRange global, cl::NDRange local)
{
	cl_int err = 0;
	cl::Event event;
	err = software.device->commandQueue.enqueueNDRangeKernel(kernel,offset,global,local,NULL,&event);
	if(err != CL_SUCCESS)
	{
		cout << "Error enqueuing NDRange Kernel, code " << err << endl;
		return err;
	}
	event.wait();
	return err;
}

cl_int Kernel::enqueueTask()
{
	cl_int err = 0;
	cl::Event event;
	err = software.device->commandQueue.enqueueTask(kernel,NULL,&event);
	if(err != CL_SUCCESS)
	{
		cout << "Error enqueuing Task, code " << err << endl;
		return err;
	}
	event.wait();
	return err;
}

cl_int Kernel::enqueueSPMD()
{
	cl_int err = 0;
	int preferWorkSizeBase =
		kernel.getWorkGroupInfo<CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE>
		(software.device->device);
	int maxComputeUnit = software.device->device.getInfo<CL_DEVICE_MAX_COMPUTE_UNITS>();
	int spmdSize = preferWorkSizeBase*maxComputeUnit;
	cl::NDRange global(spmdSize);
	cl::NDRange local(1);
	cl::Event event;
	err = software.device->commandQueue.enqueueNDRangeKernel(kernel,cl::NullRange,global,local,NULL,&event);
	if(err != CL_SUCCESS)
	{
		cout << "Error enqueuing NDRange Kernel, code " << err << endl;
		return err;
	}
	event.wait();
	return err;

}

cl_int Kernel::readBuffer(int index, size_t size, void* ptr)
{
	cl_int err = 0;
	err = software.device->commandQueue.enqueueReadBuffer(*buffers[index],CL_TRUE, 0, size, ptr);
	if(err != CL_SUCCESS)
	{
		cout << "Error reading bufer " << index << ", code " << err << endl;
		return err;
	}
	return err;
}

//////////////////////////////////////////////////////////////////////////
//DeviceManager								//
//////////////////////////////////////////////////////////////////////////

DeviceManager::DeviceManager()
{
	vector<cl::Platform> platforms;
	cl::Platform::get(&platforms);
	int platformCount = platforms.size();

	for(int i=0;i<platformCount;i++)
	{
		cl_context_properties properties[] =
			{ CL_CONTEXT_PLATFORM, (cl_context_properties)(platforms[i])(), 0};
		cl::Context context(CL_DEVICE_TYPE_ALL, properties);
		vector<cl::Device> platformDevice = context.getInfo<CL_CONTEXT_DEVICES>();
		ComputeDeviceList deviceList;
		int deviceCount = platformDevice.size();

		for(int j=0;j<deviceCount;j++)
		{
			ComputeDevice device(platformDevice[j],context);
			deviceList.devices.push_back(device);
		}

		deviceLists.push_back(deviceList);
	}
}

ComputeDevice* DeviceManager::defaultDevice(cl_device_type deviceType)
{
	int platformCount = deviceLists.size();

	for(int i=0;i<platformCount;i++)
	{
		ComputeDevice* device = deviceLists[i].defaultDevice(deviceType);
		if(device != NULL)
			return device;
	}

	return NULL;
}

ComputeDeviceList DeviceManager::findDevice(string keyWord,cl_device_type deviceType)
{
	ComputeDeviceList list;

	int platformCount = deviceLists.size();
	for(int i=0;i<platformCount;i++)
	{
		ComputeDeviceList found = deviceLists[i].findDevice(keyWord,deviceType);
		if(found.devices.size() != 0)
			list.devices.insert(list.devices.end(), found.devices.begin(), found.devices.end());
	}
	return list;
}
<commit_msg>Improve SPMD<commit_after>#include <iostream>

#include <CL/cl.hpp>
#include <EasyCl.h>
#include <fstream>

using namespace EasyCl;
using namespace std;

//////////////////////////////////////////////////////////////////////////
//DeviceManager								//
//////////////////////////////////////////////////////////////////////////

SourceCode::SourceCode(string path)
{
	load(path);
}

SourceCode::SourceCode()
{
}

int SourceCode::load(string path)
{
	isGood = false;

	ifstream file(path);
	if(file.good() == false)
	{
		cout << "Failed to load " << path << " ." << endl;
		return 0;
	}

	string sourceCode(
            istreambuf_iterator<char>(file),
            (istreambuf_iterator<char>()));

	source = cl::Program::Sources(1, make_pair(sourceCode.c_str(), sourceCode.length()+1));
	code = sourceCode;
	isGood = true;

	return 1;
}

bool SourceCode::good()
{
	return isGood;
}

//////////////////////////////////////////////////////////////////////////
//ComputeDevice								//
//////////////////////////////////////////////////////////////////////////

ComputeDevice::ComputeDevice(cl::Device dev,cl::Context con)
{
	device = dev;
	context = con;
	commandQueue = cl::CommandQueue(context, device);
}

//////////////////////////////////////////////////////////////////////////
//ComputeDeviceList							//
//////////////////////////////////////////////////////////////////////////

bool ComputeDevice::avliable()
{
	int inQueueComunt = commandQueue.getInfo<CL_QUEUE_REFERENCE_COUNT>();
	if(inQueueComunt == 0)
		return false;
	return true;
}

ComputeDevice* ComputeDeviceList::defaultDevice(cl_device_type deviceType)
{
	if(deviceType == CL_DEVICE_TYPE_ALL)
		return &devices[0];

	int deviceCount = devices.size();
	for(int i=0;i<deviceCount;i++)
	{
		cl_device_type type = devices[i].device.getInfo<CL_DEVICE_TYPE>();
		//NOTE: I shouldn't need deviceType == CL_DEVICE_TYPE_ALL here. Just for completeness.
		if((type & deviceType) != 0 || deviceType == CL_DEVICE_TYPE_ALL)
			return &devices[i];
	}

	return NULL;
}

ComputeDeviceList ComputeDeviceList::findDevice(string keyWord,cl_device_type deviceType)
{
	int deviceCount = devices.size();
	ComputeDeviceList list;
	for(int i=0;i<deviceCount;i++)
	{
		cl_device_type type = devices[i].device.getInfo<CL_DEVICE_TYPE>();
		if((type & deviceType) || deviceType == CL_DEVICE_TYPE_ALL)
			if(devices[i].device.getInfo<CL_DEVICE_NAME>().find(keyWord) != string::npos)
				list.devices.push_back(devices[i]);
	}

	return list;
}

//////////////////////////////////////////////////////////////////////////
//ComputeDevice								//
//////////////////////////////////////////////////////////////////////////

Software::Software(ComputeDevice* dev, SourceCode sou)
{
	//cl_int err = this->errorCode;
	device = dev;
	sourceCode = sou;

	program = cl::Program(device->context, sourceCode.source,&errorCode);
	if(errorCode != CL_SUCCESS)
	{
		cout << "Error while creating Software/cl::Program , code " << errorCode << endl;
		isGood = false;
	}
	else
		isGood = true;
}

Software::Software()
{
}

Software::~Software()
{
	int size = buffers.size();
	for(int i=0;i<size;i++)
		if(buffers[i] != NULL)
			delete buffers[i];
}

cl_int Software::build(string options)
{
	//HACK: This is a nasty way to make cl::Program::build() only build for one device
	vector<cl::Device> devs;
	devs.push_back(device->device);

	cl_int result = program.build(devs,options.c_str());
	if(result != CL_SUCCESS)
	{
		cl_int err = 0;
		//NOTE 2015/5/9 : nVidia OpenCL compiler SUCKS. the error message is mostly misleading.
		//Go for AMD or Intel if possible. Really.
		cout << program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(devs[0],&err) << endl;

		cout << "Error occured while compiling OpenCL program" << endl
			<< "Error Code: " << result << endl;
		return result;
	}
	return result;
}

bool Software::good()
{
	return isGood;
}

cl_int Software::getError()
{
	return errorCode;
}

cl_int Software::createBuffer(cl_mem_flags flags, size_t size, void* ptr,int& index)
{
	int buffersListSize = buffers.size();
	int emptyIndex = -1;
	for(int i=0;i<buffersListSize;i++)
		if(buffers[i] == NULL)
		{
			emptyIndex = i;
			break;
		}

	cl_int err = 0;
	cl::Buffer* newBuffer = new cl::Buffer(device->context,flags,size,ptr,&err);
	if(err != CL_SUCCESS)
	{
		cout << "Error creating cl::Buffer , code " << err << endl;
		return err;
	}
	if(ptr != NULL)
	{
		err = device->commandQueue.enqueueWriteBuffer(*newBuffer,CL_TRUE,0,size, ptr);
		if(err != CL_SUCCESS)
		{
			cout << "Error uploading data to device , code " << err << endl;
			delete newBuffer;
			return err;
		}
	}

	if(emptyIndex >= 0)
	{
		buffers[emptyIndex] = newBuffer;
		index = emptyIndex;
	}
	else
	{
		index = buffers.size();
		buffers.push_back(newBuffer);
	}
	return err;

}

void Software::releaseBuffer(int index)
{
	delete buffers[index];
	buffers[index] = NULL;
}

//////////////////////////////////////////////////////////////////////////
//DeviceManager								//
//////////////////////////////////////////////////////////////////////////

Kernel::Kernel(Software program, string funcName)
{
	software = program;
	cl_int err = 0;

	kernel = cl::Kernel(software.program, funcName.c_str(),&err);

	if(err != CL_SUCCESS)
	{
		cout << "Error creating kernel " << funcName << ", code " << err << endl;
		return;
	}

	int argCount = kernel.getInfo<CL_KERNEL_NUM_ARGS>();
	buffers = new cl::Buffer* [argCount];
	delProtect = new bool[argCount];
	for(int i=0;i<argCount;i++)
		buffers[i] = NULL, delProtect[i] = false;
}

Kernel::~Kernel()
{
	int argCount = kernel.getInfo<CL_KERNEL_NUM_ARGS>();
	for(int i=0;i<argCount;i++)
		if(buffers[i] != NULL && delProtect[i] == false)
		{
			//cout << this << " -> " << &buffers[i] << " : " << i << endl;
			delete buffers[i];
		}
	delete [] buffers;
	delete [] delProtect;
}

cl_int Kernel::setArgBuffer(int index, cl_mem_flags flags, size_t size, void* ptr)
{
	if(buffers[index] != NULL && delProtect[index] == false)
		delete buffers[index];

	cl_int err = 0;
	buffers[index] = new cl::Buffer(software.device->context,flags,size,ptr,&err);

	if(err != CL_SUCCESS)
	{
		cout << "Error creating cl::Buffer , code " << err << endl;
		return err;
	}

	if(ptr != NULL)
	{
		cl::Event event;
		err = software.device->commandQueue.enqueueWriteBuffer(*buffers[index],CL_TRUE,0,size, ptr,NULL,&event);
		if(err != CL_SUCCESS)
		{
			cout << "Error uploading data to device , code " << err << endl;
			//delete buffers[index];
			return err;
		}
		event.wait();
	}

	err = kernel.setArg(index, *buffers[index]);
	if(err != CL_SUCCESS)
	{
		cout << "Error set argumant to kernel , code " << err << endl;
		delete buffers[index];
		return err;
	}
	delProtect[index] = false;

	return err;
}

cl_int Kernel::setArg(int index, cl::Buffer& buf)
{
	if(buffers[index] != NULL && delProtect[index] == false)
		delete buffers[index];
	delProtect[index] = true;
	buffers[index] = &buf;
	cl_int err = kernel.setArg(index,buf);
	if(err != CL_SUCCESS)
	{
		cout << "Error set argumant to kernel , code " << err << endl;
		return err;
	}
	return err;
}

cl_int Kernel::enqueueNDRange(cl::NDRange offset, cl::NDRange global, cl::NDRange local)
{
	cl_int err = 0;
	cl::Event event;
	err = software.device->commandQueue.enqueueNDRangeKernel(kernel,offset,global,local,NULL,&event);
	if(err != CL_SUCCESS)
	{
		cout << "Error enqueuing NDRange Kernel, code " << err << endl;
		return err;
	}
	event.wait();
	return err;
}

cl_int Kernel::enqueueTask()
{
	cl_int err = 0;
	cl::Event event;
	err = software.device->commandQueue.enqueueTask(kernel,NULL,&event);
	if(err != CL_SUCCESS)
	{
		cout << "Error enqueuing Task, code " << err << endl;
		return err;
	}
	event.wait();
	return err;
}

cl_int Kernel::enqueueSPMD()
{
	cl_int err = 0;
	int preferWorkSizeBase =
		kernel.getWorkGroupInfo<CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE>
		(software.device->device);
	int maxComputeUnit = software.device->device.getInfo<CL_DEVICE_MAX_COMPUTE_UNITS>();
	int spmdSize = preferWorkSizeBase*maxComputeUnit;
	cl::NDRange global(spmdSize);
	cl::NDRange local(maxComputeUnit);
	//cout << "Base = " << preferWorkSizeBase << " CU = " << maxComputeUnit << endl;
	cl::Event event;
	err = software.device->commandQueue.enqueueNDRangeKernel(kernel,cl::NullRange,global,local,NULL,&event);
	if(err != CL_SUCCESS)
	{
		cout << "Error enqueuing NDRange Kernel, code " << err << endl;
		return err;
	}
	event.wait();
	return err;

}

cl_int Kernel::readBuffer(int index, size_t size, void* ptr)
{
	cl_int err = 0;
	err = software.device->commandQueue.enqueueReadBuffer(*buffers[index],CL_TRUE, 0, size, ptr);
	if(err != CL_SUCCESS)
	{
		cout << "Error reading bufer " << index << ", code " << err << endl;
		return err;
	}
	return err;
}

//////////////////////////////////////////////////////////////////////////
//DeviceManager								//
//////////////////////////////////////////////////////////////////////////

DeviceManager::DeviceManager()
{
	vector<cl::Platform> platforms;
	cl::Platform::get(&platforms);
	int platformCount = platforms.size();

	for(int i=0;i<platformCount;i++)
	{
		cl_context_properties properties[] =
			{ CL_CONTEXT_PLATFORM, (cl_context_properties)(platforms[i])(), 0};
		cl::Context context(CL_DEVICE_TYPE_ALL, properties);
		vector<cl::Device> platformDevice = context.getInfo<CL_CONTEXT_DEVICES>();
		ComputeDeviceList deviceList;
		int deviceCount = platformDevice.size();

		for(int j=0;j<deviceCount;j++)
		{
			ComputeDevice device(platformDevice[j],context);
			deviceList.devices.push_back(device);
		}

		deviceLists.push_back(deviceList);
	}
}

ComputeDevice* DeviceManager::defaultDevice(cl_device_type deviceType)
{
	int platformCount = deviceLists.size();

	for(int i=0;i<platformCount;i++)
	{
		ComputeDevice* device = deviceLists[i].defaultDevice(deviceType);
		if(device != NULL)
			return device;
	}

	return NULL;
}

ComputeDeviceList DeviceManager::findDevice(string keyWord,cl_device_type deviceType)
{
	ComputeDeviceList list;

	int platformCount = deviceLists.size();
	for(int i=0;i<platformCount;i++)
	{
		ComputeDeviceList found = deviceLists[i].findDevice(keyWord,deviceType);
		if(found.devices.size() != 0)
			list.devices.insert(list.devices.end(), found.devices.begin(), found.devices.end());
	}
	return list;
}
<|endoftext|>


<commit_before>#ifndef REPEAT_HPP
#define REPEAT_HPP

#include <iostream>
#include <iterator_range.hpp>
#include <iterator>

namespace iter {
    template <typename Elem>
        struct repeat_iter {
            const Elem elem;
            size_t until;
            size_t start=0;
            repeat_iter(const Elem & elem,
                    size_t until) :
                elem(elem),
                until(until) {}
            repeat_iter & operator++() {
                if (until != 0) ++start; //no point in repeating 0 times
                //so use that to repeat infinitely
                return *this;
            }
            bool operator!=(const repeat_iter &) {
                if (until == 0) return true;
                else if (start != until) return true;
                else return false;
            }
            Elem operator*()
            {
                return elem;
            }
        };
    template <typename Elem>
        iterator_range<repeat_iter<Elem>> repeat(
                const Elem & elem,
                size_t until=0)
        //-1 causes it to repeat infintely
        {
            return iterator_range<repeat_iter<Elem>>(
                    repeat_iter<Elem>(elem,until),
                    repeat_iter<Elem>(elem,until));//just a dummy iter
        }

}

#endif //REPEAT_HPP
<commit_msg>Various touchups to repeat<commit_after>#ifndef REPEAT_HPP
#define REPEAT_HPP

#include <iterator_range.hpp>

#include <iterator>

namespace iter {
    template <typename Elem>
    class repeat_iter {
        private:
            const Elem elem;
            size_t until;
            size_t start=0;
        public:
            repeat_iter(const Elem & elem, size_t until) :
                elem(elem),
                until(until)
            { }

            repeat_iter & operator++() {
                if (this->until != 0) ++start; //no point in repeating 0 times
                //so use that to repeat infinitely
                return *this;
            }

            bool operator!=(const repeat_iter &) const {
                return this->until == 0 || this->start != this->until;
            }

            Elem operator*() const {
                return this->elem;
            }
    };

    //-1 causes it to repeat infintely
    template <typename Elem>
    iterator_range<repeat_iter<Elem>> repeat(
            const Elem & elem,
            size_t until=0)
    {
        return iterator_range<repeat_iter<Elem>>(
                repeat_iter<Elem>(elem, until),
                repeat_iter<Elem>(elem, until));//just a dummy iter
    }

}

#endif //REPEAT_HPP
<|endoftext|>


<commit_before>/*
  Copyright (C) 2011 Christian Van Brussel, Institute of Information
      and Communication Technologies, Electronics and Applied Mathematics
      at Universite catholique de Louvain, Belgium
      http://www.uclouvain.be/en-icteam.html

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Library General Public
  License as published by the Free Software Foundation; either
  version 2 of the License, or (at your option) any later version.

  This library 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
  Library General Public License for more details.

  You should have received a copy of the GNU Library General Public
  License along with this library; if not, write to the Free
  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "cssysdef.h"

#include "imap/services.h"
#include "imesh/animesh.h"
#include "iutil/document.h"
#include "iutil/vfs.h"
#include "cstool/animeshtools.h"
#include "csutil/scf.h"
#include "csutil/stringquote.h"

#include "splitmorph.h"

CS_PLUGIN_NAMESPACE_BEGIN (SplitMorph)
{
  SCF_IMPLEMENT_FACTORY (SplitMorphLoader);

  SplitMorphLoader::SplitMorphLoader (iBase* parent)
    : scfImplementationType (this, parent)
  {}

  static const char* msgidFactory = "crystalspace.mesh.loader.factory.animesh.splitmorph";

  bool SplitMorphLoader::Initialize (iObjectRegistry* registry)
  {
    this->registry = registry;
    synldr = csQueryRegistry<iSyntaxService> (registry);
    InitTokenTable (xmltokens);

    return true;
  }

  csPtr<iBase> SplitMorphLoader::Parse (iDocumentNode* node,
					iStreamSource* ssource,
					iLoaderContext* ldr_context,
					iBase* context)
  {
    csString path, realPath, file, name, mask;

    csRef<iDocumentNodeIterator> it = node->GetNodes ();
    while (it->HasNext ())
    {
      csRef<iDocumentNode> child = it->Next ();
      if (child->GetType () != CS_NODE_ELEMENT) continue;
      const char* value = child->GetValue ();
      csStringID id = xmltokens.Request (value);
      switch (id)
      {
      case XMLTOKEN_VFSPATH:
	path = child->GetContentsValue ();
	break;

      case XMLTOKEN_REALPATH:
	realPath = child->GetContentsValue ();
	break;

      case XMLTOKEN_BASEFILE:
	file = child->GetContentsValue ();
	break;

      case XMLTOKEN_MESHNAME:
	name = child->GetContentsValue ();
	break;

      case XMLTOKEN_MASK:
	mask = child->GetContentsValue ();
	break;

      default:
        synldr->ReportBadToken (child);
        return csPtr<iBase> (nullptr);
      }
    }

    // Check that the parameters are invalid
    if (file.IsEmpty ())
    {
      synldr->ReportError (msgidFactory, node, "No base file provided!");
      return csPtr<iBase> (nullptr);
    }

    // If no name is provided then use the one from the mesh wrapper
    if (name.IsEmpty ())
    {
      if (node->GetParent ())
	name = node->GetParent ()->GetAttributeValue ("name");
      else name = "splitmorph";
    }

    // Check for a temporary path to be mounted
    if (!realPath.IsEmpty ())
    {
      csRef<iVFS> vfs =  csQueryRegistry<iVFS> (registry);
      if (!vfs->Mount ("/tmp/splitmorph", realPath))
      {
	synldr->ReportError (msgidFactory, node, "Could not mount real path %s!",
			     CS::Quote::Single (realPath));
	return csPtr<iBase> (nullptr);
      }

      path = "/tmp/splitmorph/";
    }

    // Import the animesh
    csRef<CS::Mesh::iAnimatedMeshFactory> meshFactory =
      CS::Mesh::AnimatedMeshTools::ImportSplitMorphMesh (registry, path, file, name, mask);
    if (!meshFactory)
      return csPtr<iBase> (nullptr);

    // Unmount the temporary path
    if (!realPath.IsEmpty ())
    {
      csRef<iVFS> vfs =  csQueryRegistry<iVFS> (registry);
      vfs->Unmount ("/tmp/splitmorph", nullptr);
    }

    return scfQueryInterface<iBase> (meshFactory);
  }

}
CS_PLUGIN_NAMESPACE_END (SplitMorph)
<commit_msg>Fixed memory leak<commit_after>/*
  Copyright (C) 2011 Christian Van Brussel, Institute of Information
      and Communication Technologies, Electronics and Applied Mathematics
      at Universite catholique de Louvain, Belgium
      http://www.uclouvain.be/en-icteam.html

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Library General Public
  License as published by the Free Software Foundation; either
  version 2 of the License, or (at your option) any later version.

  This library 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
  Library General Public License for more details.

  You should have received a copy of the GNU Library General Public
  License along with this library; if not, write to the Free
  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "cssysdef.h"

#include "imap/services.h"
#include "imesh/animesh.h"
#include "iutil/document.h"
#include "iutil/vfs.h"
#include "cstool/animeshtools.h"
#include "csutil/scf.h"
#include "csutil/stringquote.h"

#include "splitmorph.h"

CS_PLUGIN_NAMESPACE_BEGIN (SplitMorph)
{
  SCF_IMPLEMENT_FACTORY (SplitMorphLoader);

  SplitMorphLoader::SplitMorphLoader (iBase* parent)
    : scfImplementationType (this, parent)
  {}

  static const char* msgidFactory = "crystalspace.mesh.loader.factory.animesh.splitmorph";

  bool SplitMorphLoader::Initialize (iObjectRegistry* registry)
  {
    this->registry = registry;
    synldr = csQueryRegistry<iSyntaxService> (registry);
    InitTokenTable (xmltokens);

    return true;
  }

  csPtr<iBase> SplitMorphLoader::Parse (iDocumentNode* node,
					iStreamSource* ssource,
					iLoaderContext* ldr_context,
					iBase* context)
  {
    csString path, realPath, file, name, mask;

    csRef<iDocumentNodeIterator> it = node->GetNodes ();
    while (it->HasNext ())
    {
      csRef<iDocumentNode> child = it->Next ();
      if (child->GetType () != CS_NODE_ELEMENT) continue;
      const char* value = child->GetValue ();
      csStringID id = xmltokens.Request (value);
      switch (id)
      {
      case XMLTOKEN_VFSPATH:
	path = child->GetContentsValue ();
	break;

      case XMLTOKEN_REALPATH:
	realPath = child->GetContentsValue ();
	break;

      case XMLTOKEN_BASEFILE:
	file = child->GetContentsValue ();
	break;

      case XMLTOKEN_MESHNAME:
	name = child->GetContentsValue ();
	break;

      case XMLTOKEN_MASK:
	mask = child->GetContentsValue ();
	break;

      default:
        synldr->ReportBadToken (child);
        return csPtr<iBase> (nullptr);
      }
    }

    // Check that the parameters are invalid
    if (file.IsEmpty ())
    {
      synldr->ReportError (msgidFactory, node, "No base file provided!");
      return csPtr<iBase> (nullptr);
    }

    // If no name is provided then use the one from the mesh wrapper
    if (name.IsEmpty ())
    {
      if (node->GetParent ())
	name = node->GetParent ()->GetAttributeValue ("name");
      else name = "splitmorph";
    }

    // Check for a temporary path to be mounted
    if (!realPath.IsEmpty ())
    {
      csRef<iVFS> vfs =  csQueryRegistry<iVFS> (registry);
      if (!vfs->Mount ("/tmp/splitmorph", realPath))
      {
	synldr->ReportError (msgidFactory, node, "Could not mount real path %s!",
			     CS::Quote::Single (realPath));
	return csPtr<iBase> (nullptr);
      }

      path = "/tmp/splitmorph/";
    }

    // Import the animesh
    csRef<CS::Mesh::iAnimatedMeshFactory> meshFactory =
      CS::Mesh::AnimatedMeshTools::ImportSplitMorphMesh (registry, path, file, name, mask);
    if (!meshFactory)
      return csPtr<iBase> (nullptr);

    // Unmount the temporary path
    if (!realPath.IsEmpty ())
    {
      csRef<iVFS> vfs =  csQueryRegistry<iVFS> (registry);
      vfs->Unmount ("/tmp/splitmorph", nullptr);
    }

    return csPtr<iBase> (scfQueryInterface<iBase> (meshFactory));
  }

}
CS_PLUGIN_NAMESPACE_END (SplitMorph)
<|endoftext|>


<commit_before>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  You may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
/*
 * Copyright (C) 2014 Cloudius Systems, Ltd.
 */

#ifndef STREAM_HH_
#define STREAM_HH_

#include "future.hh"
#include <exception>
#include <cassert>

// A stream/subscription pair is similar to a promise/future pair,
// but apply to a sequence of values instead of a single value.
//
// A stream<> is the producer side.  It may call produce() as long
// as the future<> returned from the previous invocation is ready.
// To signify no more data is available, call close().
//
// A subscription<> is the consumer side.  It is created by a call
// to stream::listen().  Calling subscription::start(),
// which registers the data processing callback, starts processing
// events.  It may register for end-of-stream notifications by
// chaining the when_done() future, which also delivers error
// events (as exceptions).
//
// The consumer can pause generation of new data by returning
// a non-ready future; when the future becomes ready, the producer
// will resume processing.

template <typename... T>
class stream;

template <typename... T>
class subscription;

template <typename... T>
class stream {
    subscription<T...>* _sub = nullptr;
    promise<> _done;
    promise<> _ready;
public:
    using next_fn = std::function<future<> (T...)>;
    stream() = default;
    stream(const stream&) = delete;
    stream(stream&&) = delete;
    ~stream();
    void operator=(const stream&) = delete;
    void operator=(stream&&) = delete;

    // Returns a subscription that reads value from this
    // stream.
    subscription<T...> listen();

    // Returns a subscription that reads value from this
    // stream, and also sets up the listen function.
    subscription<T...> listen(next_fn next);

    // Becomes ready when the listener is ready to accept
    // values.  Call only once, when beginning to produce
    // values.
    future<> started();

    // Produce a value.  Call only after started(), and after
    // a previous produce() is ready.
    future<> produce(T... data);

    // End the stream.   Call only after started(), and after
    // a previous produce() is ready.  No functions may be called
    // after this.
    void close();

    // Signal an error.   Call only after started(), and after
    // a previous produce() is ready.  No functions may be called
    // after this.
    template <typename E>
    void set_exception(E ex);
private:
    void pause(future<> can_continue);
    void start();
    friend class subscription<T...>;
};

template <typename... T>
class subscription {
public:
    using next_fn = typename stream<T...>::next_fn;
private:
    stream<T...>* _stream;
    next_fn _next;
private:
    explicit subscription(stream<T...>* s);
public:
    subscription(subscription&& x);
    ~subscription();

    /// \brief Start receiving events from the stream.
    ///
    /// \param next Callback to call for each event
    void start(std::function<future<> (T...)> next);

    // Becomes ready when the stream is empty, or when an error
    // happens (in that case, an exception is held).
    future<> done();

    friend class stream<T...>;
};

template <typename... T>
inline
stream<T...>::~stream() {
    if (_sub) {
        _sub->_stream = nullptr;
    }
}

template <typename... T>
inline
subscription<T...>
stream<T...>::listen() {
    return subscription<T...>(this);
}

template <typename... T>
inline
subscription<T...>
stream<T...>::listen(next_fn next) {
    auto sub = subscription<T...>(this);
    sub.start(std::move(next));
    return sub;
}

template <typename... T>
inline
future<>
stream<T...>::started() {
    return _ready.get_future();
}

template <typename... T>
inline
future<>
stream<T...>::produce(T... data) {
    return _sub->_next(std::move(data)...).then_wrapped([this] (future<> f) {
        try {
            f.get();
        } catch (...) {
            _done.set_exception(std::current_exception());
            // FIXME: tell the producer to stop producing
            abort();
        }
    });
}

template <typename... T>
inline
void
stream<T...>::close() {
    _done.set_value();
}

template <typename... T>
template <typename E>
inline
void
stream<T...>::set_exception(E ex) {
    _sub->_done.set_exception(ex);
}

template <typename... T>
inline
subscription<T...>::subscription(stream<T...>* s)
        : _stream(s) {
    assert(!_stream->_sub);
    _stream->_sub = this;
}

template <typename... T>
inline
void
subscription<T...>::start(std::function<future<> (T...)> next) {
    _next = std::move(next);
    _stream->_ready.set_value();
}

template <typename... T>
inline
subscription<T...>::~subscription() {
    if (_stream) {
        _stream->_sub = nullptr;
    }
}

template <typename... T>
inline
subscription<T...>::subscription(subscription&& x)
    : _stream(x._stream), _next(std::move(x._next)) {
    x._stream = nullptr;
    if (_stream) {
        _stream->_sub = this;
    }
}

template <typename... T>
inline
future<>
subscription<T...>::done() {
    return _stream->_done.get_future();
}

#endif /* STREAM_HH_ */
<commit_msg>stream: use a smaller stick for failed producers<commit_after>/*
 * This file is open source software, licensed to you under the terms
 * of the Apache License, Version 2.0 (the "License").  See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership.  You may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
/*
 * Copyright (C) 2014 Cloudius Systems, Ltd.
 */

#ifndef STREAM_HH_
#define STREAM_HH_

#include "future.hh"
#include <exception>
#include <cassert>

// A stream/subscription pair is similar to a promise/future pair,
// but apply to a sequence of values instead of a single value.
//
// A stream<> is the producer side.  It may call produce() as long
// as the future<> returned from the previous invocation is ready.
// To signify no more data is available, call close().
//
// A subscription<> is the consumer side.  It is created by a call
// to stream::listen().  Calling subscription::start(),
// which registers the data processing callback, starts processing
// events.  It may register for end-of-stream notifications by
// chaining the when_done() future, which also delivers error
// events (as exceptions).
//
// The consumer can pause generation of new data by returning
// a non-ready future; when the future becomes ready, the producer
// will resume processing.

template <typename... T>
class stream;

template <typename... T>
class subscription;

template <typename... T>
class stream {
    subscription<T...>* _sub = nullptr;
    promise<> _done;
    promise<> _ready;
public:
    using next_fn = std::function<future<> (T...)>;
    stream() = default;
    stream(const stream&) = delete;
    stream(stream&&) = delete;
    ~stream();
    void operator=(const stream&) = delete;
    void operator=(stream&&) = delete;

    // Returns a subscription that reads value from this
    // stream.
    subscription<T...> listen();

    // Returns a subscription that reads value from this
    // stream, and also sets up the listen function.
    subscription<T...> listen(next_fn next);

    // Becomes ready when the listener is ready to accept
    // values.  Call only once, when beginning to produce
    // values.
    future<> started();

    // Produce a value.  Call only after started(), and after
    // a previous produce() is ready.
    future<> produce(T... data);

    // End the stream.   Call only after started(), and after
    // a previous produce() is ready.  No functions may be called
    // after this.
    void close();

    // Signal an error.   Call only after started(), and after
    // a previous produce() is ready.  No functions may be called
    // after this.
    template <typename E>
    void set_exception(E ex);
private:
    void pause(future<> can_continue);
    void start();
    friend class subscription<T...>;
};

template <typename... T>
class subscription {
public:
    using next_fn = typename stream<T...>::next_fn;
private:
    stream<T...>* _stream;
    next_fn _next;
private:
    explicit subscription(stream<T...>* s);
public:
    subscription(subscription&& x);
    ~subscription();

    /// \brief Start receiving events from the stream.
    ///
    /// \param next Callback to call for each event
    void start(std::function<future<> (T...)> next);

    // Becomes ready when the stream is empty, or when an error
    // happens (in that case, an exception is held).
    future<> done();

    friend class stream<T...>;
};

template <typename... T>
inline
stream<T...>::~stream() {
    if (_sub) {
        _sub->_stream = nullptr;
    }
}

template <typename... T>
inline
subscription<T...>
stream<T...>::listen() {
    return subscription<T...>(this);
}

template <typename... T>
inline
subscription<T...>
stream<T...>::listen(next_fn next) {
    auto sub = subscription<T...>(this);
    sub.start(std::move(next));
    return sub;
}

template <typename... T>
inline
future<>
stream<T...>::started() {
    return _ready.get_future();
}

template <typename... T>
inline
future<>
stream<T...>::produce(T... data) {
    return _sub->_next(std::move(data)...).then_wrapped([this] (future<> f) {
        try {
            f.get();
        } catch (...) {
            _done.set_exception(std::current_exception());
            // FIXME: tell the producer to stop producing
            throw;
        }
    });
}

template <typename... T>
inline
void
stream<T...>::close() {
    _done.set_value();
}

template <typename... T>
template <typename E>
inline
void
stream<T...>::set_exception(E ex) {
    _sub->_done.set_exception(ex);
}

template <typename... T>
inline
subscription<T...>::subscription(stream<T...>* s)
        : _stream(s) {
    assert(!_stream->_sub);
    _stream->_sub = this;
}

template <typename... T>
inline
void
subscription<T...>::start(std::function<future<> (T...)> next) {
    _next = std::move(next);
    _stream->_ready.set_value();
}

template <typename... T>
inline
subscription<T...>::~subscription() {
    if (_stream) {
        _stream->_sub = nullptr;
    }
}

template <typename... T>
inline
subscription<T...>::subscription(subscription&& x)
    : _stream(x._stream), _next(std::move(x._next)) {
    x._stream = nullptr;
    if (_stream) {
        _stream->_sub = this;
    }
}

template <typename... T>
inline
future<>
subscription<T...>::done() {
    return _stream->_done.get_future();
}

#endif /* STREAM_HH_ */
<|endoftext|>


<commit_before>//
// This file is a part of pomerol - a scientific ED code for obtaining
// properties of a Hubbard model on a finite-size lattice
//
// Copyright (C) 2010-2013 Andrey Antipov <antipov@ct-qmc.org>
// Copyright (C) 2010-2013 Igor Krivenko <igor@shg.ru>
//
// pomerol 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.
//
// pomerol 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 pomerol.  If not, see <http://www.gnu.org/licenses/>.

/** \file examples/example01.cpp
** \brief An example of how to use the pomerol library.
**
** \author Andrey Antipov (Andrey.E.Antipov@gmail.com)
*/

/* In this file we provide a tutorial example of how to actually use the
 * pomerol library.
 */

// Include the pomerol library
#include <pomerol.h>

// Use the namespace of Pomerol. Otherwise Pomerol::{name}
// calling of the objects would be required
using namespace Pomerol;

boost::mpi::communicator world;
// Small routine to make fancy screen output for text.
void print_section (const std::string& str);

/* Generic tips:
 * The calculation is done by computing a set of objects in the following order:
 * Lattice -> IndexClassification -> IndexHamiltonian -> Symmetrizer ->
 * -> StatesClassification -> Hamiltonian -> FieldOperator
 ;
 * (for thermal objects, such as GFs in Matsubara domain)
 * -> DensityMatrix -> Greens Function
 *                  -> TwoParticle GF   -> Vertex4
 * The detailed explanation of each class is given below.
 */

int main(int argc, char* argv[])
{
    boost::mpi::environment MpiEnv(argc, argv);
    world = boost::mpi::communicator();

    /* As pomerol is an ED code, it requires a finite-size lattice to be
     * provided. Here is an example of a lattice of 2 sites. */
    // First, we construct an empty lattice
    Lattice L;
    // Add a site with a name "A", that has 1 orbitals and 2 spins.
    L.addSite(new Lattice::Site("A",1,2));
    // Add one more site with a name "B". It also has 1 orbitals and 2 spins.
    L.addSite(new Lattice::Site("B",1,2));

    // Let us now connect two sites with a hopping term, with matrix element -1.
    RealType t=1.0;
    LatticePresets::addHopping(&L, "A","B", -t);

    /* Now add interaction. In order to provide some custom interaction, one can
     * give any custom term of 4,6 operators. This is done via
     * Lattice.addTerm(Lattice::Term) method.
     * We will use Hubbard-type n_{up}n_{down} interaction. For this and some
     * other typical interactions, such as SzSz or SS couplings a shortcut is
     * provided in the LatticePresets class.
     */
    RealType U = 2.0;
    RealType mu = 1.0;
    // LatticePresets::addCoulombS adds Un_{up}n_{down} for 1 orbital and 2 spins.
    LatticePresets::addCoulombS(&L, "A", U, -mu);
    LatticePresets::addCoulombS(&L, "B", U, -mu);

    // Let us now print which sites and terms are defined.
    if (!world.rank()) {
        INFO("Sites"); // equivalent to std::cout << "Sites" << std::endl;
        L.printSites();
        INFO("Terms");
        L.printTerms(2);
        INFO("Terms with 4 operators");
        L.printTerms(4);

        print_section("Indices");
    };
    /* In order to go further, we need to introduce the index space. An index
     * is a number that uniquely identifies a combination of (site,orbital,spin).
     * The object that takes care of handling indices is called
     * IndexClassification.
     */

    // Construct IndexClassification
    IndexClassification IndexInfo(L.getSiteMap());

    /* Important remark 1!
     * Most of the objects that are defined within Pomerol library have the
     * following semantics. They can be constructed, prepared and computed.
     * This means
     *   - constructed: No operations are done except from initializing links to
     *                  other objects that current class depends on.
     *   - prepared: Typically, this is when all memory allocation takes place.
     *   - computed: The actual computation. This is the most costly operation.
     *               When no heavy computation is done, it can be done during
     *               preparation stage.
     */

    // IndexClassification does not require much computing time, so everything
    // is calculated during prepare() method.
    IndexInfo.prepare();

    // Print which indices we have
    IndexInfo.printIndices();
    // Save the total number of indices.
    ParticleIndex IndexSize = IndexInfo.getIndexSize();

    print_section("Matrix element storage");
    /* We now need to construct the actual Hamiltonian. First, we need to create
     * it in the index space, e.g. write down a formula with all terms. It is
     * useful for a subsequent symmetry analysis. The corresponding class is called
     * an IndexHamiltonian. It is inherited from Operator class, which is designed
     * to represent a generic second-quantized fermionic operator and fully model
     * the algebra of fermionic operators. This means one can multiply, add,
     * subtract it, and also calculate the commutator of two operators, etc.
     */

    // First construct the IndexHamiltonian object.
    IndexHamiltonian Storage(&L,IndexInfo);
    // Then prepare it. As previously no long computation required, so everything
    // is done in the prepare() method.
    Storage.prepare();
    // Print out the Hamiltonian.
    INFO("Terms");
    INFO(Storage);

    // Let us make a test, that our Hamiltonian commutes with an operator, that
    // represents the total number of particles. The preset for such operator is
    // defined in OperatorPresets.h and .cpp files.
    OperatorPresets::N N(IndexSize);
    INFO("N terms");
    N.printAllTerms();
    if ((Storage.commutes(N))) INFO("H commutes with N");

    /* The Hamiltonian that is set now, has a set of symmetries. One can identify
     * them by checking that the IndexHamiltonian commutes with the corresponding
     * symmetry operator. The class that does it is called Symmetrizer.
     */
    // Construct Symmetrizer
    Symmetrizer Symm(IndexInfo, Storage);
    /* At this stage Symmetrizer checks symmetries with some predefined operators,
     * such as number-of-particles and sz operators.
     */
    Symm.compute();
    /* A custom check for a symmetry can be done using
     * Symmetrizer.checkSymmetry(Operator).
     * After checking all the symmetry operations, Symmetrizer defines a set of
     * quantum numbers, which uniquely identifies the closed region in the
     * phase space.
     * Calling Symmetrizer::compute(true) will skip all symmetry operations and
     * result in a single Hamiltonian block in the end.
     */

    /* We shall proceed now with obtaining the spectrum of the Hamiltonian.
     * First, introduce a basis of Fock states and classify them into blocks
     * that correspond to a set of quantum numbers. This is done in the
     * StatesClassification class. It provides all the information about Blocks
     * and FockStates.
     */
    StatesClassification S(IndexInfo,Symm);
    S.compute();

    /* We now convert the IndexHamiltonian into the basis of Fock States. The
     * Hamiltonian class is the one, which does it.
     */
    Hamiltonian H(IndexInfo, Storage, S);
    // Enter all blocks of the Hamiltonian.
    H.prepare();
    // Diagonalize them.
    H.compute(world);
    // Get ground energy.
    INFO("The value of ground energy is " << H.getGroundEnergy());

    /* Important remark 2!
     * All the calculations done in the pomerol code are done with respect to the
     * block structure of the Hamiltonian. All objects that operate in Fock
     * space and all thermal objects, such as Green's functions are in fact a
     * set of pieces (called "parts") that operate on a certain block or set of
     * blocks. As such all actual computations are done within this parts and
     * grand objects like Green's functions or Hamiltonian basically just loops
     * over parts and tells them to run prepare() or compute() methods.
     */

    /* At this stage the Hamiltonian, defined in Fock Space is
     * entered and diagonalized and it's spectrum and eigenfunctions can be
     * directly accessed to calculate some observables.
     *
     * We shall now proceed to the calculations of thermal quantities, e.g.
     * assume that our finite-size system was adiabatically connected to a thermal
     * reservoir, that sets certain temperature (in fact, inverse temperature
     * beta). This means, that the observables in the systems should be calculated
     * with a density-matrix exp(-\beta H), rather than by averaging with the
     * ground state. In the eigenbasis of the Hamiltonian the calculation of
     * a density matrix is straightforward - it is just \exp(-\beta (E_i - E_0)),
     * where E_i is an energy of the excited state, and E_0 is the ground energy.
     * The procedure is done as following:
     */

    // Define inverse temperature
    RealType beta = 10.0;

    // Create the Density Matrix.
    DensityMatrix rho(S,H,beta);
    // Allocate all internal parts of density matrix.
    rho.prepare();
    // Actually compute the density matrix.
    rho.compute();
    // Truncate blocks that have only small contributions
    // rho.truncateBlocks(1e-15);

    /* Lehmanns representation of the Green's function required creation and
     * annihilation operators, calculated in the basis of eigenstates of the
     * Hamiltonian. Creation/AnnihilationOperator are the classes that do it.
     */

    // Let us create c^+_{"A",up} and c_{"A",up}
    ParticleIndex up_index = IndexInfo.getIndex("A",0,up);
    CreationOperator CX(IndexInfo,S,H,up_index);
    CX.prepare();
    CX.compute();
    AnnihilationOperator C(IndexInfo,S,H,up_index);
    C.prepare();
    C.compute();

    // The local Greens function in the Matsubara domain G_{"A",up}(i\omega_n)
    GreensFunction GF(S,H,C,CX, rho);
    GF.prepare();
    /* Calculate the GF and cache values for 10 Matsubaras.
     * These values will be fast to retrieve. The other values are also
     * accessible, but will require a short calculation to be done.
     */
    GF.compute();

    for(int n = 0; n<10; ++n) {
        INFO(n << " | " << GF(n));
        }

    /* The two particle GF is constructed in analogy to the single-particle GF,
     * it requires 4 operators to be provided though.
     */
    TwoParticleGF Chi(S,H,C,C,CX,CX,rho);
    /* Some knobs to make calc faster - the larger the values of tolerances, the faster is calc, but rounding errors may show.
       Typically these errors are less then 10^{-3} of the value.
       Here are some knobs that give very high-precision. If you want to make things faster, and when many values on
       different frequencies required - change ReduceResonanceTolerance to something like 10^-4. */
    /** A difference in energies with magnitude less than this value is treated as zero. */
    Chi.ReduceResonanceTolerance = 1e-8;
    /** Minimal magnitude of the coefficient of a term to take it into account. */
    Chi.CoefficientTolerance = 1e-16;
    /** Minimal magnitude of the coefficient of a term to take it into account with respect to amount of terms. */
    Chi.MultiTermCoefficientTolerance = 1e-6;

    Chi.prepare();
    std::vector<boost::tuple<ComplexType, ComplexType, ComplexType> > freqs_2pgf;
    Chi.compute(false, freqs_2pgf, world);

    if (world.rank()==0) {
    int nm = 2;
    for(int n1 = -nm; n1<nm; ++n1)
        for(int n2 = -nm; n2<nm; ++n2)
            for(int n3 = -nm; n3<nm; ++n3){
                INFO(n1 << " " << n2 << " " << n3 << "|" << Chi(n1,n2,n3));
                };
    };
}

void print_section (const std::string& str)
{
  if (!world.rank()) {
  std::cout << std::string(str.size(),'=') << std::endl;
  std::cout << str << std::endl;
  std::cout << std::string(str.size(),'=') << std::endl;
    };
}
<commit_msg>Update tutorial to add susceptibility and ensemble average<commit_after>//
// This file is a part of pomerol - a scientific ED code for obtaining
// properties of a Hubbard model on a finite-size lattice
//
// Copyright (C) 2010-2013 Andrey Antipov <antipov@ct-qmc.org>
// Copyright (C) 2010-2013 Igor Krivenko <igor@shg.ru>
//
// pomerol 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.
//
// pomerol 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 pomerol.  If not, see <http://www.gnu.org/licenses/>.

/** \file examples/example01.cpp
** \brief An example of how to use the pomerol library.
**
** \author Andrey Antipov (Andrey.E.Antipov@gmail.com)
*/

/* In this file we provide a tutorial example of how to actually use the
 * pomerol library.
 */

// Include the pomerol library
#include <pomerol.h>

// Use the namespace of Pomerol. Otherwise Pomerol::{name}
// calling of the objects would be required
using namespace Pomerol;

boost::mpi::communicator world;
// Small routine to make fancy screen output for text.
void print_section (const std::string& str);

/* Generic tips:
 * The calculation is done by computing a set of objects in the following order:
 * Lattice -> IndexClassification -> IndexHamiltonian -> Symmetrizer ->
 * -> StatesClassification -> Hamiltonian -> FieldOperator
 ;
 * (for thermal objects, such as GFs in Matsubara domain)
 * -> DensityMatrix -> Greens Function
 *                  -> TwoParticle GF   -> Vertex4
 * The detailed explanation of each class is given below.
 */

int main(int argc, char* argv[])
{
    boost::mpi::environment MpiEnv(argc, argv);
    world = boost::mpi::communicator();

    /* As pomerol is an ED code, it requires a finite-size lattice to be
     * provided. Here is an example of a lattice of 2 sites. */
    // First, we construct an empty lattice
    Lattice L;
    // Add a site with a name "A", that has 1 orbitals and 2 spins.
    L.addSite(new Lattice::Site("A",1,2));
    // Add one more site with a name "B". It also has 1 orbitals and 2 spins.
    L.addSite(new Lattice::Site("B",1,2));

    // Let us now connect two sites with a hopping term, with matrix element -1.
    RealType t=1.0;
    LatticePresets::addHopping(&L, "A","B", -t);

    /* Now add interaction. In order to provide some custom interaction, one can
     * give any custom term of 4,6 operators. This is done via
     * Lattice.addTerm(Lattice::Term) method.
     * We will use Hubbard-type n_{up}n_{down} interaction. For this and some
     * other typical interactions, such as SzSz or SS couplings a shortcut is
     * provided in the LatticePresets class.
     */
    RealType U = 2.0;
    RealType mu = 1.0;
    // LatticePresets::addCoulombS adds Un_{up}n_{down} for 1 orbital and 2 spins.
    LatticePresets::addCoulombS(&L, "A", U, -mu);
    LatticePresets::addCoulombS(&L, "B", U, -mu);

    // Let us now print which sites and terms are defined.
    if (!world.rank()) {
        INFO("Sites"); // equivalent to std::cout << "Sites" << std::endl;
        L.printSites();
        INFO("Terms");
        L.printTerms(2);
        INFO("Terms with 4 operators");
        L.printTerms(4);

        print_section("Indices");
    };
    /* In order to go further, we need to introduce the index space. An index
     * is a number that uniquely identifies a combination of (site,orbital,spin).
     * The object that takes care of handling indices is called
     * IndexClassification.
     */

    // Construct IndexClassification
    IndexClassification IndexInfo(L.getSiteMap());

    /* Important remark 1!
     * Most of the objects that are defined within Pomerol library have the
     * following semantics. They can be constructed, prepared and computed.
     * This means
     *   - constructed: No operations are done except from initializing links to
     *                  other objects that current class depends on.
     *   - prepared: Typically, this is when all memory allocation takes place.
     *   - computed: The actual computation. This is the most costly operation.
     *               When no heavy computation is done, it can be done during
     *               preparation stage.
     */

    // IndexClassification does not require much computing time, so everything
    // is calculated during prepare() method.
    IndexInfo.prepare();

    // Print which indices we have
    IndexInfo.printIndices();
    // Save the total number of indices.
    ParticleIndex IndexSize = IndexInfo.getIndexSize();

    print_section("Matrix element storage");
    /* We now need to construct the actual Hamiltonian. First, we need to create
     * it in the index space, e.g. write down a formula with all terms. It is
     * useful for a subsequent symmetry analysis. The corresponding class is called
     * an IndexHamiltonian. It is inherited from Operator class, which is designed
     * to represent a generic second-quantized fermionic operator and fully model
     * the algebra of fermionic operators. This means one can multiply, add,
     * subtract it, and also calculate the commutator of two operators, etc.
     */

    // First construct the IndexHamiltonian object.
    IndexHamiltonian Storage(&L,IndexInfo);
    // Then prepare it. As previously no long computation required, so everything
    // is done in the prepare() method.
    Storage.prepare();
    // Print out the Hamiltonian.
    INFO("Terms");
    INFO(Storage);

    // Let us make a test, that our Hamiltonian commutes with an operator, that
    // represents the total number of particles. The preset for such operator is
    // defined in OperatorPresets.h and .cpp files.
    OperatorPresets::N N(IndexSize);
    INFO("N terms");
    N.printAllTerms();
    if ((Storage.commutes(N))) INFO("H commutes with N");

    /* The Hamiltonian that is set now, has a set of symmetries. One can identify
     * them by checking that the IndexHamiltonian commutes with the corresponding
     * symmetry operator. The class that does it is called Symmetrizer.
     */
    // Construct Symmetrizer
    Symmetrizer Symm(IndexInfo, Storage);
    /* At this stage Symmetrizer checks symmetries with some predefined operators,
     * such as number-of-particles and sz operators.
     */
    Symm.compute();
    /* A custom check for a symmetry can be done using
     * Symmetrizer.checkSymmetry(Operator).
     * After checking all the symmetry operations, Symmetrizer defines a set of
     * quantum numbers, which uniquely identifies the closed region in the
     * phase space.
     * Calling Symmetrizer::compute(true) will skip all symmetry operations and
     * result in a single Hamiltonian block in the end.
     */

    /* We shall proceed now with obtaining the spectrum of the Hamiltonian.
     * First, introduce a basis of Fock states and classify them into blocks
     * that correspond to a set of quantum numbers. This is done in the
     * StatesClassification class. It provides all the information about Blocks
     * and FockStates.
     */
    StatesClassification S(IndexInfo,Symm);
    S.compute();

    /* We now convert the IndexHamiltonian into the basis of Fock States. The
     * Hamiltonian class is the one, which does it.
     */
    Hamiltonian H(IndexInfo, Storage, S);
    // Enter all blocks of the Hamiltonian.
    H.prepare();
    // Diagonalize them.
    H.compute(world);
    // Get ground energy.
    INFO("The value of ground energy is " << H.getGroundEnergy());

    /* Important remark 2!
     * All the calculations done in the pomerol code are done with respect to the
     * block structure of the Hamiltonian. All objects that operate in Fock
     * space and all thermal objects, such as Green's functions are in fact a
     * set of pieces (called "parts") that operate on a certain block or set of
     * blocks. As such all actual computations are done within this parts and
     * grand objects like Green's functions or Hamiltonian basically just loops
     * over parts and tells them to run prepare() or compute() methods.
     */

    /* At this stage the Hamiltonian, defined in Fock Space is
     * entered and diagonalized and it's spectrum and eigenfunctions can be
     * directly accessed to calculate some observables.
     *
     * We shall now proceed to the calculations of thermal quantities, e.g.
     * assume that our finite-size system was adiabatically connected to a thermal
     * reservoir, that sets certain temperature (in fact, inverse temperature
     * beta). This means, that the observables in the systems should be calculated
     * with a density-matrix exp(-\beta H), rather than by averaging with the
     * ground state. In the eigenbasis of the Hamiltonian the calculation of
     * a density matrix is straightforward - it is just \exp(-\beta (E_i - E_0)),
     * where E_i is an energy of the excited state, and E_0 is the ground energy.
     * The procedure is done as following:
     */

    // Define inverse temperature
    RealType beta = 10.0;

    // Create the Density Matrix.
    DensityMatrix rho(S,H,beta);
    // Allocate all internal parts of density matrix.
    rho.prepare();
    // Actually compute the density matrix.
    rho.compute();
    // Truncate blocks that have only small contributions
    // rho.truncateBlocks(1e-15);

    /* Lehmanns representation of the Green's function required creation and
     * annihilation operators, calculated in the basis of eigenstates of the
     * Hamiltonian. Creation/AnnihilationOperator are the classes that do it.
     */

    // Let us create c^+_{"A",up} and c_{"A",up}
    ParticleIndex up_index = IndexInfo.getIndex("A",0,up);
    CreationOperator CX(IndexInfo,S,H,up_index);
    CX.prepare();
    CX.compute();
    AnnihilationOperator C(IndexInfo,S,H,up_index);
    C.prepare();
    C.compute();

    // The local Greens function in the Matsubara domain G_{"A",up}(i\omega_n)
    GreensFunction GF(S,H,C,CX, rho);
    GF.prepare();
    /* Calculate the GF and cache values for 10 Matsubaras.
     * These values will be fast to retrieve. The other values are also
     * accessible, but will require a short calculation to be done.
     */
    GF.compute();

    for(int n = 0; n<10; ++n) {
        INFO(n << " | " << GF(n));
        }

    /* The two particle GF is constructed in analogy to the single-particle GF,
     * it requires 4 operators to be provided though.
     */
    TwoParticleGF Chi(S,H,C,C,CX,CX,rho);
    /* Some knobs to make calc faster - the larger the values of tolerances, the faster is calc, but rounding errors may show.
       Typically these errors are less then 10^{-3} of the value.
       Here are some knobs that give very high-precision. If you want to make things faster, and when many values on
       different frequencies required - change ReduceResonanceTolerance to something like 10^-4. */
    /** A difference in energies with magnitude less than this value is treated as zero. */
    Chi.ReduceResonanceTolerance = 1e-8;
    /** Minimal magnitude of the coefficient of a term to take it into account. */
    Chi.CoefficientTolerance = 1e-16;
    /** Minimal magnitude of the coefficient of a term to take it into account with respect to amount of terms. */
    Chi.MultiTermCoefficientTolerance = 1e-6;

    Chi.prepare();
    std::vector<boost::tuple<ComplexType, ComplexType, ComplexType> > freqs_2pgf;
    Chi.compute(false, freqs_2pgf, world);

    if (world.rank()==0) {
    int nm = 2;
    for(int n1 = -nm; n1<nm; ++n1)
        for(int n2 = -nm; n2<nm; ++n2)
            for(int n3 = -nm; n3<nm; ++n3){
                INFO(n1 << " " << n2 << " " << n3 << "|" << Chi(n1,n2,n3));
                };
    };

    /* We define a quadratic operator, O_{ij} = c_i^+ c_j, to compute its ensemble average
     * and its fluctuations (dynamical susceptibility).
     * QuadraticOperator is the class which defines O_{ij}.
     */

    // define a quadratic operator, O = c^+_{up} c_{up}
    print_section("Quadratic oparator");
    QuadraticOperator N_up(IndexInfo, S, H, up_index, up_index);
    N_up.prepare();
    N_up.compute();

    // compute an ensemble average, <O>
    print_section("Ensemble average");
    EnsembleAverage EA(S,H, N_up, rho);
    EA.prepare();
    RealType occup_up = real(EA.getResult());
    INFO("Occupation number of up spin is " << occup_up);

    /* The dynamical susceptibility is computed by Susceptibility class.
     * One can obtain either F[ <A(tau)B> ] or F[ <A(tau)B> - <A><B> ],
     * where F denotes Fourier transform from tau to Matsubara frequency.
     * To choose the latter quantity, call subtractDisconnected() method.
     *
     * There are 3 variants of subtractDisconnected() method.
     *  1. <A> and <B> are computed in Susceptibility class
     *  2. use precomputed <A> and <B>
     *  3. use predefined QuadraticOperator instances, A and B
     */
    print_section("Dynamical susceptibility");
    Susceptibility Sus(S,H, N_up, N_up, rho);
    Sus.prepare();
    Sus.compute();
    // subtract <n_up><n_uo>
    Sus.subtractDisconnected();  // 1
    //Sus.subtractDisconnected(occup_up, occup_up);  // 2
    //Sus.subtractDisconnected(N_up, N_up);  // 3
    for(int n=0; n<10; n++){
        INFO(n << " " << Sus(n));
    }
}

void print_section (const std::string& str)
{
  if (!world.rank()) {
  std::cout << std::string(str.size(),'=') << std::endl;
  std::cout << str << std::endl;
  std::cout << std::string(str.size(),'=') << std::endl;
    };
}
<|endoftext|>


<commit_before>/* Copyright 2015 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include <dirent.h>
#include <dlfcn.h>
#include <errno.h>
#include <fcntl.h>
#include <fnmatch.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>

#ifdef __FreeBSD__
#include <pthread_np.h>
#endif

#include <thread>
#include <vector>

#include "tensorflow/core/platform/env.h"
#include "tensorflow/core/platform/load_library.h"
#include "tensorflow/core/platform/logging.h"
#include "tensorflow/core/platform/mutex.h"
#include "tensorflow/core/platform/ram_file_system.h"
#include "tensorflow/core/platform/strcat.h"
#include "tensorflow/core/protobuf/error_codes.pb.h"
#include "tensorflow/tsl/platform/default/posix_file_system.h"

namespace tensorflow {

namespace {

mutex name_mutex(tensorflow::LINKER_INITIALIZED);

std::map<std::thread::id, string>& GetThreadNameRegistry()
    TF_EXCLUSIVE_LOCKS_REQUIRED(name_mutex) {
  static auto* thread_name_registry = new std::map<std::thread::id, string>();
  return *thread_name_registry;
}

// We use the pthread API instead of std::thread so we can control stack sizes.
class PThread : public Thread {
 public:
  PThread(const ThreadOptions& thread_options, const std::string& name,
          std::function<void()> fn) {
    ThreadParams* params = new ThreadParams;
    params->name = name;
    params->fn = std::move(fn);
    pthread_attr_t attributes;
    pthread_attr_init(&attributes);
    if (thread_options.stack_size != 0) {
      pthread_attr_setstacksize(&attributes, thread_options.stack_size);
    }
    int ret = pthread_create(&thread_, &attributes, &ThreadFn, params);
    // There is no mechanism for the thread creation API to fail, so we CHECK.
    CHECK_EQ(ret, 0) << "Thread " << name
                     << " creation via pthread_create() failed.";
    pthread_attr_destroy(&attributes);
  }

  ~PThread() override { pthread_join(thread_, nullptr); }

 private:
  struct ThreadParams {
    std::string name;
    std::function<void()> fn;
  };
  static void* ThreadFn(void* params_arg) {
    std::unique_ptr<ThreadParams> params(
        reinterpret_cast<ThreadParams*>(params_arg));
    {
      mutex_lock l(name_mutex);
      GetThreadNameRegistry().emplace(std::this_thread::get_id(), params->name);
    }
    params->fn();
    {
      mutex_lock l(name_mutex);
      GetThreadNameRegistry().erase(std::this_thread::get_id());
    }
    return nullptr;
  }

  pthread_t thread_;
};

class PosixEnv : public Env {
 public:
  PosixEnv() {}

  ~PosixEnv() override { LOG(FATAL) << "Env::Default() must not be destroyed"; }

  bool MatchPath(const string& path, const string& pattern) override {
    return fnmatch(pattern.c_str(), path.c_str(), FNM_PATHNAME) == 0;
  }

  void SleepForMicroseconds(int64 micros) override {
    while (micros > 0) {
      timespec sleep_time;
      sleep_time.tv_sec = 0;
      sleep_time.tv_nsec = 0;

      if (micros >= 1e6) {
        sleep_time.tv_sec =
            std::min<int64_t>(micros / 1e6, std::numeric_limits<time_t>::max());
        micros -= static_cast<int64_t>(sleep_time.tv_sec) * 1e6;
      }
      if (micros < 1e6) {
        sleep_time.tv_nsec = 1000 * micros;
        micros = 0;
      }
      while (nanosleep(&sleep_time, &sleep_time) != 0 && errno == EINTR) {
        // Ignore signals and wait for the full interval to elapse.
      }
    }
  }

  Thread* StartThread(const ThreadOptions& thread_options, const string& name,
                      std::function<void()> fn) override {
    return new PThread(thread_options, name, fn);
  }

  int32 GetCurrentThreadId() override {
    static thread_local int32 current_thread_id = GetCurrentThreadIdInternal();
    return current_thread_id;
  }

  bool GetCurrentThreadName(string* name) override {
    {
      mutex_lock l(name_mutex);
      auto thread_name =
          GetThreadNameRegistry().find(std::this_thread::get_id());
      if (thread_name != GetThreadNameRegistry().end()) {
        *name = strings::StrCat(thread_name->second, "/", GetCurrentThreadId());
        return true;
      }
    }
#if defined(__GLIBC__) || defined(__FreeBSD__)
    char buf[100];
#ifdef __FreeBSD__
    int res = 0;
    pthread_get_name_np(pthread_self(), buf, static_cast<size_t>(100));
#else
    int res = pthread_getname_np(pthread_self(), buf, static_cast<size_t>(100));
#endif
    if (res != 0) {
      return false;
    }
    *name = buf;
    return true;
#else
    return false;
#endif
  }

  void SchedClosure(std::function<void()> closure) override {
    // TODO(b/27290852): Spawning a new thread here is wasteful, but
    // needed to deal with the fact that many `closure` functions are
    // blocking in the current codebase.
    std::thread closure_thread(closure);
    closure_thread.detach();
  }

  void SchedClosureAfter(int64 micros, std::function<void()> closure) override {
    // TODO(b/27290852): Consuming a thread here is wasteful, but this
    // code is (currently) only used in the case where a step fails
    // (AbortStep). This could be replaced by a timer thread
    SchedClosure([this, micros, closure]() {
      SleepForMicroseconds(micros);
      closure();
    });
  }

  Status LoadDynamicLibrary(const char* library_filename,
                            void** handle) override {
    return tensorflow::internal::LoadDynamicLibrary(library_filename, handle);
  }

  Status GetSymbolFromLibrary(void* handle, const char* symbol_name,
                              void** symbol) override {
    return tensorflow::internal::GetSymbolFromLibrary(handle, symbol_name,
                                                      symbol);
  }

  string FormatLibraryFileName(const string& name,
                               const string& version) override {
    return tensorflow::internal::FormatLibraryFileName(name, version);
  }

  string GetRunfilesDir() override {
    string bin_path = this->GetExecutablePath();
    string runfiles_suffix = ".runfiles/org_tensorflow";
    std::size_t pos = bin_path.find(runfiles_suffix);

    // Sometimes (when executing under python) bin_path returns the full path to
    // the python scripts under runfiles. Get the substring.
    if (pos != std::string::npos) {
      return bin_path.substr(0, pos + runfiles_suffix.length());
    }

    // See if we have the executable path. if executable.runfiles exists, return
    // that folder.
    string runfiles_path = bin_path + runfiles_suffix;
    Status s = this->IsDirectory(runfiles_path);
    if (s.ok()) {
      return runfiles_path;
    }

    // If nothing can be found, return something close.
    return bin_path.substr(0, bin_path.find_last_of("/\\"));
  }

 private:
  void GetLocalTempDirectories(std::vector<string>* list) override;

  int32 GetCurrentThreadIdInternal() {
#ifdef __APPLE__
    uint64_t tid64;
    pthread_threadid_np(nullptr, &tid64);
    return static_cast<int32>(tid64);
#elif defined(__FreeBSD__)
    return pthread_getthreadid_np();
#elif defined(__NR_gettid)
    return static_cast<int32>(syscall(__NR_gettid));
#else
    return std::hash<std::thread::id>()(std::this_thread::get_id());
#endif
  }
};

}  // namespace

#if defined(PLATFORM_POSIX) || defined(__APPLE__) || defined(__ANDROID__)
REGISTER_FILE_SYSTEM("", PosixFileSystem);
REGISTER_FILE_SYSTEM("file", LocalPosixFileSystem);
REGISTER_FILE_SYSTEM("ram", RamFileSystem);

Env* Env::Default() {
  static Env* default_env = new PosixEnv;
  return default_env;
}
#endif

void PosixEnv::GetLocalTempDirectories(std::vector<string>* list) {
  list->clear();
  // Directories, in order of preference. If we find a dir that
  // exists, we stop adding other less-preferred dirs
  const char* candidates[] = {
    // Non-null only during unittest/regtest
    getenv("TEST_TMPDIR"),

    // Explicitly-supplied temp dirs
    getenv("TMPDIR"),
    getenv("TMP"),

#if defined(__ANDROID__)
    "/data/local/tmp",
#endif

    // If all else fails
    "/tmp",
  };

  for (const char* d : candidates) {
    if (!d || d[0] == '\0') continue;  // Empty env var

    // Make sure we don't surprise anyone who's expecting a '/'
    string dstr = d;
    if (dstr[dstr.size() - 1] != '/') {
      dstr += "/";
    }

    struct stat statbuf;
    if (!stat(d, &statbuf) && S_ISDIR(statbuf.st_mode) &&
        !access(dstr.c_str(), 0)) {
      // We found a dir that exists and is accessible - we're done.
      list->push_back(dstr);
      return;
    }
  }
}

int setenv(const char* name, const char* value, int overwrite) {
  return ::setenv(name, value, overwrite);
}

int unsetenv(const char* name) { return ::unsetenv(name); }

}  // namespace tensorflow
<commit_msg>Print a useful warning if we can't find a directory for temporary files.<commit_after>/* Copyright 2015 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include <dirent.h>
#include <dlfcn.h>
#include <errno.h>
#include <fcntl.h>
#include <fnmatch.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>

#ifdef __FreeBSD__
#include <pthread_np.h>
#endif

#include <thread>
#include <vector>

#include "tensorflow/core/platform/env.h"
#include "tensorflow/core/platform/load_library.h"
#include "tensorflow/core/platform/logging.h"
#include "tensorflow/core/platform/mutex.h"
#include "tensorflow/core/platform/ram_file_system.h"
#include "tensorflow/core/platform/strcat.h"
#include "tensorflow/core/protobuf/error_codes.pb.h"
#include "tensorflow/tsl/platform/default/posix_file_system.h"

namespace tensorflow {

namespace {

mutex name_mutex(tensorflow::LINKER_INITIALIZED);

std::map<std::thread::id, string>& GetThreadNameRegistry()
    TF_EXCLUSIVE_LOCKS_REQUIRED(name_mutex) {
  static auto* thread_name_registry = new std::map<std::thread::id, string>();
  return *thread_name_registry;
}

// We use the pthread API instead of std::thread so we can control stack sizes.
class PThread : public Thread {
 public:
  PThread(const ThreadOptions& thread_options, const std::string& name,
          std::function<void()> fn) {
    ThreadParams* params = new ThreadParams;
    params->name = name;
    params->fn = std::move(fn);
    pthread_attr_t attributes;
    pthread_attr_init(&attributes);
    if (thread_options.stack_size != 0) {
      pthread_attr_setstacksize(&attributes, thread_options.stack_size);
    }
    int ret = pthread_create(&thread_, &attributes, &ThreadFn, params);
    // There is no mechanism for the thread creation API to fail, so we CHECK.
    CHECK_EQ(ret, 0) << "Thread " << name
                     << " creation via pthread_create() failed.";
    pthread_attr_destroy(&attributes);
  }

  ~PThread() override { pthread_join(thread_, nullptr); }

 private:
  struct ThreadParams {
    std::string name;
    std::function<void()> fn;
  };
  static void* ThreadFn(void* params_arg) {
    std::unique_ptr<ThreadParams> params(
        reinterpret_cast<ThreadParams*>(params_arg));
    {
      mutex_lock l(name_mutex);
      GetThreadNameRegistry().emplace(std::this_thread::get_id(), params->name);
    }
    params->fn();
    {
      mutex_lock l(name_mutex);
      GetThreadNameRegistry().erase(std::this_thread::get_id());
    }
    return nullptr;
  }

  pthread_t thread_;
};

class PosixEnv : public Env {
 public:
  PosixEnv() {}

  ~PosixEnv() override { LOG(FATAL) << "Env::Default() must not be destroyed"; }

  bool MatchPath(const string& path, const string& pattern) override {
    return fnmatch(pattern.c_str(), path.c_str(), FNM_PATHNAME) == 0;
  }

  void SleepForMicroseconds(int64 micros) override {
    while (micros > 0) {
      timespec sleep_time;
      sleep_time.tv_sec = 0;
      sleep_time.tv_nsec = 0;

      if (micros >= 1e6) {
        sleep_time.tv_sec =
            std::min<int64_t>(micros / 1e6, std::numeric_limits<time_t>::max());
        micros -= static_cast<int64_t>(sleep_time.tv_sec) * 1e6;
      }
      if (micros < 1e6) {
        sleep_time.tv_nsec = 1000 * micros;
        micros = 0;
      }
      while (nanosleep(&sleep_time, &sleep_time) != 0 && errno == EINTR) {
        // Ignore signals and wait for the full interval to elapse.
      }
    }
  }

  Thread* StartThread(const ThreadOptions& thread_options, const string& name,
                      std::function<void()> fn) override {
    return new PThread(thread_options, name, fn);
  }

  int32 GetCurrentThreadId() override {
    static thread_local int32 current_thread_id = GetCurrentThreadIdInternal();
    return current_thread_id;
  }

  bool GetCurrentThreadName(string* name) override {
    {
      mutex_lock l(name_mutex);
      auto thread_name =
          GetThreadNameRegistry().find(std::this_thread::get_id());
      if (thread_name != GetThreadNameRegistry().end()) {
        *name = strings::StrCat(thread_name->second, "/", GetCurrentThreadId());
        return true;
      }
    }
#if defined(__GLIBC__) || defined(__FreeBSD__)
    char buf[100];
#ifdef __FreeBSD__
    int res = 0;
    pthread_get_name_np(pthread_self(), buf, static_cast<size_t>(100));
#else
    int res = pthread_getname_np(pthread_self(), buf, static_cast<size_t>(100));
#endif
    if (res != 0) {
      return false;
    }
    *name = buf;
    return true;
#else
    return false;
#endif
  }

  void SchedClosure(std::function<void()> closure) override {
    // TODO(b/27290852): Spawning a new thread here is wasteful, but
    // needed to deal with the fact that many `closure` functions are
    // blocking in the current codebase.
    std::thread closure_thread(closure);
    closure_thread.detach();
  }

  void SchedClosureAfter(int64 micros, std::function<void()> closure) override {
    // TODO(b/27290852): Consuming a thread here is wasteful, but this
    // code is (currently) only used in the case where a step fails
    // (AbortStep). This could be replaced by a timer thread
    SchedClosure([this, micros, closure]() {
      SleepForMicroseconds(micros);
      closure();
    });
  }

  Status LoadDynamicLibrary(const char* library_filename,
                            void** handle) override {
    return tensorflow::internal::LoadDynamicLibrary(library_filename, handle);
  }

  Status GetSymbolFromLibrary(void* handle, const char* symbol_name,
                              void** symbol) override {
    return tensorflow::internal::GetSymbolFromLibrary(handle, symbol_name,
                                                      symbol);
  }

  string FormatLibraryFileName(const string& name,
                               const string& version) override {
    return tensorflow::internal::FormatLibraryFileName(name, version);
  }

  string GetRunfilesDir() override {
    string bin_path = this->GetExecutablePath();
    string runfiles_suffix = ".runfiles/org_tensorflow";
    std::size_t pos = bin_path.find(runfiles_suffix);

    // Sometimes (when executing under python) bin_path returns the full path to
    // the python scripts under runfiles. Get the substring.
    if (pos != std::string::npos) {
      return bin_path.substr(0, pos + runfiles_suffix.length());
    }

    // See if we have the executable path. if executable.runfiles exists, return
    // that folder.
    string runfiles_path = bin_path + runfiles_suffix;
    Status s = this->IsDirectory(runfiles_path);
    if (s.ok()) {
      return runfiles_path;
    }

    // If nothing can be found, return something close.
    return bin_path.substr(0, bin_path.find_last_of("/\\"));
  }

 private:
  void GetLocalTempDirectories(std::vector<string>* list) override;

  int32 GetCurrentThreadIdInternal() {
#ifdef __APPLE__
    uint64_t tid64;
    pthread_threadid_np(nullptr, &tid64);
    return static_cast<int32>(tid64);
#elif defined(__FreeBSD__)
    return pthread_getthreadid_np();
#elif defined(__NR_gettid)
    return static_cast<int32>(syscall(__NR_gettid));
#else
    return std::hash<std::thread::id>()(std::this_thread::get_id());
#endif
  }
};

}  // namespace

#if defined(PLATFORM_POSIX) || defined(__APPLE__) || defined(__ANDROID__)
REGISTER_FILE_SYSTEM("", PosixFileSystem);
REGISTER_FILE_SYSTEM("file", LocalPosixFileSystem);
REGISTER_FILE_SYSTEM("ram", RamFileSystem);

Env* Env::Default() {
  static Env* default_env = new PosixEnv;
  return default_env;
}
#endif

void PosixEnv::GetLocalTempDirectories(std::vector<string>* list) {
  list->clear();
  // Directories, in order of preference. If we find a dir that
  // exists, we stop adding other less-preferred dirs
  const char* candidates[] = {
    // Non-null only during unittest/regtest
    getenv("TEST_TMPDIR"),

    // Explicitly-supplied temp dirs
    getenv("TMPDIR"),
    getenv("TMP"),

#if defined(__ANDROID__)
    "/data/local/tmp",
#endif

    // If all else fails
    "/tmp",
  };

  std::string paths; // Only in case of errors.
  for (const char* d : candidates) {
    if (!d || d[0] == '\0') continue;  // Empty env var
    if (!paths.empty()) {
      paths += ", ";
    }
    paths += std::string(d);
    // Make sure we don't surprise anyone who's expecting a '/'
    string dstr = d;
    if (dstr[dstr.size() - 1] != '/') {
      dstr += "/";
    }

    struct stat statbuf;
    if (!stat(d, &statbuf) && S_ISDIR(statbuf.st_mode) &&
        !access(dstr.c_str(), 0)) {
      // We found a dir that exists and is accessible - we're done.
      list->push_back(dstr);
      return;
    }
  }
  LOG(WARNING) << "We are not able to find a directory for temporary files.\n"
               << "Verify the directory access and available space under: "
               << paths << ". "
               << "You can also provide a directory for temporary files with"
               << " the environment variable TMP or TMPDIR. "
               << "Example under bash: `export TMP=/my_new_temp_directory;`";
}

int setenv(const char* name, const char* value, int overwrite) {
  return ::setenv(name, value, overwrite);
}

int unsetenv(const char* name) { return ::unsetenv(name); }

}  // namespace tensorflow
<|endoftext|>


<commit_before>#include <faunus/species.h>
#include <faunus/inputfile.h>
#include <faunus/textio.h>
#include <faunus/physconst.h>
#include <faunus/json.h>
#include <stdlib.h>

namespace Faunus {

  AtomData::AtomData() {
    activity=0;
    charge=0;
    dp=0;
    dprot=0;
    eps=0;
    hydrophobic=0;
    mean=0;
    muscalar=0;
    mw=1.0;
    name="UNK";
    patchtype=0;
    radius=0;
    sigma=0;
    variance=0;
    len=0;
    half_len=0;
    pswitch=0;
    pdis=0;
    pangl=0;
    panglsw=0;
    //rcutwca=0;
    //rcut=0;
    //pcangl=0;
    //pcanglsw=0;
    //pcoshalfi=0;
    //psinhalfi=0;
    chiral_angle=0;
    mu.clear();
    theta.clear();
    alpha.clear();
  }

  AtomMap::AtomMap() {
    AtomData a;
    a.id=list.size();
    a.name="UNK";
    list.push_back(a);
  }

  AtomData & AtomMap::operator[] (AtomData::Tid i) {
    assert(i<list.size() && "Particle id not found!");
    return list.at(i);
  }

  AtomData & AtomMap::operator[] (string s) {
    for (auto &l_i : list)
      if (s==l_i.name)
        return l_i;
    return list.at(0);
  }

  /**
   * This will look for the keyword `atomlist` in the InputMap and
   * use value as the filename.fs
   */
  bool AtomMap::includefile(InputMap &in) {
    return includefile( in.get<string>("atomlist",filename) );
  }

  bool AtomMap::includeJSON(const string& file) {
    int n=0;
    filename=file;
    auto j=json::open(file);
    for (auto &atom : json::object("atomlist", j)) {
      n++;
      AtomData a;
      //Tensor<double> fallback;
      //fallback.clear();
      a.name = atom.first;
      a.activity = json::value<double>(atom.second, "activity", 0);
      a.alpha << json::value<std::string>(atom.second, "alpha", "");
      a.alpha *= 4*pc::pi*pc::e0*(1e-10)*pc::kT()/(pc::e*pc::e);
      a.theta << json::value<std::string>(atom.second, "theta", "");
      a.theta *= 0.20819434; // Debye Å -> e Å^2
      a.dp = json::value<double>(atom.second, "dp", 0);
      a.dprot = json::value<double>(atom.second, "dprot", 0) * pc::pi / 180.; // deg->rads
      a.eps = json::value<double>(atom.second, "eps", 0);
      a.hydrophobic = json::value<bool>(atom.second, "hydrophobic", false);
      a.mu << json::value<std::string>(atom.second, "mu", "0 0 0");
      a.muscalar = a.mu.len()*pc::D2eA();
      if (a.mu.len()>1e-6)
        a.mu = a.mu/a.mu.len();
      a.mw = json::value<double>(atom.second, "Mw", 1.);
      a.charge = json::value<double>(atom.second, "q", 0);
      a.radius = json::value<double>(atom.second, "r", 0);
      a.sigma = 2*a.radius;
      a.sigma = json::value<double>(atom.second, "sigma", a.sigma);
      a.radius = a.sigma/2;
      a.id=AtomData::Tid( list.size() );

      a.half_len = 0.5 * json::value<double>(atom.second, "len", 0);
      a.patchtype = json::value<double>(atom.second, "patchtype", 0);
      a.pswitch = json::value<double>(atom.second, "patchswitch", 0);
      a.pdis = json::value<double>(atom.second, "patchdistance", 0);
      a.pangl = json::value<double>(atom.second, "patchangle", 0)/180.0*pc::pi;
      a.panglsw = json::value<double>(atom.second, "patchangleswitch", 0)/180.0*pc::pi;
      a.chiral_angle = json::value<double>(atom.second, "patchchiralangle", 0)/180.0*pc::pi;
      a.betaC = json::value<double>(atom.second, "betaC", pc::infty);
      a.betaD = json::value<double>(atom.second, "betaD", pc::infty);
      a.betaQ = json::value<double>(atom.second, "betaQ", pc::infty);

      list.push_back(a); // add to main particle list

      // add to particle list
      bool insert=true;
      for (auto &i : list)
        if (i.name==a.name) {
          a.id=i.id; // keep old id and
          i=a; // override existing
          insert=false;
          break;
        }
      if (insert)
        list.push_back(a);
    }
    return (n>0) ? true : false;
  }

  /**
   * This will automatically detect if the file is a JSON
   * file and call includeJSON(). If not, the old restricted
   * file format is used.
   */
  bool AtomMap::includefile(string file) {
    // is it a JSON file?
    if (file.substr(file.find_last_of(".") + 1) == "json")
      return includeJSON(file);
    AtomData a;
    string t;
    filename=file;
    std::ifstream f(filename.c_str());
    cout << "Reading atom data from '" << filename << "'. ";
    if (f) {
      cout << "OK!\n";
      while (!f.eof()) {
        f >> t;
        if (t=="Atom") {
          f >> a.name >> a.charge >> a.radius >> a.eps >> a.mw >> t;
          a.sigma=2*a.radius;
          a.hydrophobic = (t=="yes") ? true : false;
          a.id=list.size();
          list.push_back(a);
        }
      }
      return true;
    }
    cout << "FAILED!\n";
    filename+=" (n/a)";
    return false;
  }

  string AtomMap::info() {
    using namespace textio;
    char w=25;
    if (filename.empty())
      filename="(undefined)";
    std::ostringstream o;
    o << header("Atomic Species")
      << pad(SUB,w,"Number of species") << list.size() << endl
      << pad(SUB,w,"Parameter file") << filename << endl
      << indent(SUB) << "Species:";
    for (size_t i=0; i<list.size(); i++) {
      if (i%10==0)
        o << endl << indent(SUBSUB);
      o << setw(SUBSUB+1) << std::left << list[i].name;
    }
    o << endl;
    return o.str();
  }

  AtomMap atom; // Instantiate global copy

}//namespace
<commit_msg>conflict<commit_after>#include <faunus/species.h>
#include <faunus/inputfile.h>
#include <faunus/textio.h>
#include <faunus/physconst.h>
#include <faunus/json.h>
#include <stdlib.h>

namespace Faunus {

  AtomData::AtomData() {
    activity=0;
    charge=0;
    dp=0;
    dprot=0;
    eps=0;
    hydrophobic=0;
    mean=0;
    muscalar=0;
    mw=1.0;
    name="UNK";
    patchtype=0;
    radius=0;
    sigma=0;
    variance=0;
    len=0;
    half_len=0;
    pswitch=0;
    pdis=0;
    pangl=0;
    panglsw=0;
    //rcutwca=0;
    //rcut=0;
    //pcangl=0;
    //pcanglsw=0;
    //pcoshalfi=0;
    //psinhalfi=0;
    chiral_angle=0;
    mu.clear();
    theta.clear();
    alpha.clear();
  }

  AtomMap::AtomMap() {
    AtomData a;
    a.id=list.size();
    a.name="UNK";
    list.push_back(a);
  }

  AtomData & AtomMap::operator[] (AtomData::Tid i) {
    assert(i<list.size() && "Particle id not found!");
    return list.at(i);
  }

  AtomData & AtomMap::operator[] (string s) {
    for (auto &l_i : list)
      if (s==l_i.name)
        return l_i;
    return list.at(0);
  }

  /**
   * This will look for the keyword `atomlist` in the InputMap and
   * use value as the filename.fs
   */
  bool AtomMap::includefile(InputMap &in) {
    return includefile( in.get<string>("atomlist",filename) );
  }

  bool AtomMap::includeJSON(const string& file) {
    int n=0;
    filename=file;
    auto j=json::open(file);
    for (auto &atom : json::object("atomlist", j)) {
      n++;
      AtomData a;
      //Tensor<double> fallback;
      //fallback.clear();
      a.name = atom.first;
      a.activity = json::value<double>(atom.second, "activity", 0);
      a.alpha << json::value<std::string>(atom.second, "alpha", "");
      a.alpha *= 4*pc::pi*pc::e0*(1e-10)*pc::kT()/(pc::e*pc::e);
      a.theta << json::value<std::string>(atom.second, "theta", "");
      a.theta *= 0.20819434; // Debye Å -> e Å^2
      a.dp = json::value<double>(atom.second, "dp", 0);
      a.dprot = json::value<double>(atom.second, "dprot", 0) * pc::pi / 180.; // deg->rads
      a.eps = json::value<double>(atom.second, "eps", 0);
      a.hydrophobic = json::value<bool>(atom.second, "hydrophobic", false);
      a.mu << json::value<std::string>(atom.second, "mu", "0 0 0");
      a.muscalar = a.mu.len()*pc::D2eA();
      if (a.mu.len()>1e-6)
        a.mu = a.mu/a.mu.len();
      a.mw = json::value<double>(atom.second, "Mw", 1.);
      a.charge = json::value<double>(atom.second, "q", 0);
      a.radius = json::value<double>(atom.second, "r", 0);
      a.sigma = 2*a.radius;
      a.sigma = json::value<double>(atom.second, "sigma", a.sigma);
      a.radius = a.sigma/2;
      a.id=AtomData::Tid( list.size() );
      a.half_len = 0.5 * json::value<double>(atom.second, "len", 0);
      a.patchtype = json::value<double>(atom.second, "patchtype", 0);
      a.pswitch = json::value<double>(atom.second, "patchswitch", 0);
      a.pdis = json::value<double>(atom.second, "patchdistance", 0);
      a.pangl = json::value<double>(atom.second, "patchangle", 0)/180.0*pc::pi;
      a.panglsw = json::value<double>(atom.second, "patchangleswitch", 0)/180.0*pc::pi;
      a.chiral_angle = json::value<double>(atom.second, "patchchiralangle", 0)/180.0*pc::pi;
      a.betaC = json::value<double>(atom.second, "betaC", pc::infty);
      a.betaD = json::value<double>(atom.second, "betaD", pc::infty);
      a.betaQ = json::value<double>(atom.second, "betaQ", pc::infty);
      // add to particle list
      bool insert=true;
      for (auto &i : list)
        if (i.name==a.name) {
          a.id=i.id; // keep old id and
          i=a; // override existing
          insert=false;
          break;
        }
      if (insert)
        list.push_back(a);
    }
    return (n>0) ? true : false;
  }

  /**
   * This will automatically detect if the file is a JSON
   * file and call includeJSON(). If not, the old restricted
   * file format is used.
   */
  bool AtomMap::includefile(string file) {
    // is it a JSON file?
    if (file.substr(file.find_last_of(".") + 1) == "json")
      return includeJSON(file);
    AtomData a;
    string t;
    filename=file;
    std::ifstream f(filename.c_str());
    cout << "Reading atom data from '" << filename << "'. ";
    if (f) {
      cout << "OK!\n";
      while (!f.eof()) {
        f >> t;
        if (t=="Atom") {
          f >> a.name >> a.charge >> a.radius >> a.eps >> a.mw >> t;
          a.sigma=2*a.radius;
          a.hydrophobic = (t=="yes") ? true : false;
          a.id=list.size();
          list.push_back(a);
        }
      }
      return true;
    }
    cout << "FAILED!\n";
    filename+=" (n/a)";
    return false;
  }

  string AtomMap::info() {
    using namespace textio;
    char w=25;
    if (filename.empty())
      filename="(undefined)";
    std::ostringstream o;
    o << header("Atomic Species")
      << pad(SUB,w,"Number of species") << list.size() << endl
      << pad(SUB,w,"Parameter file") << filename << endl
      << indent(SUB) << "Species:";
    for (size_t i=0; i<list.size(); i++) {
      if (i%10==0)
        o << endl << indent(SUBSUB);
      o << setw(SUBSUB+1) << std::left << list[i].name;
    }
    o << endl;
    return o.str();
  }

  AtomMap atom; // Instantiate global copy

}//namespace
<|endoftext|>