<commit_before>//(c) 2016 by Authors
//This file is a part of ABruijn program.
//Released under the BSD license (see LICENSE file)

#include "read_aligner.h"
#include "../common/parallel.h"
#include <cmath>
#include <iomanip>

namespace
{
	struct Chain
	{
		Chain(): score(0) {}
		std::vector<const EdgeAlignment*> aln;
		int32_t score;
	};
}

//Give alignments to separate edges for a single read, merges them
//into non-overlapping chains (could be more than one chain per read
//in case of chimera) with maximum score
std::vector<GraphAlignment>
	ReadAligner::chainReadAlignments(const SequenceContainer& edgeSeqs,
								 	 const std::vector<EdgeAlignment>& ovlps) const
{
	static const int32_t MAX_JUMP = Config::get("maximum_jump");
	static const int32_t MAX_READ_OVLP = 50;

	std::list<Chain> activeChains;
	for (auto& edgeAlignment : ovlps)
	{
		std::list<Chain> newChains;
		int32_t maxScore = 0;
		Chain* maxChain = nullptr;
		for (auto& chain : activeChains)
		{
			const OverlapRange& nextOvlp = edgeAlignment.overlap;
			const OverlapRange& prevOvlp = chain.aln.back()->overlap;

			int32_t readDiff = nextOvlp.curBegin - prevOvlp.curEnd;
			int32_t graphDiff = nextOvlp.extBegin +
								prevOvlp.extLen - prevOvlp.extEnd;

			if (chain.aln.back()->edge->nodeRight == edgeAlignment.edge->nodeLeft &&
				MAX_JUMP > readDiff && readDiff > -MAX_READ_OVLP &&
				MAX_JUMP > graphDiff && graphDiff > 0)
			{
				int32_t jumpDiv = abs(readDiff - graphDiff);
				int32_t gapCost = jumpDiv ? std::log2(jumpDiv) : 0;
				int32_t score = chain.score + nextOvlp.score - gapCost;
				if (score > maxScore)
				{
					maxScore = score;
					maxChain = &chain;
				}
			}
		}

		if (maxChain)
		{
			newChains.push_back(*maxChain);
			maxChain->aln.push_back(&edgeAlignment);
			maxChain->score = maxScore;
		}

		activeChains.splice(activeChains.end(), newChains);
		activeChains.push_back(Chain());
		activeChains.back().aln.push_back(&edgeAlignment);
		activeChains.back().score = edgeAlignment.overlap.score;
	}

	//greedily choose non-intersecting set of alignments
	std::vector<GraphAlignment> acceptedAlignments;
	std::vector<Chain> sortedChains(activeChains.begin(), activeChains.end());
	std::sort(sortedChains.begin(), sortedChains.end(),
			  [](const Chain& c1, const Chain& c2)
			  {return c1.score > c2.score;});
	for (auto& chain : sortedChains)
	{
		int32_t alnLen = chain.aln.back()->overlap.curEnd -
					 	 chain.aln.front()->overlap.curBegin;
		if (alnLen < Parameters::get().minimumOverlap) continue;

		//check if it overlaps with other accepted chains
		bool overlaps = false;
		for (auto& existAln : acceptedAlignments)
		{
			int32_t existStart = existAln.front().overlap.curBegin;
			int32_t existEnd = existAln.back().overlap.curEnd;
			int32_t curStart = chain.aln.front()->overlap.curBegin;
			int32_t curEnd = chain.aln.back()->overlap.curEnd;

			int32_t overlapRate = std::min(curEnd, existEnd) -
									std::max(curStart, existStart);
			if (overlapRate > (int)Config::get("max_separation")) overlaps = true;
		}
		if (!overlaps)
		{
			acceptedAlignments.emplace_back();
			for (auto& aln : chain.aln) acceptedAlignments.back().push_back(*aln);
		}
	}

	return acceptedAlignments;
}

void ReadAligner::alignReads()
{
	static const int MIN_EDGE_OVLP = (int)Config::get("max_separation");
	static const int EDGE_FLANK = 100;

	//create database
	std::unordered_map<FastaRecord::Id,
					   std::pair<GraphEdge*, SequenceSegment>> idToSegment;
	SequenceContainer pathsContainer;

	for (auto& edge : _graph.iterEdges())
	{
		if (!edge->edgeId.strand()) continue;

		//add each edge sequence variant to the database
		for (auto& segment : edge->seqSegments)
		{
			size_t len = segment.end - segment.start;
			auto sequence = _asmSeqs.getSeq(segment.seqId)
										.substr(segment.start, len);
			auto& newRec = pathsContainer.addSequence(sequence, "");

			idToSegment[newRec.id] = {edge, segment};
			idToSegment[newRec.id.rc()] = {_graph.complementEdge(edge),
										   segment.complement()};
		}
	}
	pathsContainer.buildPositionIndex();

	//index it and align reads
	VertexIndex pathsIndex(pathsContainer,
						   (int)Config::get("read_align_kmer_sample"));
	pathsIndex.countKmers(/*min freq*/ 1, /* genome size*/ 0);
	pathsIndex.setRepeatCutoff(/*min freq*/ 1);
	pathsIndex.buildIndex(/*min freq*/ 1);
	OverlapDetector readsOverlapper(pathsContainer, pathsIndex,
									(int)Config::get("maximum_jump"),
									MIN_EDGE_OVLP - EDGE_FLANK,
									/*no overhang*/ 0, /*no max ovlp count*/ 0,
									/*keep alignment*/ false, /*only max*/ false,
									(float)Config::get("read_align_ovlp_ident"),
									/* bad end adjust*/ 0.0f);
	OverlapContainer readsOverlaps(readsOverlapper, _readSeqs);

	std::vector<FastaRecord::Id> allQueries;
	int64_t totalLength = 0;
	for (auto& read : _readSeqs.iterSeqs())
	{
		if (!read.id.strand()) continue;
		if (read.sequence.length() > (size_t)Parameters::get().minimumOverlap)
		{
			totalLength += read.sequence.length();
			allQueries.push_back(read.id);
		}
	}
	std::mutex indexMutex;
	int numAligned = 0;
	int alignedInFull = 0;
	int64_t alignedLength = 0;

	std::function<void(const FastaRecord::Id&)> alignRead =
	[this, &indexMutex, &numAligned, &readsOverlaps,
		&idToSegment, &pathsContainer, &alignedLength, &alignedInFull]
	(const FastaRecord::Id& seqId)
	{
		auto overlaps = readsOverlaps.quickSeqOverlaps(seqId);
		std::vector<EdgeAlignment> alignments;
		for (auto& ovlp : overlaps)
		{
			//because edges might be as short as max_separation,
			//we set minimum alignment threshold to a bit shorter value.
			//However, apply the actual threshold for longer edges now.
			if (ovlp.extLen < MIN_EDGE_OVLP + EDGE_FLANK ||
				std::min(ovlp.curRange(), ovlp.extRange()) > MIN_EDGE_OVLP)
			{
				alignments.push_back({ovlp, idToSegment[ovlp.extId].first,
									  idToSegment[ovlp.extId].second});
			}

		}
		std::sort(alignments.begin(), alignments.end(),
		  [](const EdgeAlignment& e1, const EdgeAlignment& e2)
			{return e1.overlap.curBegin < e2.overlap.curBegin;});
		auto readChains = this->chainReadAlignments(pathsContainer, alignments);

		std::vector<GraphAlignment> complChains(readChains);
		for (auto& chain : complChains)
		{
			for (auto& aln : chain)
			{
				aln.edge = _graph.complementEdge(aln.edge);
				aln.segment = aln.segment.complement();
				aln.overlap = aln.overlap.complement();
			}
			std::reverse(chain.begin(), chain.end());
		}

		if (readChains.empty()) return;

		/////synchronized part
		indexMutex.lock();
		++numAligned;
		if (readChains.size() == 1) ++alignedInFull;
		for (auto& chain : readChains)
		{
			_readAlignments.push_back(chain);
			alignedLength += chain.back().overlap.curEnd -
							 chain.front().overlap.curBegin;
		}
		for (auto& chain : complChains)
		{
			_readAlignments.push_back(chain);
		}
		indexMutex.unlock();
		/////
	};

	processInParallel(allQueries, alignRead,
					  Parameters::get().numThreads, true);

	/*for (auto& aln : _readAlignments)
	{
		if (aln.size() > 1)
		{
			std::string alnStr;
			int switches = 0;
			for (size_t i = 0; i < aln.size() - 1; ++i)
			{
				if (aln[i].segment.end != aln[i + 1].segment.start) ++switches;
			}

			for (auto& edge : aln)
			{
				alnStr += std::to_string(edge.edge->edgeId.signedId()) + " ("
					+ std::to_string(edge.overlap.curRange()) + " "
					+ std::to_string(edge.overlap.score) + " "
					+ std::to_string((float)edge.overlap.score /
						edge.overlap.curRange()) + ") -> ";
			}
			alnStr.erase(alnStr.size() - 4);
			alnStr += " s: " + std::to_string(switches);
			FastaRecord::Id readId = aln.front().overlap.curId;
			Logger::get().debug() << "Aln " << _readSeqs.seqName(readId);
			Logger::get().debug() << "\t" << alnStr;
		}
	}*/

	Logger::get().debug() << "Total reads : " << allQueries.size();
	Logger::get().debug() << "Read with aligned parts : " << numAligned;
	Logger::get().debug() << "Aligned in one piece : " << alignedInFull;
	Logger::get().info() << "Aligned read sequence: " << alignedLength << " / "
		<< totalLength << " (" << (float)alignedLength / totalLength << ")";
	readsOverlaps.overlapDivergenceStats();
}

//updates alignments with respect to the new graph
void ReadAligner::updateAlignments()
{
	std::vector<GraphAlignment> newAlignments;
	for (auto& aln : _readAlignments)
	{
		GraphAlignment curAlignment;
		for (size_t i = 0; i < aln.size() - 1; ++i)
		{
			if (!_graph.hasEdge(aln[i].edge)) continue;

			curAlignment.push_back(aln[i]);
			if (!_graph.hasEdge(aln[i + 1].edge) ||
				aln[i].edge->nodeRight != aln[i + 1].edge->nodeLeft)
			{
				newAlignments.push_back(curAlignment);
				curAlignment.clear();
			}
		}

		if (_graph.hasEdge(aln.back().edge)) curAlignment.push_back(aln.back());
		if (!curAlignment.empty()) newAlignments.push_back(curAlignment);
	}

	_readAlignments = newAlignments;
}
<commit_msg>more accurate read alignment chaining<commit_after>//(c) 2016 by Authors
//This file is a part of ABruijn program.
//Released under the BSD license (see LICENSE file)

#include "read_aligner.h"
#include "../common/parallel.h"
#include <cmath>
#include <iomanip>

namespace
{
	struct Chain
	{
		Chain(): score(0) {}
		std::vector<const EdgeAlignment*> aln;
		int32_t score;
	};
}

//Give alignments to separate edges for a single read, merges them
//into non-overlapping chains (could be more than one chain per read
//in case of chimera) with maximum score
std::vector<GraphAlignment>
	ReadAligner::chainReadAlignments(const SequenceContainer& edgeSeqs,
								 	 const std::vector<EdgeAlignment>& ovlps) const
{
	static const int32_t MAX_JUMP = Config::get("maximum_jump");
	static const int32_t MAX_SEP = Config::get("max_separation");
	static const int32_t MAX_READ_OVLP = 50;

	std::list<Chain> activeChains;
	for (auto& edgeAlignment : ovlps)
	{
		std::list<Chain> newChains;
		int32_t maxScore = 0;
		Chain* maxChain = nullptr;
		for (auto& chain : activeChains)
		{
			const OverlapRange& nextOvlp = edgeAlignment.overlap;
			const OverlapRange& prevOvlp = chain.aln.back()->overlap;

			int32_t readDiff = nextOvlp.curBegin - prevOvlp.curEnd;
			int32_t graphLeftDiff = nextOvlp.extBegin;
			int32_t graphRightDiff = prevOvlp.extLen - prevOvlp.extEnd;

			if (chain.aln.back()->edge->nodeRight == edgeAlignment.edge->nodeLeft &&
				MAX_JUMP > readDiff && readDiff > -MAX_READ_OVLP &&
				graphLeftDiff < MAX_SEP && graphRightDiff < MAX_SEP)
			{
				//int32_t jumpDiv = abs(readDiff - graphDiff);
				//int32_t gapCost = jumpDiv ? std::log2(jumpDiv) : 0;
				int32_t gapCost = (graphLeftDiff + graphRightDiff) / 10;
				int32_t score = chain.score + nextOvlp.score - gapCost;
				if (score > maxScore)
				{
					maxScore = score;
					maxChain = &chain;
				}
			}
		}

		if (maxChain)
		{
			newChains.push_back(*maxChain);
			maxChain->aln.push_back(&edgeAlignment);
			maxChain->score = maxScore;
		}

		activeChains.splice(activeChains.end(), newChains);
		activeChains.push_back(Chain());
		activeChains.back().aln.push_back(&edgeAlignment);
		activeChains.back().score = edgeAlignment.overlap.score;
	}

	//greedily choose non-intersecting set of alignments
	std::vector<GraphAlignment> acceptedAlignments;
	std::vector<Chain> sortedChains(activeChains.begin(), activeChains.end());
	std::sort(sortedChains.begin(), sortedChains.end(),
			  [](const Chain& c1, const Chain& c2)
			  {return c1.score > c2.score;});
	for (auto& chain : sortedChains)
	{
		int32_t alnLen = chain.aln.back()->overlap.curEnd -
					 	 chain.aln.front()->overlap.curBegin;
		if (alnLen < Parameters::get().minimumOverlap) continue;

		//check if it overlaps with other accepted chains
		bool overlaps = false;
		for (auto& existAln : acceptedAlignments)
		{
			int32_t existStart = existAln.front().overlap.curBegin;
			int32_t existEnd = existAln.back().overlap.curEnd;
			int32_t curStart = chain.aln.front()->overlap.curBegin;
			int32_t curEnd = chain.aln.back()->overlap.curEnd;

			int32_t overlapRate = std::min(curEnd, existEnd) -
									std::max(curStart, existStart);
			if (overlapRate > (int)Config::get("max_separation")) overlaps = true;
		}
		if (!overlaps)
		{
			acceptedAlignments.emplace_back();
			for (auto& aln : chain.aln) acceptedAlignments.back().push_back(*aln);
		}
	}

	return acceptedAlignments;
}

void ReadAligner::alignReads()
{
	static const int MIN_EDGE_OVLP = (int)Config::get("max_separation");
	static const int EDGE_FLANK = 100;

	//create database
	std::unordered_map<FastaRecord::Id,
					   std::pair<GraphEdge*, SequenceSegment>> idToSegment;
	SequenceContainer pathsContainer;

	for (auto& edge : _graph.iterEdges())
	{
		if (!edge->edgeId.strand()) continue;

		//add each edge sequence variant to the database
		for (auto& segment : edge->seqSegments)
		{
			size_t len = segment.end - segment.start;
			auto sequence = _asmSeqs.getSeq(segment.seqId)
										.substr(segment.start, len);
			auto& newRec = pathsContainer.addSequence(sequence, "");

			idToSegment[newRec.id] = {edge, segment};
			idToSegment[newRec.id.rc()] = {_graph.complementEdge(edge),
										   segment.complement()};
		}
	}
	pathsContainer.buildPositionIndex();

	//index it and align reads
	VertexIndex pathsIndex(pathsContainer,
						   (int)Config::get("read_align_kmer_sample"));
	pathsIndex.countKmers(/*min freq*/ 1, /* genome size*/ 0);
	pathsIndex.setRepeatCutoff(/*min freq*/ 1);
	pathsIndex.buildIndex(/*min freq*/ 1);
	OverlapDetector readsOverlapper(pathsContainer, pathsIndex,
									(int)Config::get("maximum_jump"),
									MIN_EDGE_OVLP - EDGE_FLANK,
									/*no overhang*/ 0, /*no max ovlp count*/ 0,
									/*keep alignment*/ false, /*only max*/ false,
									(float)Config::get("read_align_ovlp_ident"),
									/* bad end adjust*/ 0.0f);
	OverlapContainer readsOverlaps(readsOverlapper, _readSeqs);

	std::vector<FastaRecord::Id> allQueries;
	int64_t totalLength = 0;
	for (auto& read : _readSeqs.iterSeqs())
	{
		if (!read.id.strand()) continue;
		if (read.sequence.length() > (size_t)Parameters::get().minimumOverlap)
		{
			totalLength += read.sequence.length();
			allQueries.push_back(read.id);
		}
	}
	std::mutex indexMutex;
	int numAligned = 0;
	int alignedInFull = 0;
	int64_t alignedLength = 0;

	std::function<void(const FastaRecord::Id&)> alignRead =
	[this, &indexMutex, &numAligned, &readsOverlaps,
		&idToSegment, &pathsContainer, &alignedLength, &alignedInFull]
	(const FastaRecord::Id& seqId)
	{
		auto overlaps = readsOverlaps.quickSeqOverlaps(seqId);
		std::vector<EdgeAlignment> alignments;
		for (auto& ovlp : overlaps)
		{
			//because edges might be as short as max_separation,
			//we set minimum alignment threshold to a bit shorter value.
			//However, apply the actual threshold for longer edges now.
			if (ovlp.extLen < MIN_EDGE_OVLP + EDGE_FLANK ||
				std::min(ovlp.curRange(), ovlp.extRange()) > MIN_EDGE_OVLP)
			{
				alignments.push_back({ovlp, idToSegment[ovlp.extId].first,
									  idToSegment[ovlp.extId].second});
			}

		}
		std::sort(alignments.begin(), alignments.end(),
		  [](const EdgeAlignment& e1, const EdgeAlignment& e2)
			{return e1.overlap.curBegin < e2.overlap.curBegin;});
		auto readChains = this->chainReadAlignments(pathsContainer, alignments);

		std::vector<GraphAlignment> complChains(readChains);
		for (auto& chain : complChains)
		{
			for (auto& aln : chain)
			{
				aln.edge = _graph.complementEdge(aln.edge);
				aln.segment = aln.segment.complement();
				aln.overlap = aln.overlap.complement();
			}
			std::reverse(chain.begin(), chain.end());
		}

		if (readChains.empty()) return;

		/////synchronized part
		indexMutex.lock();
		++numAligned;
		if (readChains.size() == 1) ++alignedInFull;
		for (auto& chain : readChains)
		{
			_readAlignments.push_back(chain);
			alignedLength += chain.back().overlap.curEnd -
							 chain.front().overlap.curBegin;
		}
		for (auto& chain : complChains)
		{
			_readAlignments.push_back(chain);
		}
		indexMutex.unlock();
		/////
	};

	processInParallel(allQueries, alignRead,
					  Parameters::get().numThreads, true);

	/*for (auto& aln : _readAlignments)
	{
		if (aln.size() > 1)
		{
			std::string alnStr;
			int switches = 0;
			for (size_t i = 0; i < aln.size() - 1; ++i)
			{
				if (aln[i].segment.end != aln[i + 1].segment.start) ++switches;
			}

			for (auto& edge : aln)
			{
				alnStr += std::to_string(edge.edge->edgeId.signedId()) + " ("
					+ std::to_string(edge.overlap.curRange()) + " "
					+ std::to_string(edge.overlap.score) + " "
					+ std::to_string((float)edge.overlap.score /
						edge.overlap.curRange()) + ") -> ";
			}
			alnStr.erase(alnStr.size() - 4);
			alnStr += " s: " + std::to_string(switches);
			FastaRecord::Id readId = aln.front().overlap.curId;
			Logger::get().debug() << "Aln " << _readSeqs.seqName(readId);
			Logger::get().debug() << "\t" << alnStr;
		}
	}*/

	Logger::get().debug() << "Total reads : " << allQueries.size();
	Logger::get().debug() << "Read with aligned parts : " << numAligned;
	Logger::get().debug() << "Aligned in one piece : " << alignedInFull;
	Logger::get().info() << "Aligned read sequence: " << alignedLength << " / "
		<< totalLength << " (" << (float)alignedLength / totalLength << ")";
	readsOverlaps.overlapDivergenceStats();
}

//updates alignments with respect to the new graph
void ReadAligner::updateAlignments()
{
	std::vector<GraphAlignment> newAlignments;
	for (auto& aln : _readAlignments)
	{
		GraphAlignment curAlignment;
		for (size_t i = 0; i < aln.size() - 1; ++i)
		{
			if (!_graph.hasEdge(aln[i].edge)) continue;

			curAlignment.push_back(aln[i]);
			if (!_graph.hasEdge(aln[i + 1].edge) ||
				aln[i].edge->nodeRight != aln[i + 1].edge->nodeLeft)
			{
				newAlignments.push_back(curAlignment);
				curAlignment.clear();
			}
		}

		if (_graph.hasEdge(aln.back().edge)) curAlignment.push_back(aln.back());
		if (!curAlignment.empty()) newAlignments.push_back(curAlignment);
	}

	_readAlignments = newAlignments;
}
<|endoftext|>


<commit_before>#include "obj_loader.hpp"

#include <fstream>
#include <sstream>

namespace sample_util
    {
    static bool begins_with(const std::string& input, const std::string& search_string)
    {
        if (input.size() < search_string.size())
        {
            return false;
        }

        for (size_t i = 0; i < search_string.size(); ++i)
        {
            if (input[i] != search_string[i])
            {
                return false;
            }
        }

        return true;
    }

    template <typename vertex_type, typename output_iterator>
    static void copy_face_elements(const std::vector<vertex_type>& source, const std::vector<size_t>& indices, output_iterator output)
    {
        for (size_t i = 0; i < indices.size(); ++i)
        {
            if (indices[i] < 1 || indices[i] > source.size())
            {
                std::ostringstream err;
                err << "index " << i << "(" << indices[i] << ") is out of range, must be in [0, " << source.size() << "].";
                throw std::runtime_error(err.str());
            }
            *output = source[indices[i] - 1];
            ++output;
        }
    }

    template <typename vertex_type, size_t element_count>
    static void compute_bounds(const std::vector< std::array<vertex_type, element_count> >& elements,
                               std::array<vertex_type, element_count>& min_bound, std::array<vertex_type, element_count>& max_bound)
    {
        min_bound.assign(std::numeric_limits<vertex_type>::max());
        max_bound.assign(std::numeric_limits<vertex_type>::min());
        for (size_t i = 0; i < elements.size(); ++i)
        {
            for (size_t j = 0; j < element_count; ++j)
            {
                min_bound[j] = std::min(min_bound[j], elements[i][j]);
                max_bound[j] = std::max(max_bound[j], elements[i][j]);
            }
        }
    }

    template <typename element_type>
    void read_attribute(std::istringstream& stream, element_type& element)
    {
        stream >> element;
    }

    template <typename element_type, size_t count>
    void read_attribute(std::istringstream& stream, std::array<element_type, count>& arr, size_t seperator_size = 0)
    {
        for (size_t i = 0; i < count; ++i)
        {
            stream >> arr[i];
            if (seperator_size > 0 && i + 1 < count)
            {
                char sep;
                for (size_t j = 0; j < seperator_size; ++j)
                {
                    stream >> sep;
                }
            }
        }
    }

    model load_model_from_file(const std::string& path)
    {
        static const std::string vertex_identifier = "v";
        static const std::string texcoord_identifier = "vt";
        static const std::string normal_identifier = "vn";
        static const std::string face_identifier = "f";

        std::vector<float4> vertices;
        std::vector<size_t> vertex_indicies;

        std::vector<float3> texcoords;
        std::vector<size_t> texcoord_indices;

        std::vector<float3> normals;
        std::vector<size_t> normal_indices;

        std::ifstream input_stream(path);
        if (!input_stream)
        {
            std::ostringstream err;
            err << "error opening model file " << path << " for reading.";
            throw std::runtime_error(err.str());
        }

        size_t line_count = 0;
        std::string line, identifier;
        while (std::getline(input_stream, line))
        {
            std::istringstream line_stream(line);
            line_stream >> identifier;

            if (identifier == vertex_identifier)
            {
                float4 vertex = { 0.0f, 0.0f, 0.0f, 1.0f };
                read_attribute(line_stream, vertex);
                vertices.push_back(vertex);
            }
            else if (identifier == texcoord_identifier)
            {
                float3 texcoord = { 0.0f, 0.0f, 0.0f };
                read_attribute(line_stream, texcoord);
                texcoords.push_back(texcoord);
            }
            else if (identifier == normal_identifier)
            {
                float3 normal = { 0.0f, 0.0f, 0.0f };
                read_attribute(line_stream, normal);
                normals.push_back(normal);
            }
            else if (identifier == face_identifier)
            {
                for (size_t i = 0; i < 3; ++i)
                {
                    std::array<size_t, 3> face = { 0, 0, 0 };
                    read_attribute(line_stream, face, 1);
                    vertex_indicies.push_back(face[0]);
                    texcoord_indices.push_back(face[1]);
                    normal_indices.push_back(face[2]);
                }
            }
            else
            {
                // unsupported identifier
            }

            line_count++;
        }

        model result;
        copy_face_elements(vertices, vertex_indicies, std::back_inserter(result.vertices));
        copy_face_elements(texcoords, texcoord_indices, std::back_inserter(result.texcoords));
        copy_face_elements(normals, normal_indices, std::back_inserter(result.normals));
        return result;
    }

    static const std::string ambient_identifier = "Ka";
    static const std::string diffuse_identifier = "Kd";
    static const std::string specular_color_identifier = "Ks";
    static const std::string specular_coefficient_identifier = "Ns";
    static const std::string disolved_identifier = "d";
    static const std::string transparency_identifier = "Tr";
    static const std::string ambient_map_identifier = "map_Ka";
    static const std::string diffuse_map_identifier = "map_Kd";
    static const std::string specular_color_map_identifier = "map_Ks";
    static const std::string alpha_map_identifier = "map_d";
    static const std::string bump_identifier = "bump";
    static const std::string bump_map_identifier = "map_bump";
    static const std::string displacement_map_identifier = "disp";

    material load_material_from_file(const std::string& path)
    {
        material result;

        std::ifstream input_stream(path);
        if (!input_stream)
        {
            std::ostringstream err;
            err << "error opening model file " << path << " for reading.";
            throw std::runtime_error(err.str());
        }

        size_t line_count = 0;
        std::string line, identifier;
        while (std::getline(input_stream, line))
        {
            std::istringstream line_stream(line);
            line_stream >> identifier;

            if (identifier == ambient_identifier)
            {
                read_attribute(line_stream, result.ambient_color);
            }
            else if (identifier == diffuse_identifier)
            {
                read_attribute(line_stream, result.diffuse_color);
            }
            else if (identifier == specular_color_identifier)
            {
                read_attribute(line_stream, result.specular_color);
            }
            else if (identifier == specular_coefficient_identifier)
            {
                read_attribute(line_stream, result.specular_coefficient);
            }
            else if (identifier == disolved_identifier || identifier == transparency_identifier)
            {
                read_attribute(line_stream, result.transparency);
            }
            else if (identifier == ambient_map_identifier)
            {
                read_attribute(line_stream, result.ambient_map_path);
            }
            else if (identifier == diffuse_map_identifier)
            {
                read_attribute(line_stream, result.diffuse_map_path);
            }
            else if (identifier == alpha_map_identifier)
            {
                read_attribute(line_stream, result.alpha_map_path);
            }
            else if (identifier == bump_identifier || identifier == bump_map_identifier)
            {
                read_attribute(line_stream, result.bump_map_path);
            }
            else if (identifier == displacement_map_identifier)
            {
                read_attribute(line_stream, result.displacement_map_path);
            }
            else
            {
                // unsupported identifier
            }
        }

        return result;
    }
}
<commit_msg>Removed unreferenced function and moved constants out of the global scope.<commit_after>#include "obj_loader.hpp"

#include <fstream>
#include <sstream>

namespace sample_util
{
    template <typename vertex_type, typename output_iterator>
    static void copy_face_elements(const std::vector<vertex_type>& source, const std::vector<size_t>& indices, output_iterator output)
    {
        for (size_t i = 0; i < indices.size(); ++i)
        {
            if (indices[i] < 1 || indices[i] > source.size())
            {
                std::ostringstream err;
                err << "index " << i << "(" << indices[i] << ") is out of range, must be in [0, " << source.size() << "].";
                throw std::runtime_error(err.str());
            }
            *output = source[indices[i] - 1];
            ++output;
        }
    }

    template <typename vertex_type, size_t element_count>
    static void compute_bounds(const std::vector< std::array<vertex_type, element_count> >& elements,
                               std::array<vertex_type, element_count>& min_bound, std::array<vertex_type, element_count>& max_bound)
    {
        min_bound.assign(std::numeric_limits<vertex_type>::max());
        max_bound.assign(std::numeric_limits<vertex_type>::min());
        for (size_t i = 0; i < elements.size(); ++i)
        {
            for (size_t j = 0; j < element_count; ++j)
            {
                min_bound[j] = std::min(min_bound[j], elements[i][j]);
                max_bound[j] = std::max(max_bound[j], elements[i][j]);
            }
        }
    }

    template <typename element_type>
    void read_attribute(std::istringstream& stream, element_type& element)
    {
        stream >> element;
    }

    template <typename element_type, size_t count>
    void read_attribute(std::istringstream& stream, std::array<element_type, count>& arr, size_t seperator_size = 0)
    {
        for (size_t i = 0; i < count; ++i)
        {
            stream >> arr[i];
            if (seperator_size > 0 && i + 1 < count)
            {
                char sep;
                for (size_t j = 0; j < seperator_size; ++j)
                {
                    stream >> sep;
                }
            }
        }
    }

    model load_model_from_file(const std::string& path)
    {
        static const std::string vertex_identifier = "v";
        static const std::string texcoord_identifier = "vt";
        static const std::string normal_identifier = "vn";
        static const std::string face_identifier = "f";

        std::vector<float4> vertices;
        std::vector<size_t> vertex_indicies;

        std::vector<float3> texcoords;
        std::vector<size_t> texcoord_indices;

        std::vector<float3> normals;
        std::vector<size_t> normal_indices;

        std::ifstream input_stream(path);
        if (!input_stream)
        {
            std::ostringstream err;
            err << "error opening model file " << path << " for reading.";
            throw std::runtime_error(err.str());
        }

        size_t line_count = 0;
        std::string line, identifier;
        while (std::getline(input_stream, line))
        {
            std::istringstream line_stream(line);
            line_stream >> identifier;

            if (identifier == vertex_identifier)
            {
                float4 vertex = { 0.0f, 0.0f, 0.0f, 1.0f };
                read_attribute(line_stream, vertex);
                vertices.push_back(vertex);
            }
            else if (identifier == texcoord_identifier)
            {
                float3 texcoord = { 0.0f, 0.0f, 0.0f };
                read_attribute(line_stream, texcoord);
                texcoords.push_back(texcoord);
            }
            else if (identifier == normal_identifier)
            {
                float3 normal = { 0.0f, 0.0f, 0.0f };
                read_attribute(line_stream, normal);
                normals.push_back(normal);
            }
            else if (identifier == face_identifier)
            {
                for (size_t i = 0; i < 3; ++i)
                {
                    std::array<size_t, 3> face = { 0, 0, 0 };
                    read_attribute(line_stream, face, 1);
                    vertex_indicies.push_back(face[0]);
                    texcoord_indices.push_back(face[1]);
                    normal_indices.push_back(face[2]);
                }
            }
            else
            {
                // unsupported identifier
            }

            line_count++;
        }

        model result;
        copy_face_elements(vertices, vertex_indicies, std::back_inserter(result.vertices));
        copy_face_elements(texcoords, texcoord_indices, std::back_inserter(result.texcoords));
        copy_face_elements(normals, normal_indices, std::back_inserter(result.normals));
        return result;
    }

    material load_material_from_file(const std::string& path)
    {
        static const std::string ambient_identifier = "Ka";
        static const std::string diffuse_identifier = "Kd";
        static const std::string specular_color_identifier = "Ks";
        static const std::string specular_coefficient_identifier = "Ns";
        static const std::string disolved_identifier = "d";
        static const std::string transparency_identifier = "Tr";
        static const std::string ambient_map_identifier = "map_Ka";
        static const std::string diffuse_map_identifier = "map_Kd";
        static const std::string specular_color_map_identifier = "map_Ks";
        static const std::string alpha_map_identifier = "map_d";
        static const std::string bump_identifier = "bump";
        static const std::string bump_map_identifier = "map_bump";
        static const std::string displacement_map_identifier = "disp";

        material result;

        std::ifstream input_stream(path);
        if (!input_stream)
        {
            std::ostringstream err;
            err << "error opening model file " << path << " for reading.";
            throw std::runtime_error(err.str());
        }

        size_t line_count = 0;
        std::string line, identifier;
        while (std::getline(input_stream, line))
        {
            std::istringstream line_stream(line);
            line_stream >> identifier;

            if (identifier == ambient_identifier)
            {
                read_attribute(line_stream, result.ambient_color);
            }
            else if (identifier == diffuse_identifier)
            {
                read_attribute(line_stream, result.diffuse_color);
            }
            else if (identifier == specular_color_identifier)
            {
                read_attribute(line_stream, result.specular_color);
            }
            else if (identifier == specular_coefficient_identifier)
            {
                read_attribute(line_stream, result.specular_coefficient);
            }
            else if (identifier == disolved_identifier || identifier == transparency_identifier)
            {
                read_attribute(line_stream, result.transparency);
            }
            else if (identifier == ambient_map_identifier)
            {
                read_attribute(line_stream, result.ambient_map_path);
            }
            else if (identifier == diffuse_map_identifier)
            {
                read_attribute(line_stream, result.diffuse_map_path);
            }
            else if (identifier == alpha_map_identifier)
            {
                read_attribute(line_stream, result.alpha_map_path);
            }
            else if (identifier == bump_identifier || identifier == bump_map_identifier)
            {
                read_attribute(line_stream, result.bump_map_path);
            }
            else if (identifier == displacement_map_identifier)
            {
                read_attribute(line_stream, result.displacement_map_path);
            }
            else
            {
                // unsupported identifier
            }
        }

        return result;
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ppapi/cpp/input_event.h"

#include "ppapi/cpp/instance.h"
#include "ppapi/cpp/module.h"
#include "ppapi/cpp/module_impl.h"
#include "ppapi/cpp/point.h"
#include "ppapi/cpp/var.h"

namespace pp {

namespace {

template <> const char* interface_name<PPB_InputEvent>() {
  return PPB_INPUT_EVENT_INTERFACE;
}

template <> const char* interface_name<PPB_KeyboardInputEvent>() {
  return PPB_KEYBOARD_INPUT_EVENT_INTERFACE;
}

template <> const char* interface_name<PPB_MouseInputEvent>() {
  return PPB_MOUSE_INPUT_EVENT_INTERFACE;
}

template <> const char* interface_name<PPB_WheelInputEvent>() {
  return PPB_WHEEL_INPUT_EVENT_INTERFACE;
}

}  // namespace

// InputEvent ------------------------------------------------------------------

InputEvent::InputEvent() : Resource() {
}

InputEvent::InputEvent(PP_Resource input_event_resource) : Resource() {
  // Type check the input event before setting it.
  if (!has_interface<PPB_InputEvent>())
    return;
  if (get_interface<PPB_InputEvent>()->IsInputEvent(input_event_resource)) {
    Module::Get()->core()->AddRefResource(input_event_resource);
    PassRefFromConstructor(input_event_resource);
  }
}

InputEvent::~InputEvent() {
}

PP_InputEvent_Type InputEvent::GetType() const {
  if (!has_interface<PPB_InputEvent>())
    return PP_INPUTEVENT_TYPE_UNDEFINED;
  return get_interface<PPB_InputEvent>()->GetType(pp_resource());
}

PP_TimeTicks InputEvent::GetTimeStamp() const {
  if (!has_interface<PPB_InputEvent>())
    return 0.0f;
  return get_interface<PPB_InputEvent>()->GetTimeStamp(pp_resource());
}

uint32_t InputEvent::GetModifiers() const {
  if (!has_interface<PPB_InputEvent>())
    return 0;
  return get_interface<PPB_InputEvent>()->GetModifiers(pp_resource());
}

// MouseInputEvent -------------------------------------------------------------

MouseInputEvent::MouseInputEvent() : InputEvent() {
}

MouseInputEvent::MouseInputEvent(const InputEvent& event) : InputEvent() {
  // Type check the input event before setting it.
  if (!has_interface<PPB_MouseInputEvent>())
    return;
  if (get_interface<PPB_MouseInputEvent>()->IsMouseInputEvent(
          event.pp_resource())) {
    Module::Get()->core()->AddRefResource(event.pp_resource());
    PassRefFromConstructor(event.pp_resource());
  }
}

PP_InputEvent_MouseButton MouseInputEvent::GetMouseButton() const {
  if (!has_interface<PPB_MouseInputEvent>())
    return PP_INPUTEVENT_MOUSEBUTTON_NONE;
  return get_interface<PPB_MouseInputEvent>()->GetMouseButton(pp_resource());
}

Point MouseInputEvent::GetMousePosition() const {
  if (!has_interface<PPB_MouseInputEvent>())
    return Point();
  return get_interface<PPB_MouseInputEvent>()->GetMousePosition(pp_resource());
}

int32_t MouseInputEvent::GetMouseClickCount() const {
  if (!has_interface<PPB_MouseInputEvent>())
    return 0;
  return get_interface<PPB_MouseInputEvent>()->GetMouseClickCount(
      pp_resource());
}

// WheelInputEvent -------------------------------------------------------------

WheelInputEvent::WheelInputEvent() : InputEvent() {
}

WheelInputEvent::WheelInputEvent(const InputEvent& event) : InputEvent() {
  // Type check the input event before setting it.
  if (!has_interface<PPB_WheelInputEvent>())
    return;
  if (get_interface<PPB_WheelInputEvent>()->IsWheelInputEvent(
          event.pp_resource())) {
    Module::Get()->core()->AddRefResource(event.pp_resource());
    PassRefFromConstructor(event.pp_resource());
  }
}

FloatPoint WheelInputEvent::GetWheelDelta() const {
  if (!has_interface<PPB_WheelInputEvent>())
    return FloatPoint();
  return get_interface<PPB_WheelInputEvent>()->GetWheelDelta(pp_resource());
}

FloatPoint WheelInputEvent::GetWheelTicks() const {
  if (!has_interface<PPB_WheelInputEvent>())
    return FloatPoint();
  return get_interface<PPB_WheelInputEvent>()->GetWheelTicks(pp_resource());
}

bool WheelInputEvent::GetScrollByPage() const {
  if (!has_interface<PPB_WheelInputEvent>())
    return false;
  return PP_ToBool(
      get_interface<PPB_WheelInputEvent>()->GetScrollByPage(pp_resource()));
}

// KeyboardInputEvent ----------------------------------------------------------

KeyboardInputEvent::KeyboardInputEvent() : InputEvent() {
}

KeyboardInputEvent::KeyboardInputEvent(const InputEvent& event) : InputEvent() {
  // Type check the input event before setting it.
  if (!has_interface<PPB_KeyboardInputEvent>())
    return;
  if (get_interface<PPB_KeyboardInputEvent>()->IsKeyboardInputEvent(
          event.pp_resource())) {
    Module::Get()->core()->AddRefResource(event.pp_resource());
    PassRefFromConstructor(event.pp_resource());
  }
}

uint32_t KeyboardInputEvent::GetKeyCode() const {
  if (!has_interface<PPB_KeyboardInputEvent>())
    return 0;
  return get_interface<PPB_KeyboardInputEvent>()->GetKeyCode(pp_resource());
}

Var KeyboardInputEvent::GetCharacterText() const {
  if (!has_interface<PPB_KeyboardInputEvent>())
    return PP_INPUTEVENT_TYPE_UNDEFINED;
  return Var(Var::PassRef(),
             get_interface<PPB_KeyboardInputEvent>()->GetCharacterText(
                 pp_resource()));
}

}  // namespace pp
<commit_msg>Fix return statement in ppapi/cpp/input_event.cc<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ppapi/cpp/input_event.h"

#include "ppapi/cpp/instance.h"
#include "ppapi/cpp/module.h"
#include "ppapi/cpp/module_impl.h"
#include "ppapi/cpp/point.h"
#include "ppapi/cpp/var.h"

namespace pp {

namespace {

template <> const char* interface_name<PPB_InputEvent>() {
  return PPB_INPUT_EVENT_INTERFACE;
}

template <> const char* interface_name<PPB_KeyboardInputEvent>() {
  return PPB_KEYBOARD_INPUT_EVENT_INTERFACE;
}

template <> const char* interface_name<PPB_MouseInputEvent>() {
  return PPB_MOUSE_INPUT_EVENT_INTERFACE;
}

template <> const char* interface_name<PPB_WheelInputEvent>() {
  return PPB_WHEEL_INPUT_EVENT_INTERFACE;
}

}  // namespace

// InputEvent ------------------------------------------------------------------

InputEvent::InputEvent() : Resource() {
}

InputEvent::InputEvent(PP_Resource input_event_resource) : Resource() {
  // Type check the input event before setting it.
  if (!has_interface<PPB_InputEvent>())
    return;
  if (get_interface<PPB_InputEvent>()->IsInputEvent(input_event_resource)) {
    Module::Get()->core()->AddRefResource(input_event_resource);
    PassRefFromConstructor(input_event_resource);
  }
}

InputEvent::~InputEvent() {
}

PP_InputEvent_Type InputEvent::GetType() const {
  if (!has_interface<PPB_InputEvent>())
    return PP_INPUTEVENT_TYPE_UNDEFINED;
  return get_interface<PPB_InputEvent>()->GetType(pp_resource());
}

PP_TimeTicks InputEvent::GetTimeStamp() const {
  if (!has_interface<PPB_InputEvent>())
    return 0.0f;
  return get_interface<PPB_InputEvent>()->GetTimeStamp(pp_resource());
}

uint32_t InputEvent::GetModifiers() const {
  if (!has_interface<PPB_InputEvent>())
    return 0;
  return get_interface<PPB_InputEvent>()->GetModifiers(pp_resource());
}

// MouseInputEvent -------------------------------------------------------------

MouseInputEvent::MouseInputEvent() : InputEvent() {
}

MouseInputEvent::MouseInputEvent(const InputEvent& event) : InputEvent() {
  // Type check the input event before setting it.
  if (!has_interface<PPB_MouseInputEvent>())
    return;
  if (get_interface<PPB_MouseInputEvent>()->IsMouseInputEvent(
          event.pp_resource())) {
    Module::Get()->core()->AddRefResource(event.pp_resource());
    PassRefFromConstructor(event.pp_resource());
  }
}

PP_InputEvent_MouseButton MouseInputEvent::GetMouseButton() const {
  if (!has_interface<PPB_MouseInputEvent>())
    return PP_INPUTEVENT_MOUSEBUTTON_NONE;
  return get_interface<PPB_MouseInputEvent>()->GetMouseButton(pp_resource());
}

Point MouseInputEvent::GetMousePosition() const {
  if (!has_interface<PPB_MouseInputEvent>())
    return Point();
  return get_interface<PPB_MouseInputEvent>()->GetMousePosition(pp_resource());
}

int32_t MouseInputEvent::GetMouseClickCount() const {
  if (!has_interface<PPB_MouseInputEvent>())
    return 0;
  return get_interface<PPB_MouseInputEvent>()->GetMouseClickCount(
      pp_resource());
}

// WheelInputEvent -------------------------------------------------------------

WheelInputEvent::WheelInputEvent() : InputEvent() {
}

WheelInputEvent::WheelInputEvent(const InputEvent& event) : InputEvent() {
  // Type check the input event before setting it.
  if (!has_interface<PPB_WheelInputEvent>())
    return;
  if (get_interface<PPB_WheelInputEvent>()->IsWheelInputEvent(
          event.pp_resource())) {
    Module::Get()->core()->AddRefResource(event.pp_resource());
    PassRefFromConstructor(event.pp_resource());
  }
}

FloatPoint WheelInputEvent::GetWheelDelta() const {
  if (!has_interface<PPB_WheelInputEvent>())
    return FloatPoint();
  return get_interface<PPB_WheelInputEvent>()->GetWheelDelta(pp_resource());
}

FloatPoint WheelInputEvent::GetWheelTicks() const {
  if (!has_interface<PPB_WheelInputEvent>())
    return FloatPoint();
  return get_interface<PPB_WheelInputEvent>()->GetWheelTicks(pp_resource());
}

bool WheelInputEvent::GetScrollByPage() const {
  if (!has_interface<PPB_WheelInputEvent>())
    return false;
  return PP_ToBool(
      get_interface<PPB_WheelInputEvent>()->GetScrollByPage(pp_resource()));
}

// KeyboardInputEvent ----------------------------------------------------------

KeyboardInputEvent::KeyboardInputEvent() : InputEvent() {
}

KeyboardInputEvent::KeyboardInputEvent(const InputEvent& event) : InputEvent() {
  // Type check the input event before setting it.
  if (!has_interface<PPB_KeyboardInputEvent>())
    return;
  if (get_interface<PPB_KeyboardInputEvent>()->IsKeyboardInputEvent(
          event.pp_resource())) {
    Module::Get()->core()->AddRefResource(event.pp_resource());
    PassRefFromConstructor(event.pp_resource());
  }
}

uint32_t KeyboardInputEvent::GetKeyCode() const {
  if (!has_interface<PPB_KeyboardInputEvent>())
    return 0;
  return get_interface<PPB_KeyboardInputEvent>()->GetKeyCode(pp_resource());
}

Var KeyboardInputEvent::GetCharacterText() const {
  if (!has_interface<PPB_KeyboardInputEvent>())
    return Var();
  return Var(Var::PassRef(),
             get_interface<PPB_KeyboardInputEvent>()->GetCharacterText(
                 pp_resource()));
}

}  // namespace pp
<|endoftext|>


<commit_before>/*******************************************************************************
GPU OPTIMIZED MONTE CARLO (GOMC) 2.40
Copyright (C) 2018  GOMC Group
A copy of the GNU General Public License can be found in the COPYRIGHT.txt
along with this program, also can be found at <http://www.gnu.org/licenses/>.
********************************************************************************/
#include "Simulation.h"
#include "GOMC_Config.h"    //For version number
#if GOMC_LIB_MPI
#include <mpi.h>
#include "ParallelTemperingPreprocessor.h"
#endif
#ifdef GOMC_CUDA
#include "cuda.h"
#include <cuda_runtime_api.h>
#endif
#include <iostream>
#include <ctime>

//find and include appropriate files for getHostname
#ifdef _WIN32
#include <Winsock2.h>
#define HOSTNAME
#elif defined(__linux__) || defined(__apple__) || defined(__FreeBSD__)
#include <unistd.h>
#include <sys/sysinfo.h>
#include <sys/utsname.h>
#define HOSTNAME
#endif

namespace
{
std::ostream& PrintTime(std::ostream& stream);
std::ostream& PrintHostname(std::ostream& stream);
std::ostream& PrintVersion(std::ostream& stream);
void PrintSimulationHeader();
void PrintSimulationFooter();
void PrintDebugMode();
bool CheckAndPrintEnsemble();
uint ReadNum(char *argv);
}

void PrintHardwareInfo();
#ifdef GOMC_CUDA
void PrintGPUHardwareInfo();
#endif

int main(int argc, char *argv[])
{
#if GOMC_LIB_MPI
  string inputFileStringMPI;
  fstream inputFileReaderMPI;
  MultiSim * multisim;
  int worldSize;
  int worldRank;
  ParallelTemperingPreprocessor pt;

  //std::streambuf * savedCOUT;
  //CHECK IF ARGS/FILE PROVIDED IN CMD LINE
  if (argc < 2) {
    std::cout << "Error: Input parameter file (*.dat or *.conf) not specified on command line!\n";
    exit(EXIT_FAILURE);
  } else {
    if(argc == 2) {
      //FIRST PARAMETER WILL BE FILE NAME
      inputFileStringMPI = argv[1];
    } else {
      //SECOND PARAMETER WILL BE FILE NAME
      inputFileStringMPI = argv[2];

      if(argv[1][0] == '+' && argv[1][1] == 'p') {
      // placeholder
      } else {
        std::cout << "Error: Undefined command to set number of threads!\n";
        std::cout << "Use +p# command to set number of threads.\n";
        exit(EXIT_FAILURE);
      }
    }

    //OPEN FILE
    inputFileReaderMPI.open(inputFileStringMPI.c_str(), ios::in | ios::out);

    //CHECK IF FILE IS OPENED...IF NOT OPENED EXCEPTION REASON FIRED
    if (!inputFileReaderMPI.is_open()) {
      std::cout << "Error: Cannot open/find " << inputFileStringMPI <<
                " in the directory provided!\n";
      exit(EXIT_FAILURE);
    }

    //CLOSE FILE TO NOW PASS TO SIMULATION
    inputFileReaderMPI.close();

    // Initialize the MPI environment
    MPI_Init(NULL, NULL);

    // Get the number of processes
    MPI_Comm_size(MPI_COMM_WORLD, &worldSize);

    // Get the rank of the process
    MPI_Comm_rank(MPI_COMM_WORLD, &worldRank);

    std::string pathToReplicaDirectory;
    if(pt.checkIfParallelTempering(inputFileStringMPI)){
      pt.checkIfValid(inputFileStringMPI);
      if(worldSize > pt.getNumberOfReplicas(inputFileStringMPI)){
        std::cout << "You may not request more processes (" << worldSize
          << ") than there are replicas(" << pt.getNumberOfReplicas(inputFileStringMPI) << ")! Exiting!\n";
      } else {
        #if ENSEMBLE == GCMC
        pathToReplicaDirectory = pt.setupReplicaDirectoriesAndRedirectSTDOUTToFile  ( pt.getMultiSimFolderName(inputFileStringMPI).c_str(),
                                                                                pt.getTemperature(inputFileStringMPI.c_str(), worldRank).c_str(),
                                                                                pt.getChemicalPotential(inputFileStringMPI.c_str(), worldRank).c_str()
                                                                                );
        #else
        pathToReplicaDirectory = pt.setupReplicaDirectoriesAndRedirectSTDOUTToFile  ( pt.getMultiSimFolderName(inputFileStringMPI).c_str(),
                                                                                pt.getTemperature(inputFileStringMPI.c_str(), worldRank).c_str()
                                                                                );
        #endif
        multisim = new MultiSim(worldSize, worldRank, pathToReplicaDirectory);
      }
    }
  }
#endif
#ifndef NDEBUG
  PrintDebugMode();
#endif
  PrintSimulationHeader();
  PrintHardwareInfo();
#ifdef GOMC_CUDA
  PrintGPUHardwareInfo();
#endif
  //Only run if valid ensemble was detected.
  if (CheckAndPrintEnsemble()) {
    //FOLLOWING LINES ADDED TO OBTAIN INPUT PARAMETER FILE
    string inputFileString;
    fstream inputFileReader;
    uint numThreads;

    //CHECK IF ARGS/FILE PROVIDED IN CMD LINE
    if (argc < 2) {
      std::cout << "Error: Input parameter file (*.dat or *.conf) not specified on command line!\n";
      exit(EXIT_FAILURE);
    } else {
      if(argc == 2) {
        //FIRST PARAMETER WILL BE FILE NAME
        inputFileString = argv[1];
        numThreads = 1;
      } else {
        //SECOND PARAMETER WILL BE FILE NAME
        inputFileString = argv[2];

        if(argv[1][0] == '+' && argv[1][1] == 'p') {
          numThreads = ReadNum(argv[1]);
        } else {
          std::cout << "Error: Undefined command to set number of threads!\n";
          std::cout << "Use +p# command to set number of threads.\n";
          exit(EXIT_FAILURE);
        }

      }
    }

    //SET NUMBER OF THREADS
#ifdef _OPENMP
    omp_set_num_threads(numThreads);
    printf("%-40s %-d \n", "Info: Number of threads", numThreads);
#else
    printf("%-40s %-d \n", "Info: Number of threads", 1);
#endif

    //OPEN FILE
    inputFileReader.open(inputFileString.c_str(), ios::in | ios::out);

    //CHECK IF FILE IS OPENED...IF NOT OPENED EXCEPTION REASON FIRED
    if (!inputFileReader.is_open()) {
      std::cout << "Error: Cannot open/find " << inputFileString <<
                " in the directory provided!\n";
      exit(EXIT_FAILURE);
    }

    //CLOSE FILE TO NOW PASS TO SIMULATION
    inputFileReader.close();

    //ONCE FILE FOUND PASS STRING TO SIMULATION CLASS TO READ AND
    //HANDLE PDB|PSF FILE
#if GOMC_LIB_MPI
    if(worldSize <= pt.getNumberOfReplicas(inputFileStringMPI)){
      Simulation sim(inputFileString.c_str(), multisim);
      sim.RunSimulation();
      PrintSimulationFooter();
    }
#else
    Simulation sim(inputFileString.c_str());
    sim.RunSimulation();
    PrintSimulationFooter();
#endif
  }
  #if GOMC_LIB_MPI
    delete multisim;
    MPI_Finalize();
    //std::cout.rdbuf(savedCOUT); //reset to standard output again
  #endif
  return 0;
}

namespace
{

void PrintSimulationHeader()
{
  std::cout << PrintVersion << '\n'
            << "Info: Start Time: " << PrintTime
#ifdef HOSTNAME
            << "Info: Host Name: " << PrintHostname
#endif
            << "\n";
}

bool CheckAndPrintEnsemble()
{
  bool healthy = true;
  std::cout << "Info: GOMC COMPILED TO RUN ";
#if ENSEMBLE == NVT
  std::cout << "CANONICAL (NVT)";
#elif ENSEMBLE == GEMC
  std::cout << "GIBBS";
#elif ENSEMBLE == GCMC
  std::cout << "GRAND CANONICAL";
#elif ENSEMBLE == NPT
  std::cout << "ISOBARIC-ISOTHERMAL";
#else
  std::cerr << "CRITICAL ERROR! Preprocessor value ENSEMBLE is "
            << "invalid or undefined." << std::endl
            << "Code will exit.";
  healthy = false;
#endif
  std::cout << " ENSEMBLE." << std::endl;
  return healthy;
}

void PrintDebugMode()
{
  std::cout << "################################################################################\n";
  std::cout << "########################## RUNNING GOMC IN DEBUG MODE ##########################\n";
  std::cout << "################################################################################\n";
}

void PrintSimulationFooter()
{
  std::cout << PrintVersion << '\n'
            << "Info: Completed at: " << PrintTime
            << "Info: On hostname: " << PrintHostname
            << '\n';
}

std::ostream& PrintVersion(std::ostream& stream)
{
  stream << "Info: GOMC Version " << GOMC_VERSION_MAJOR
         << '.' << GOMC_VERSION_MINOR;
  return stream;
}

std::ostream& PrintTime(std::ostream& stream)
{
  time_t timer;
  time(&timer);
  stream << asctime(localtime(&timer));
  return stream;
}

std::ostream& PrintHostname(std::ostream& stream)
{
#ifdef HOSTNAME
#ifdef _WIN32
  //setup WINSOCK
  WSADATA wsaData;
  WSAStartup(MAKEWORD(2, 0), &wsaData);
#endif

  const int maxNameLength = 80;
  char hostname[maxNameLength];
  gethostname(hostname, maxNameLength);
  //gethostname does not guarantee null termination
  hostname[maxNameLength - 1] = '\0';
  stream << hostname;

#ifdef _WIN32
  //teardown WINSOCK
  WSACleanup();
#endif
#else
  stream << "Info: Hostname Unavailable";
#endif
  return stream;
}

uint ReadNum(char *argv)
{
  uint thread = 0;

  for(uint i = 2; argv[i] != 0; i++) {
    thread = thread * 10 + (argv[i] - '0');
  }

  return thread;
}
}

void PrintHardwareInfo()
{
#ifdef __linux__
  struct sysinfo mem;
  const double megabyte = 1024 * 1024;
  struct utsname name;
  uname(&name);
  printf("CPU information:\n");
  std::cout << std::setprecision(1) << std::fixed;
  std::cout << "Info: Total number of CPUs: " << get_nprocs() << std::endl;
  std::cout << "Info: Total number of CPUs available: " << sysconf(_SC_NPROCESSORS_ONLN) << std::endl;
  std::cout << "Info: Model name:" << std::flush;
  if(system("awk -F: '/model name/ {print $2;exit}' /proc/cpuinfo") == -1)
    std::cout << "Error: Couldn't retrieve CPU information" << std::endl;
  std::cout << "Info: System name: " << name.sysname << std::endl;
  std::cout << "Info: Release: " << name.release << std::endl;
  std::cout << "Info: Version: " << name.version << std::endl;
  std::cout << "Info: Kernel Architecture: " << name.machine << std::endl;
  if(sysinfo(&mem) == 0) {
    std::cout << "Info: Total Ram: " << mem.totalram / megabyte << "MB" << std::endl;
    std::cout << "Info: Used Ram: " << mem.totalram / megabyte - mem.freeram / megabyte << "MB" << std::endl;
  }
  std::cout << "Info: Working in the current directory: " << get_current_dir_name();
  std::cout << std::endl;
#endif
}

#ifdef GOMC_CUDA
void PrintGPUHardwareInfo()
{
  int nDevices;
  int fast = 0;
  int fastIndex = 0;

  cudaGetDeviceCount(&nDevices);

  if(nDevices == 0) {
    printf("There are no available device(s) that support CUDA\n");
    exit(EXIT_FAILURE);
  }

  if(nDevices <= 4) {
    printf("GPU information:\n");
    for (int i = 0; i < nDevices; i++) {
      cudaDeviceProp prop;
      cudaGetDeviceProperties(&prop, i);
      printf("Info: Device Number: %d\n", i);
      printf("Info: Device name: %s\n", prop.name);
      printf("Info: Memory Clock Rate (KHz): %d\n", prop.memoryClockRate);
      printf("Info: Memory Bus Width (bits): %d\n", prop.memoryBusWidth);
      printf("Info: Peak Memory Bandwidth (GB/s): %f\n",
             2.0 * prop.memoryClockRate * (prop.memoryBusWidth / 8) / 1.0e6);
      if( prop.memoryClockRate > fast) {
        fast =  prop.memoryClockRate;
        fastIndex = i;
      }
    }
  }
  cudaSetDevice(fastIndex);
  printf("Info: Using Device Number: %d\n", fastIndex);
}
#endif
<commit_msg>Delete multisim only if created<commit_after>/*******************************************************************************
GPU OPTIMIZED MONTE CARLO (GOMC) 2.40
Copyright (C) 2018  GOMC Group
A copy of the GNU General Public License can be found in the COPYRIGHT.txt
along with this program, also can be found at <http://www.gnu.org/licenses/>.
********************************************************************************/
#include "Simulation.h"
#include "GOMC_Config.h"    //For version number
#if GOMC_LIB_MPI
#include <mpi.h>
#include "ParallelTemperingPreprocessor.h"
#endif
#ifdef GOMC_CUDA
#include "cuda.h"
#include <cuda_runtime_api.h>
#endif
#include <iostream>
#include <ctime>

//find and include appropriate files for getHostname
#ifdef _WIN32
#include <Winsock2.h>
#define HOSTNAME
#elif defined(__linux__) || defined(__apple__) || defined(__FreeBSD__)
#include <unistd.h>
#include <sys/sysinfo.h>
#include <sys/utsname.h>
#define HOSTNAME
#endif

namespace
{
std::ostream& PrintTime(std::ostream& stream);
std::ostream& PrintHostname(std::ostream& stream);
std::ostream& PrintVersion(std::ostream& stream);
void PrintSimulationHeader();
void PrintSimulationFooter();
void PrintDebugMode();
bool CheckAndPrintEnsemble();
uint ReadNum(char *argv);
}

void PrintHardwareInfo();
#ifdef GOMC_CUDA
void PrintGPUHardwareInfo();
#endif

int main(int argc, char *argv[])
{
#if GOMC_LIB_MPI
  string inputFileStringMPI;
  fstream inputFileReaderMPI;
  MultiSim * multisim;
  int worldSize;
  int worldRank;
  ParallelTemperingPreprocessor pt;

  //std::streambuf * savedCOUT;
  //CHECK IF ARGS/FILE PROVIDED IN CMD LINE
  if (argc < 2) {
    std::cout << "Error: Input parameter file (*.dat or *.conf) not specified on command line!\n";
    exit(EXIT_FAILURE);
  } else {
    if(argc == 2) {
      //FIRST PARAMETER WILL BE FILE NAME
      inputFileStringMPI = argv[1];
    } else {
      //SECOND PARAMETER WILL BE FILE NAME
      inputFileStringMPI = argv[2];

      if(argv[1][0] == '+' && argv[1][1] == 'p') {
      // placeholder
      } else {
        std::cout << "Error: Undefined command to set number of threads!\n";
        std::cout << "Use +p# command to set number of threads.\n";
        exit(EXIT_FAILURE);
      }
    }

    //OPEN FILE
    inputFileReaderMPI.open(inputFileStringMPI.c_str(), ios::in | ios::out);

    //CHECK IF FILE IS OPENED...IF NOT OPENED EXCEPTION REASON FIRED
    if (!inputFileReaderMPI.is_open()) {
      std::cout << "Error: Cannot open/find " << inputFileStringMPI <<
                " in the directory provided!\n";
      exit(EXIT_FAILURE);
    }

    //CLOSE FILE TO NOW PASS TO SIMULATION
    inputFileReaderMPI.close();

    // Initialize the MPI environment
    MPI_Init(NULL, NULL);

    // Get the number of processes
    MPI_Comm_size(MPI_COMM_WORLD, &worldSize);

    // Get the rank of the process
    MPI_Comm_rank(MPI_COMM_WORLD, &worldRank);

    std::string pathToReplicaDirectory;
    if(pt.checkIfParallelTempering(inputFileStringMPI)){
      pt.checkIfValid(inputFileStringMPI);
      if(worldSize > pt.getNumberOfReplicas(inputFileStringMPI)){
        std::cout << "You may not request more processes (" << worldSize
          << ") than there are replicas(" << pt.getNumberOfReplicas(inputFileStringMPI) << ")! Exiting!\n";
      } else {
        #if ENSEMBLE == GCMC
        pathToReplicaDirectory = pt.setupReplicaDirectoriesAndRedirectSTDOUTToFile  ( pt.getMultiSimFolderName(inputFileStringMPI).c_str(),
                                                                                pt.getTemperature(inputFileStringMPI.c_str(), worldRank).c_str(),
                                                                                pt.getChemicalPotential(inputFileStringMPI.c_str(), worldRank).c_str()
                                                                                );
        #else
        pathToReplicaDirectory = pt.setupReplicaDirectoriesAndRedirectSTDOUTToFile  ( pt.getMultiSimFolderName(inputFileStringMPI).c_str(),
                                                                                pt.getTemperature(inputFileStringMPI.c_str(), worldRank).c_str()
                                                                                );
        #endif
        multisim = new MultiSim(worldSize, worldRank, pathToReplicaDirectory);
      }
    }
  }
#endif
#ifndef NDEBUG
  PrintDebugMode();
#endif
  PrintSimulationHeader();
  PrintHardwareInfo();
#ifdef GOMC_CUDA
  PrintGPUHardwareInfo();
#endif
  //Only run if valid ensemble was detected.
  if (CheckAndPrintEnsemble()) {
    //FOLLOWING LINES ADDED TO OBTAIN INPUT PARAMETER FILE
    string inputFileString;
    fstream inputFileReader;
    uint numThreads;

    //CHECK IF ARGS/FILE PROVIDED IN CMD LINE
    if (argc < 2) {
      std::cout << "Error: Input parameter file (*.dat or *.conf) not specified on command line!\n";
      exit(EXIT_FAILURE);
    } else {
      if(argc == 2) {
        //FIRST PARAMETER WILL BE FILE NAME
        inputFileString = argv[1];
        numThreads = 1;
      } else {
        //SECOND PARAMETER WILL BE FILE NAME
        inputFileString = argv[2];

        if(argv[1][0] == '+' && argv[1][1] == 'p') {
          numThreads = ReadNum(argv[1]);
        } else {
          std::cout << "Error: Undefined command to set number of threads!\n";
          std::cout << "Use +p# command to set number of threads.\n";
          exit(EXIT_FAILURE);
        }

      }
    }

    //SET NUMBER OF THREADS
#ifdef _OPENMP
    omp_set_num_threads(numThreads);
    printf("%-40s %-d \n", "Info: Number of threads", numThreads);
#else
    printf("%-40s %-d \n", "Info: Number of threads", 1);
#endif

    //OPEN FILE
    inputFileReader.open(inputFileString.c_str(), ios::in | ios::out);

    //CHECK IF FILE IS OPENED...IF NOT OPENED EXCEPTION REASON FIRED
    if (!inputFileReader.is_open()) {
      std::cout << "Error: Cannot open/find " << inputFileString <<
                " in the directory provided!\n";
      exit(EXIT_FAILURE);
    }

    //CLOSE FILE TO NOW PASS TO SIMULATION
    inputFileReader.close();

    //ONCE FILE FOUND PASS STRING TO SIMULATION CLASS TO READ AND
    //HANDLE PDB|PSF FILE
#if GOMC_LIB_MPI
    if(worldSize <= pt.getNumberOfReplicas(inputFileStringMPI)){
      Simulation sim(inputFileString.c_str(), multisim);
      sim.RunSimulation();
      PrintSimulationFooter();
      delete multisim;
    }
#else
    Simulation sim(inputFileString.c_str());
    sim.RunSimulation();
    PrintSimulationFooter();
#endif
  }
  #if GOMC_LIB_MPI
    MPI_Finalize();
    //std::cout.rdbuf(savedCOUT); //reset to standard output again
  #endif
  return 0;
}

namespace
{

void PrintSimulationHeader()
{
  std::cout << PrintVersion << '\n'
            << "Info: Start Time: " << PrintTime
#ifdef HOSTNAME
            << "Info: Host Name: " << PrintHostname
#endif
            << "\n";
}

bool CheckAndPrintEnsemble()
{
  bool healthy = true;
  std::cout << "Info: GOMC COMPILED TO RUN ";
#if ENSEMBLE == NVT
  std::cout << "CANONICAL (NVT)";
#elif ENSEMBLE == GEMC
  std::cout << "GIBBS";
#elif ENSEMBLE == GCMC
  std::cout << "GRAND CANONICAL";
#elif ENSEMBLE == NPT
  std::cout << "ISOBARIC-ISOTHERMAL";
#else
  std::cerr << "CRITICAL ERROR! Preprocessor value ENSEMBLE is "
            << "invalid or undefined." << std::endl
            << "Code will exit.";
  healthy = false;
#endif
  std::cout << " ENSEMBLE." << std::endl;
  return healthy;
}

void PrintDebugMode()
{
  std::cout << "################################################################################\n";
  std::cout << "########################## RUNNING GOMC IN DEBUG MODE ##########################\n";
  std::cout << "################################################################################\n";
}

void PrintSimulationFooter()
{
  std::cout << PrintVersion << '\n'
            << "Info: Completed at: " << PrintTime
            << "Info: On hostname: " << PrintHostname
            << '\n';
}

std::ostream& PrintVersion(std::ostream& stream)
{
  stream << "Info: GOMC Version " << GOMC_VERSION_MAJOR
         << '.' << GOMC_VERSION_MINOR;
  return stream;
}

std::ostream& PrintTime(std::ostream& stream)
{
  time_t timer;
  time(&timer);
  stream << asctime(localtime(&timer));
  return stream;
}

std::ostream& PrintHostname(std::ostream& stream)
{
#ifdef HOSTNAME
#ifdef _WIN32
  //setup WINSOCK
  WSADATA wsaData;
  WSAStartup(MAKEWORD(2, 0), &wsaData);
#endif

  const int maxNameLength = 80;
  char hostname[maxNameLength];
  gethostname(hostname, maxNameLength);
  //gethostname does not guarantee null termination
  hostname[maxNameLength - 1] = '\0';
  stream << hostname;

#ifdef _WIN32
  //teardown WINSOCK
  WSACleanup();
#endif
#else
  stream << "Info: Hostname Unavailable";
#endif
  return stream;
}

uint ReadNum(char *argv)
{
  uint thread = 0;

  for(uint i = 2; argv[i] != 0; i++) {
    thread = thread * 10 + (argv[i] - '0');
  }

  return thread;
}
}

void PrintHardwareInfo()
{
#ifdef __linux__
  struct sysinfo mem;
  const double megabyte = 1024 * 1024;
  struct utsname name;
  uname(&name);
  printf("CPU information:\n");
  std::cout << std::setprecision(1) << std::fixed;
  std::cout << "Info: Total number of CPUs: " << get_nprocs() << std::endl;
  std::cout << "Info: Total number of CPUs available: " << sysconf(_SC_NPROCESSORS_ONLN) << std::endl;
  std::cout << "Info: Model name:" << std::flush;
  if(system("awk -F: '/model name/ {print $2;exit}' /proc/cpuinfo") == -1)
    std::cout << "Error: Couldn't retrieve CPU information" << std::endl;
  std::cout << "Info: System name: " << name.sysname << std::endl;
  std::cout << "Info: Release: " << name.release << std::endl;
  std::cout << "Info: Version: " << name.version << std::endl;
  std::cout << "Info: Kernel Architecture: " << name.machine << std::endl;
  if(sysinfo(&mem) == 0) {
    std::cout << "Info: Total Ram: " << mem.totalram / megabyte << "MB" << std::endl;
    std::cout << "Info: Used Ram: " << mem.totalram / megabyte - mem.freeram / megabyte << "MB" << std::endl;
  }
  std::cout << "Info: Working in the current directory: " << get_current_dir_name();
  std::cout << std::endl;
#endif
}

#ifdef GOMC_CUDA
void PrintGPUHardwareInfo()
{
  int nDevices;
  int fast = 0;
  int fastIndex = 0;

  cudaGetDeviceCount(&nDevices);

  if(nDevices == 0) {
    printf("There are no available device(s) that support CUDA\n");
    exit(EXIT_FAILURE);
  }

  if(nDevices <= 4) {
    printf("GPU information:\n");
    for (int i = 0; i < nDevices; i++) {
      cudaDeviceProp prop;
      cudaGetDeviceProperties(&prop, i);
      printf("Info: Device Number: %d\n", i);
      printf("Info: Device name: %s\n", prop.name);
      printf("Info: Memory Clock Rate (KHz): %d\n", prop.memoryClockRate);
      printf("Info: Memory Bus Width (bits): %d\n", prop.memoryBusWidth);
      printf("Info: Peak Memory Bandwidth (GB/s): %f\n",
             2.0 * prop.memoryClockRate * (prop.memoryBusWidth / 8) / 1.0e6);
      if( prop.memoryClockRate > fast) {
        fast =  prop.memoryClockRate;
        fastIndex = i;
      }
    }
  }
  cudaSetDevice(fastIndex);
  printf("Info: Using Device Number: %d\n", fastIndex);
}
#endif
<|endoftext|>


<commit_before>#include "Version.h"
#include "System/Config.h"
#include "System/Events/EventLoop.h"
#include "System/IO/IOProcessor.h"
#include "Framework/Storage/StorageEnvironment.h"

#ifdef DEBUG
#define VERSION_FMT_STRING "ScalienDB v" VERSION_STRING " (DEBUG build date " __DATE__ " " __TIME__ ")"
#else
#define VERSION_FMT_STRING "ScalienDB v" VERSION_STRING
#endif

void InitLog();

int main()
{
    StartClock();
    IOProcessor::Init(configFile.GetIntValue("io.maxfd", 1024), true);
    Log_SetTarget(LOG_TARGET_STDOUT);
    Log_SetTrace(false);
    Log_SetTimestamping(true);
    EventLoop::Init();

    StorageEnvironment env;
    Buffer envPath;
    envPath.Write("db/");
    env.Open(envPath);
    env.CreateShard(1, 1, 1, ReadBuffer(""), ReadBuffer(""), true);
    env.CreateShard(1, 2, 1, ReadBuffer(""), ReadBuffer(""), true);

    Buffer key, value;
    ReadBuffer rk, rv;
    uint64_t i,j, rnd, num;

    key.Writef("999999");
    value.Writef("world");

    env.Get(1, 2, ReadBuffer(key), rv);

    env.Set(1, 2, ReadBuffer(key), ReadBuffer(value));

    num = 10*1000*1000;
    for (i = 0; i < num; i++)
    {
// rnd = RandomInt(0, num - 1);
        key.Writef("%U", i);
        value.Writef("%0100U", i);
        env.Set(1, 1, ReadBuffer(key), ReadBuffer(value));
        if (i % (100*1000) == 0)
        {
            env.Commit();
            Log_Message("%U", i);
        }
        if (i > 0 && i % (10*1000) == 0)
        {
            EventLoop::RunOnce();

//            for (j = 0; j < 1000; j++)
//            {
//                rnd = RandomInt(0, i - 1);
//                key.Writef("%U", rnd);
//                if (!env.Get(1, 1, ReadBuffer(key), rv))
//                    Log_Message("%B => not found", &key);
//            }
        }
    }
    env.Commit();

    StorageBulkCursor* bc = env.GetBulkCursor(1, 1);
    StorageKeyValue* it;
    i = 0;
    Log_Message("Bulk iterating...");
    FOREACH(it, *bc)
    {
        rk = it->GetKey();
        rv = it->GetValue();
//        Log_Message("%R => %R", &rk, &rv);
        i++;
        if (i > 0 && i % (100*1000) == 0)
        {
            Log_Message("%U", i);
            Log_Message("%R => %R", &rk, &rv);
        }

    }
    Log_Message("%d", i);

// ReadBuffer rv;
// uint64_t rnd;
// Log_Message("GET begin");
// for (i = 0; i < 100*1000; i++)
// {
// rnd = RandomInt(0, 1000*1000 - 1);
// key.Writef("%U", rnd);
// if (!env.Get(1, 1, ReadBuffer(key), rv))
// Log_Message("%B => not found", &key);
// }
//
// Log_Message("GET end");
// env.Close();

    EventLoop::Shutdown();
    IOProcessor::Shutdown();
    StopClock();
    Log_Shutdown();
}

void InitLog()
{
    int logTargets;

    logTargets = 0;
    if (configFile.GetListNum("log.targets") == 0)
        logTargets = LOG_TARGET_STDOUT;

    for (int i = 0; i < configFile.GetListNum("log.targets"); i++)
    {
        if (strcmp(configFile.GetListValue("log.targets", i, ""), "file") == 0)
        {
            logTargets |= LOG_TARGET_FILE;
            Log_SetOutputFile(configFile.GetValue("log.file", NULL),
            configFile.GetBoolValue("log.truncate", false));
        }
        if (strcmp(configFile.GetListValue("log.targets", i, NULL), "stdout") == 0)
            logTargets |= LOG_TARGET_STDOUT;
        if (strcmp(configFile.GetListValue("log.targets", i, NULL), "stderr") == 0)
            logTargets |= LOG_TARGET_STDERR;
    }
    Log_SetTarget(logTargets);

    Log_SetTrace(configFile.GetBoolValue("log.trace", false));
    Log_SetTimestamping(configFile.GetBoolValue("log.timestamping", false));
}

//#include "Version.h"
//#include "System/Config.h"
//#include "System/Events/EventLoop.h"
//#include "System/IO/IOProcessor.h"
//#include "Application/Common/ContextTransport.h"
//#include "Application/ConfigServer/ConfigServerApp.h"
//#include "Application/ShardServer/ShardServerApp.h"
//
//#ifdef DEBUG
//#define VERSION_FMT_STRING "ScalienDB v" VERSION_STRING " (DEBUG build date " __DATE__ " " __TIME__ ")"
//#else
//#define VERSION_FMT_STRING "ScalienDB v" VERSION_STRING
//#endif
//
//void InitLog();
//bool IsController();
//void InitContextTransport();
//
//int main(int argc, char** argv)
//{
//    Application*        app;
//    bool                isController;
//
//    if (argc < 2)
//        STOP_FAIL(1, "Config file argument not given, exiting");
//
//    if (!configFile.Init(argv[1]))
//        STOP_FAIL(1, "Invalid config file (%s)", argv[1]);
//
//    InitLog();
//    StartClock();
//    IOProcessor::Init(configFile.GetIntValue("io.maxfd", 1024), true);
//    InitContextTransport();
//
//    isController = IsController();
//    Log_Message(VERSION_FMT_STRING " started as %s", isController ? "CONTROLLER" : "SHARD SERVER");
//    if (isController)
//        app = new ConfigServerApp;
//    else
//        app = new ShardServerApp;
//
//    app->Init();
//
//    EventLoop::Init();
//    EventLoop::Run();
//    EventLoop::Shutdown();
//
//    app->Shutdown();
//    delete app;
//
//    IOProcessor::Shutdown();
//    DEFAULT_BUFFERPOOL->Shutdown();
//    StopClock();
//    configFile.Shutdown();
//    Log_Shutdown();
//}
//
//void InitLog()
//{
//    int logTargets;
//
//    logTargets = 0;
//    if (configFile.GetListNum("log.targets") == 0)
//        logTargets = LOG_TARGET_STDOUT;
//
//    for (int i = 0; i < configFile.GetListNum("log.targets"); i++)
//    {
//        if (strcmp(configFile.GetListValue("log.targets", i, ""), "file") == 0)
//        {
//            logTargets |= LOG_TARGET_FILE;
//            Log_SetOutputFile(configFile.GetValue("log.file", NULL),
//            configFile.GetBoolValue("log.truncate", false));
//        }
//        if (strcmp(configFile.GetListValue("log.targets", i, NULL), "stdout") == 0)
//            logTargets |= LOG_TARGET_STDOUT;
//        if (strcmp(configFile.GetListValue("log.targets", i, NULL), "stderr") == 0)
//            logTargets |= LOG_TARGET_STDERR;
//    }
//    Log_SetTarget(logTargets);
//
//    Log_SetTrace(configFile.GetBoolValue("log.trace", false));
//    Log_SetTimestamping(configFile.GetBoolValue("log.timestamping", false));
//}
//
//bool IsController()
//{
//    const char* role;
//
//    role = configFile.GetValue("role", "");
//    if (strcmp(role, "controller") == 0)
//        return true;
//    else
//        return false;
//}
//
//void InitContextTransport()
//{
//    const char*     str;
//    Endpoint        endpoint;
//
//    // set my endpoint
//    str = configFile.GetValue("endpoint", "");
//    if (str == 0)
//        ASSERT_FAIL();
//    endpoint.Set(str);
//    CONTEXT_TRANSPORT->Init(endpoint);
//}
<commit_msg>Fixed Main.cpp<commit_after>#include "Version.h"
#include "System/Config.h"
#include "System/Events/EventLoop.h"
#include "System/IO/IOProcessor.h"
#include "Application/Common/ContextTransport.h"
#include "Application/ConfigServer/ConfigServerApp.h"
#include "Application/ShardServer/ShardServerApp.h"

#ifdef DEBUG
#define VERSION_FMT_STRING "ScalienDB v" VERSION_STRING " (DEBUG build date " __DATE__ " " __TIME__ ")"
#else
#define VERSION_FMT_STRING "ScalienDB v" VERSION_STRING
#endif

void InitLog();
bool IsController();
void InitContextTransport();

int main(int argc, char** argv)
{
    Application* app;
    bool isController;

    if (argc < 2)
        STOP_FAIL(1, "Config file argument not given, exiting");

    if (!configFile.Init(argv[1]))
        STOP_FAIL(1, "Invalid config file (%s)", argv[1]);

    InitLog();
    StartClock();
    IOProcessor::Init(configFile.GetIntValue("io.maxfd", 1024), true);
    InitContextTransport();

    isController = IsController();
    Log_Message(VERSION_FMT_STRING " started as %s", isController ? "CONTROLLER" : "SHARD SERVER");
    if (isController)
        app = new ConfigServerApp;
    else
        app = new ShardServerApp;

    app->Init();

    EventLoop::Init();
    EventLoop::Run();
    EventLoop::Shutdown();

    app->Shutdown();
    delete app;

    IOProcessor::Shutdown();
    DEFAULT_BUFFERPOOL->Shutdown();
    StopClock();
    configFile.Shutdown();
    Log_Shutdown();
}

void InitLog()
{
    int logTargets;

    logTargets = 0;
    if (configFile.GetListNum("log.targets") == 0)
        logTargets = LOG_TARGET_STDOUT;

    for (int i = 0; i < configFile.GetListNum("log.targets"); i++)
    {
        if (strcmp(configFile.GetListValue("log.targets", i, ""), "file") == 0)
        {
            logTargets |= LOG_TARGET_FILE;
            Log_SetOutputFile(configFile.GetValue("log.file", NULL),
            configFile.GetBoolValue("log.truncate", false));
        }
        if (strcmp(configFile.GetListValue("log.targets", i, NULL), "stdout") == 0)
            logTargets |= LOG_TARGET_STDOUT;
        if (strcmp(configFile.GetListValue("log.targets", i, NULL), "stderr") == 0)
            logTargets |= LOG_TARGET_STDERR;
    }
    Log_SetTarget(logTargets);

    Log_SetTrace(configFile.GetBoolValue("log.trace", false));
    Log_SetTimestamping(configFile.GetBoolValue("log.timestamping", false));
}

bool IsController()
{
    const char* role;

    role = configFile.GetValue("role", "");
    if (strcmp(role, "controller") == 0)
        return true;
    else
        return false;
}

void InitContextTransport()
{
    const char* str;
    Endpoint endpoint;

    // set my endpoint
    str = configFile.GetValue("endpoint", "");
    if (str == 0)
        ASSERT_FAIL();
    endpoint.Set(str);
    CONTEXT_TRANSPORT->Init(endpoint);
}<|endoftext|>


<commit_before>/*******************************************************************************
GPU OPTIMIZED MONTE CARLO (GOMC) 2.40
Copyright (C) 2018  GOMC Group
A copy of the GNU General Public License can be found in the COPYRIGHT.txt
along with this program, also can be found at <http://www.gnu.org/licenses/>.
********************************************************************************/
#include "Simulation.h"
#include "GOMC_Config.h"    //For version number
#if GOMC_LIB_MPI
#include <mpi.h>
#include "ParallelTemperingPreprocessor.h"
#endif
#ifdef GOMC_CUDA
#include "cuda.h"
#include <cuda_runtime_api.h>
#endif
#include <iostream>
#include <ctime>

//find and include appropriate files for getHostname
#ifdef _WIN32
#include <Winsock2.h>
#define HOSTNAME
#elif defined(__linux__) || defined(__apple__) || defined(__FreeBSD__)
#include <unistd.h>
#include <sys/sysinfo.h>
#include <sys/utsname.h>
#define HOSTNAME
#endif

namespace
{
std::ostream& PrintTime(std::ostream& stream);
std::ostream& PrintHostname(std::ostream& stream);
std::ostream& PrintVersion(std::ostream& stream);
void PrintSimulationHeader();
void PrintSimulationFooter();
void PrintDebugMode();
bool CheckAndPrintEnsemble();
uint ReadNum(char *argv);
}

void PrintHardwareInfo();
#ifdef GOMC_CUDA
void PrintGPUHardwareInfo();
#endif

int main(int argc, char *argv[])
{
#if GOMC_LIB_MPI
  string inputFileStringMPI;
  fstream inputFileReaderMPI;
  MultiSim * multisim;
  int worldSize;
  int worldRank;
  ParallelTemperingPreprocessor pt;

  //std::streambuf * savedCOUT;
  //CHECK IF ARGS/FILE PROVIDED IN CMD LINE
  if (argc < 2) {
    std::cout << "Error: Input parameter file (*.dat or *.conf) not specified on command line!\n";
    exit(EXIT_FAILURE);
  } else {
    if(argc == 2) {
      //FIRST PARAMETER WILL BE FILE NAME
      inputFileStringMPI = argv[1];
    } else {
      //SECOND PARAMETER WILL BE FILE NAME
      inputFileStringMPI = argv[2];

      if(argv[1][0] == '+' && argv[1][1] == 'p') {
      // placeholder
      } else {
        std::cout << "Error: Undefined command to set number of threads!\n";
        std::cout << "Use +p# command to set number of threads.\n";
        exit(EXIT_FAILURE);
      }
    }

    //OPEN FILE
    inputFileReaderMPI.open(inputFileStringMPI.c_str(), ios::in | ios::out);

    //CHECK IF FILE IS OPENED...IF NOT OPENED EXCEPTION REASON FIRED
    if (!inputFileReaderMPI.is_open()) {
      std::cout << "Error: Cannot open/find " << inputFileStringMPI <<
                " in the directory provided!\n";
      exit(EXIT_FAILURE);
    }

    //CLOSE FILE TO NOW PASS TO SIMULATION
    inputFileReaderMPI.close();

    // Initialize the MPI environment
    MPI_Init(NULL, NULL);

    // Get the number of processes
    MPI_Comm_size(MPI_COMM_WORLD, &worldSize);

    // Get the rank of the process
    MPI_Comm_rank(MPI_COMM_WORLD, &worldRank);

    std::string pathToReplicaDirectory;
    if(pt.checkIfParallelTempering(inputFileStringMPI)){
      pt.checkIfValid(inputFileStringMPI);
      if(worldSize > pt.getNumberOfReplicas(inputFileStringMPI)){
        std::cout << "You may not request more processes (" << worldSize
          << ") than there are replicas(" << pt.getNumberOfReplicas(inputFileStringMPI) << ")! Exiting!\n";
      } else {
        #if ENSEMBLE == GCMC
        pathToReplicaDirectory = pt.setupReplicaDirectoriesAndRedirectSTDOUTToFile  ( pt.getMultiSimFolderName(inputFileStringMPI).c_str(),
                                                                                pt.getTemperature(inputFileStringMPI.c_str(), worldRank).c_str(),
                                                                                pt.getChemicalPotential(inputFileStringMPI.c_str(), worldRank).c_str()
                                                                                );
        #else
        pathToReplicaDirectory = pt.setupReplicaDirectoriesAndRedirectSTDOUTToFile  ( pt.getMultiSimFolderName(inputFileStringMPI).c_str(),
                                                                                pt.getTemperature(inputFileStringMPI.c_str(), worldRank).c_str()
                                                                                );
        #endif
        multisim = new MultiSim(worldSize, worldRank, pathToReplicaDirectory);
      }
    }
  }
#endif
#ifndef NDEBUG
  PrintDebugMode();
#endif
  PrintSimulationHeader();
  PrintHardwareInfo();
#ifdef GOMC_CUDA
  PrintGPUHardwareInfo();
#endif
  //Only run if valid ensemble was detected.
  if (CheckAndPrintEnsemble()) {
    //FOLLOWING LINES ADDED TO OBTAIN INPUT PARAMETER FILE
    string inputFileString;
    fstream inputFileReader;
    uint numThreads;

    //CHECK IF ARGS/FILE PROVIDED IN CMD LINE
    if (argc < 2) {
      std::cout << "Error: Input parameter file (*.dat or *.conf) not specified on command line!\n";
      exit(EXIT_FAILURE);
    } else {
      if(argc == 2) {
        //FIRST PARAMETER WILL BE FILE NAME
        inputFileString = argv[1];
        numThreads = 1;
      } else {
        //SECOND PARAMETER WILL BE FILE NAME
        inputFileString = argv[2];

        if(argv[1][0] == '+' && argv[1][1] == 'p') {
          numThreads = ReadNum(argv[1]);
        } else {
          std::cout << "Error: Undefined command to set number of threads!\n";
          std::cout << "Use +p# command to set number of threads.\n";
          exit(EXIT_FAILURE);
        }

      }
    }

    //SET NUMBER OF THREADS
#ifdef _OPENMP
    omp_set_num_threads(numThreads);
    printf("%-40s %-d \n", "Info: Number of threads", numThreads);
#else
    printf("%-40s %-d \n", "Info: Number of threads", 1);
#endif

    //OPEN FILE
    inputFileReader.open(inputFileString.c_str(), ios::in | ios::out);

    //CHECK IF FILE IS OPENED...IF NOT OPENED EXCEPTION REASON FIRED
    if (!inputFileReader.is_open()) {
      std::cout << "Error: Cannot open/find " << inputFileString <<
                " in the directory provided!\n";
      exit(EXIT_FAILURE);
    }

    //CLOSE FILE TO NOW PASS TO SIMULATION
    inputFileReader.close();

    //ONCE FILE FOUND PASS STRING TO SIMULATION CLASS TO READ AND
    //HANDLE PDB|PSF FILE
#if GOMC_LIB_MPI
    if(worldSize <= pt.getNumberOfReplicas(inputFileStringMPI)){
      Simulation sim(inputFileString.c_str(), multisim);
      sim.RunSimulation();
      PrintSimulationFooter();
      delete multisim;
    }
#else
    Simulation sim(inputFileString.c_str());
    sim.RunSimulation();
    PrintSimulationFooter();
#endif
  }
  #if GOMC_LIB_MPI
    MPI_Finalize();
    //std::cout.rdbuf(savedCOUT); //reset to standard output again
  #endif
  return 0;
}

namespace
{

void PrintSimulationHeader()
{
  std::cout << PrintVersion << '\n'
            << "Info: Start Time: " << PrintTime
#ifdef HOSTNAME
            << "Info: Host Name: " << PrintHostname
#endif
            << "\n";
}

bool CheckAndPrintEnsemble()
{
  bool healthy = true;
  std::cout << "Info: GOMC COMPILED TO RUN ";
#if ENSEMBLE == NVT
  std::cout << "CANONICAL (NVT)";
#elif ENSEMBLE == GEMC
  std::cout << "GIBBS";
#elif ENSEMBLE == GCMC
  std::cout << "GRAND CANONICAL";
#elif ENSEMBLE == NPT
  std::cout << "ISOBARIC-ISOTHERMAL";
#else
  std::cerr << "CRITICAL ERROR! Preprocessor value ENSEMBLE is "
            << "invalid or undefined." << std::endl
            << "Code will exit.";
  healthy = false;
#endif
  std::cout << " ENSEMBLE." << std::endl;
  return healthy;
}

void PrintDebugMode()
{
  std::cout << "################################################################################\n";
  std::cout << "########################## RUNNING GOMC IN DEBUG MODE ##########################\n";
  std::cout << "################################################################################\n";
}

void PrintSimulationFooter()
{
  std::cout << PrintVersion << '\n'
            << "Info: Completed at: " << PrintTime
            << "Info: On hostname: " << PrintHostname
            << '\n';
}

std::ostream& PrintVersion(std::ostream& stream)
{
  stream << "Info: GOMC Version " << GOMC_VERSION_MAJOR
         << '.' << GOMC_VERSION_MINOR;
  return stream;
}

std::ostream& PrintTime(std::ostream& stream)
{
  time_t timer;
  time(&timer);
  stream << asctime(localtime(&timer));
  return stream;
}

std::ostream& PrintHostname(std::ostream& stream)
{
#ifdef HOSTNAME
#ifdef _WIN32
  //setup WINSOCK
  WSADATA wsaData;
  WSAStartup(MAKEWORD(2, 0), &wsaData);
#endif

  const int maxNameLength = 80;
  char hostname[maxNameLength];
  gethostname(hostname, maxNameLength);
  //gethostname does not guarantee null termination
  hostname[maxNameLength - 1] = '\0';
  stream << hostname;

#ifdef _WIN32
  //teardown WINSOCK
  WSACleanup();
#endif
#else
  stream << "Info: Hostname Unavailable";
#endif
  return stream;
}

uint ReadNum(char *argv)
{
  uint thread = 0;

  for(uint i = 2; argv[i] != 0; i++) {
    thread = thread * 10 + (argv[i] - '0');
  }

  return thread;
}
}

void PrintHardwareInfo()
{
#ifdef __linux__
  struct sysinfo mem;
  const double megabyte = 1024 * 1024;
  struct utsname name;
  uname(&name);
  printf("CPU information:\n");
  std::cout << std::setprecision(1) << std::fixed;
  std::cout << "Info: Total number of CPUs: " << get_nprocs() << std::endl;
  std::cout << "Info: Total number of CPUs available: " << sysconf(_SC_NPROCESSORS_ONLN) << std::endl;
  std::cout << "Info: Model name:" << std::flush;
  if(system("awk -F: '/model name/ {print $2;exit}' /proc/cpuinfo") == -1)
    std::cout << "Error: Couldn't retrieve CPU information" << std::endl;
  std::cout << "Info: System name: " << name.sysname << std::endl;
  std::cout << "Info: Release: " << name.release << std::endl;
  std::cout << "Info: Version: " << name.version << std::endl;
  std::cout << "Info: Kernel Architecture: " << name.machine << std::endl;
  if(sysinfo(&mem) == 0) {
    std::cout << "Info: Total Ram: " << mem.totalram / megabyte << "MB" << std::endl;
    std::cout << "Info: Used Ram: " << mem.totalram / megabyte - mem.freeram / megabyte << "MB" << std::endl;
  }
  std::cout << "Info: Working in the current directory: " << get_current_dir_name();
  std::cout << std::endl;
#endif
}

#ifdef GOMC_CUDA
void PrintGPUHardwareInfo()
{
  int nDevices;
  int fast = 0;
  int fastIndex = 0;

  cudaGetDeviceCount(&nDevices);

  if(nDevices == 0) {
    printf("There are no available device(s) that support CUDA\n");
    exit(EXIT_FAILURE);
  }

  if(nDevices <= 4) {
    printf("GPU information:\n");
    for (int i = 0; i < nDevices; i++) {
      cudaDeviceProp prop;
      cudaGetDeviceProperties(&prop, i);
      printf("Info: Device Number: %d\n", i);
      printf("Info: Device name: %s\n", prop.name);
      printf("Info: Memory Clock Rate (KHz): %d\n", prop.memoryClockRate);
      printf("Info: Memory Bus Width (bits): %d\n", prop.memoryBusWidth);
      printf("Info: Peak Memory Bandwidth (GB/s): %f\n",
             2.0 * prop.memoryClockRate * (prop.memoryBusWidth / 8) / 1.0e6);
      if( prop.memoryClockRate > fast) {
        fast =  prop.memoryClockRate;
        fastIndex = i;
      }
    }
  }
  cudaSetDevice(fastIndex);
  printf("Info: Using Device Number: %d\n", fastIndex);
}
#endif
<commit_msg>Consolidated MPI macro at end of Main<commit_after>/*******************************************************************************
GPU OPTIMIZED MONTE CARLO (GOMC) 2.40
Copyright (C) 2018  GOMC Group
A copy of the GNU General Public License can be found in the COPYRIGHT.txt
along with this program, also can be found at <http://www.gnu.org/licenses/>.
********************************************************************************/
#include "Simulation.h"
#include "GOMC_Config.h"    //For version number
#if GOMC_LIB_MPI
#include <mpi.h>
#include "ParallelTemperingPreprocessor.h"
#endif
#ifdef GOMC_CUDA
#include "cuda.h"
#include <cuda_runtime_api.h>
#endif
#include <iostream>
#include <ctime>

//find and include appropriate files for getHostname
#ifdef _WIN32
#include <Winsock2.h>
#define HOSTNAME
#elif defined(__linux__) || defined(__apple__) || defined(__FreeBSD__)
#include <unistd.h>
#include <sys/sysinfo.h>
#include <sys/utsname.h>
#define HOSTNAME
#endif

namespace
{
std::ostream& PrintTime(std::ostream& stream);
std::ostream& PrintHostname(std::ostream& stream);
std::ostream& PrintVersion(std::ostream& stream);
void PrintSimulationHeader();
void PrintSimulationFooter();
void PrintDebugMode();
bool CheckAndPrintEnsemble();
uint ReadNum(char *argv);
}

void PrintHardwareInfo();
#ifdef GOMC_CUDA
void PrintGPUHardwareInfo();
#endif

int main(int argc, char *argv[])
{
#if GOMC_LIB_MPI
  string inputFileStringMPI;
  fstream inputFileReaderMPI;
  MultiSim * multisim;
  int worldSize;
  int worldRank;
  ParallelTemperingPreprocessor pt;

  //std::streambuf * savedCOUT;
  //CHECK IF ARGS/FILE PROVIDED IN CMD LINE
  if (argc < 2) {
    std::cout << "Error: Input parameter file (*.dat or *.conf) not specified on command line!\n";
    exit(EXIT_FAILURE);
  } else {
    if(argc == 2) {
      //FIRST PARAMETER WILL BE FILE NAME
      inputFileStringMPI = argv[1];
    } else {
      //SECOND PARAMETER WILL BE FILE NAME
      inputFileStringMPI = argv[2];

      if(argv[1][0] == '+' && argv[1][1] == 'p') {
      // placeholder
      } else {
        std::cout << "Error: Undefined command to set number of threads!\n";
        std::cout << "Use +p# command to set number of threads.\n";
        exit(EXIT_FAILURE);
      }
    }

    //OPEN FILE
    inputFileReaderMPI.open(inputFileStringMPI.c_str(), ios::in | ios::out);

    //CHECK IF FILE IS OPENED...IF NOT OPENED EXCEPTION REASON FIRED
    if (!inputFileReaderMPI.is_open()) {
      std::cout << "Error: Cannot open/find " << inputFileStringMPI <<
                " in the directory provided!\n";
      exit(EXIT_FAILURE);
    }

    //CLOSE FILE TO NOW PASS TO SIMULATION
    inputFileReaderMPI.close();

    // Initialize the MPI environment
    MPI_Init(NULL, NULL);

    // Get the number of processes
    MPI_Comm_size(MPI_COMM_WORLD, &worldSize);

    // Get the rank of the process
    MPI_Comm_rank(MPI_COMM_WORLD, &worldRank);

    std::string pathToReplicaDirectory;
    if(pt.checkIfParallelTempering(inputFileStringMPI)){
      pt.checkIfValid(inputFileStringMPI);
      if(worldSize > pt.getNumberOfReplicas(inputFileStringMPI)){
        std::cout << "You may not request more processes (" << worldSize
          << ") than there are replicas(" << pt.getNumberOfReplicas(inputFileStringMPI) << ")! Exiting!\n";
      } else {
        #if ENSEMBLE == GCMC
        pathToReplicaDirectory = pt.setupReplicaDirectoriesAndRedirectSTDOUTToFile  ( pt.getMultiSimFolderName(inputFileStringMPI).c_str(),
                                                                                pt.getTemperature(inputFileStringMPI.c_str(), worldRank).c_str(),
                                                                                pt.getChemicalPotential(inputFileStringMPI.c_str(), worldRank).c_str()
                                                                                );
        #else
        pathToReplicaDirectory = pt.setupReplicaDirectoriesAndRedirectSTDOUTToFile  ( pt.getMultiSimFolderName(inputFileStringMPI).c_str(),
                                                                                pt.getTemperature(inputFileStringMPI.c_str(), worldRank).c_str()
                                                                                );
        #endif
        multisim = new MultiSim(worldSize, worldRank, pathToReplicaDirectory);
      }
    }
  }
#endif
#ifndef NDEBUG
  PrintDebugMode();
#endif
  PrintSimulationHeader();
  PrintHardwareInfo();
#ifdef GOMC_CUDA
  PrintGPUHardwareInfo();
#endif
  //Only run if valid ensemble was detected.
  if (CheckAndPrintEnsemble()) {
    //FOLLOWING LINES ADDED TO OBTAIN INPUT PARAMETER FILE
    string inputFileString;
    fstream inputFileReader;
    uint numThreads;

    //CHECK IF ARGS/FILE PROVIDED IN CMD LINE
    if (argc < 2) {
      std::cout << "Error: Input parameter file (*.dat or *.conf) not specified on command line!\n";
      exit(EXIT_FAILURE);
    } else {
      if(argc == 2) {
        //FIRST PARAMETER WILL BE FILE NAME
        inputFileString = argv[1];
        numThreads = 1;
      } else {
        //SECOND PARAMETER WILL BE FILE NAME
        inputFileString = argv[2];

        if(argv[1][0] == '+' && argv[1][1] == 'p') {
          numThreads = ReadNum(argv[1]);
        } else {
          std::cout << "Error: Undefined command to set number of threads!\n";
          std::cout << "Use +p# command to set number of threads.\n";
          exit(EXIT_FAILURE);
        }

      }
    }

    //SET NUMBER OF THREADS
#ifdef _OPENMP
    omp_set_num_threads(numThreads);
    printf("%-40s %-d \n", "Info: Number of threads", numThreads);
#else
    printf("%-40s %-d \n", "Info: Number of threads", 1);
#endif

    //OPEN FILE
    inputFileReader.open(inputFileString.c_str(), ios::in | ios::out);

    //CHECK IF FILE IS OPENED...IF NOT OPENED EXCEPTION REASON FIRED
    if (!inputFileReader.is_open()) {
      std::cout << "Error: Cannot open/find " << inputFileString <<
                " in the directory provided!\n";
      exit(EXIT_FAILURE);
    }

    //CLOSE FILE TO NOW PASS TO SIMULATION
    inputFileReader.close();

    //ONCE FILE FOUND PASS STRING TO SIMULATION CLASS TO READ AND
    //HANDLE PDB|PSF FILE
#if GOMC_LIB_MPI
    if(worldSize <= pt.getNumberOfReplicas(inputFileStringMPI)){
      Simulation sim(inputFileString.c_str(), multisim);
      sim.RunSimulation();
      PrintSimulationFooter();
      delete multisim;
      MPI_Finalize();
    } else {
      MPI_Finalize();
    }
#else
    Simulation sim(inputFileString.c_str());
    sim.RunSimulation();
    PrintSimulationFooter();
#endif
  }
  return 0;
}

namespace
{

void PrintSimulationHeader()
{
  std::cout << PrintVersion << '\n'
            << "Info: Start Time: " << PrintTime
#ifdef HOSTNAME
            << "Info: Host Name: " << PrintHostname
#endif
            << "\n";
}

bool CheckAndPrintEnsemble()
{
  bool healthy = true;
  std::cout << "Info: GOMC COMPILED TO RUN ";
#if ENSEMBLE == NVT
  std::cout << "CANONICAL (NVT)";
#elif ENSEMBLE == GEMC
  std::cout << "GIBBS";
#elif ENSEMBLE == GCMC
  std::cout << "GRAND CANONICAL";
#elif ENSEMBLE == NPT
  std::cout << "ISOBARIC-ISOTHERMAL";
#else
  std::cerr << "CRITICAL ERROR! Preprocessor value ENSEMBLE is "
            << "invalid or undefined." << std::endl
            << "Code will exit.";
  healthy = false;
#endif
  std::cout << " ENSEMBLE." << std::endl;
  return healthy;
}

void PrintDebugMode()
{
  std::cout << "################################################################################\n";
  std::cout << "########################## RUNNING GOMC IN DEBUG MODE ##########################\n";
  std::cout << "################################################################################\n";
}

void PrintSimulationFooter()
{
  std::cout << PrintVersion << '\n'
            << "Info: Completed at: " << PrintTime
            << "Info: On hostname: " << PrintHostname
            << '\n';
}

std::ostream& PrintVersion(std::ostream& stream)
{
  stream << "Info: GOMC Version " << GOMC_VERSION_MAJOR
         << '.' << GOMC_VERSION_MINOR;
  return stream;
}

std::ostream& PrintTime(std::ostream& stream)
{
  time_t timer;
  time(&timer);
  stream << asctime(localtime(&timer));
  return stream;
}

std::ostream& PrintHostname(std::ostream& stream)
{
#ifdef HOSTNAME
#ifdef _WIN32
  //setup WINSOCK
  WSADATA wsaData;
  WSAStartup(MAKEWORD(2, 0), &wsaData);
#endif

  const int maxNameLength = 80;
  char hostname[maxNameLength];
  gethostname(hostname, maxNameLength);
  //gethostname does not guarantee null termination
  hostname[maxNameLength - 1] = '\0';
  stream << hostname;

#ifdef _WIN32
  //teardown WINSOCK
  WSACleanup();
#endif
#else
  stream << "Info: Hostname Unavailable";
#endif
  return stream;
}

uint ReadNum(char *argv)
{
  uint thread = 0;

  for(uint i = 2; argv[i] != 0; i++) {
    thread = thread * 10 + (argv[i] - '0');
  }

  return thread;
}
}

void PrintHardwareInfo()
{
#ifdef __linux__
  struct sysinfo mem;
  const double megabyte = 1024 * 1024;
  struct utsname name;
  uname(&name);
  printf("CPU information:\n");
  std::cout << std::setprecision(1) << std::fixed;
  std::cout << "Info: Total number of CPUs: " << get_nprocs() << std::endl;
  std::cout << "Info: Total number of CPUs available: " << sysconf(_SC_NPROCESSORS_ONLN) << std::endl;
  std::cout << "Info: Model name:" << std::flush;
  if(system("awk -F: '/model name/ {print $2;exit}' /proc/cpuinfo") == -1)
    std::cout << "Error: Couldn't retrieve CPU information" << std::endl;
  std::cout << "Info: System name: " << name.sysname << std::endl;
  std::cout << "Info: Release: " << name.release << std::endl;
  std::cout << "Info: Version: " << name.version << std::endl;
  std::cout << "Info: Kernel Architecture: " << name.machine << std::endl;
  if(sysinfo(&mem) == 0) {
    std::cout << "Info: Total Ram: " << mem.totalram / megabyte << "MB" << std::endl;
    std::cout << "Info: Used Ram: " << mem.totalram / megabyte - mem.freeram / megabyte << "MB" << std::endl;
  }
  std::cout << "Info: Working in the current directory: " << get_current_dir_name();
  std::cout << std::endl;
#endif
}

#ifdef GOMC_CUDA
void PrintGPUHardwareInfo()
{
  int nDevices;
  int fast = 0;
  int fastIndex = 0;

  cudaGetDeviceCount(&nDevices);

  if(nDevices == 0) {
    printf("There are no available device(s) that support CUDA\n");
    exit(EXIT_FAILURE);
  }

  if(nDevices <= 4) {
    printf("GPU information:\n");
    for (int i = 0; i < nDevices; i++) {
      cudaDeviceProp prop;
      cudaGetDeviceProperties(&prop, i);
      printf("Info: Device Number: %d\n", i);
      printf("Info: Device name: %s\n", prop.name);
      printf("Info: Memory Clock Rate (KHz): %d\n", prop.memoryClockRate);
      printf("Info: Memory Bus Width (bits): %d\n", prop.memoryBusWidth);
      printf("Info: Peak Memory Bandwidth (GB/s): %f\n",
             2.0 * prop.memoryClockRate * (prop.memoryBusWidth / 8) / 1.0e6);
      if( prop.memoryClockRate > fast) {
        fast =  prop.memoryClockRate;
        fastIndex = i;
      }
    }
  }
  cudaSetDevice(fastIndex);
  printf("Info: Using Device Number: %d\n", fastIndex);
}
#endif
<|endoftext|>