<commit_before>#include <RayTracer/RayTracer.h>

// system header
#include <RayTracer/windows_includes.h>
#include <iostream>
#include <future>
#include <vector>

// other framework header
#include <concurrent_queue.h>

// project header
#include <RayTracer/Scene/Scene.h>
#include <RayTracer/Scene/Camera.h>
#include <RayTracer/Scene/Primitives/Primitive.h>
#include <RayTracer/SceneReader/SceneReader.h>
#include <String/StringHelper.h>

// class definition
RayTracer::RayTracer()
    : scene_()
{}

RayTracer::~RayTracer()
{}

void RayTracer::load(std::string scene_file) {
    try {
        scene_ = loadScene(scene_file);

        // TODO: Compute a Axis aligned bounding box
        //       for each Primitive and
        //       construct some kind of hirarchy tree from them
        //       for example a 'fixed' grid (divide scene bounding box
        //       into 20*20 boxes)

        scene_->createAABB();
    } catch (std::exception& e) {
        std::cout << e.what() << std::endl;
        scene_ = nullptr;
    }
}

void RayTracer::renderInto(IRenderTarget* render_target) {
    if (nullptr == scene_)
        return;

    if (!scene_->_camera) {
        std::cout << "No Camera detected! Aborting..." << std::endl;
        return;
    }

    auto& camera = *scene_->_camera;
    IRenderTarget& target = *render_target;

    // if the scene definition has a size
    // then initialize the target accordingly
    if (scene_->hasSize()) {
        // set size on target
        auto& size = scene_->_size;
        target.init(size.width, size.height);
    }

    camera.initFov(static_cast<float>(target.width()), static_cast<float>(target.height()));

    SYSTEM_INFO sysinfo;
    GetSystemInfo(&sysinfo);
    auto numCPU = sysinfo.dwNumberOfProcessors;

#ifdef MULTICORE_DISABLED
    numCPU = 1;
#endif

    // decrease process priority to prevent system hangs
    /*
    REALTIME_PRIORITY_CLASS------highest
    HIGH_PRIORITY_CLASS
    ABOVE_NORMAL_PRIORITY_CLASS
    NORMAL_PRIORITY_CLASS
    BELOW_NORMAL_PRIORITY_CLASS
    IDLE_PRIORITY_CLASS------lowest
    */
    SetPriorityClass(GetCurrentProcess(), BELOW_NORMAL_PRIORITY_CLASS);

    // load all samples
    // TODO: split into tiles (32x32) and package them that each thread can work on one package
    //       use a concurrent_queue
    typedef std::vector<Sample> SamplePack;
    concurrency::concurrent_queue<SamplePack> sample_packs;

    const auto Packsize = 32u;

    // generating sample packs
    SamplePack pack;
    Sample sample;
    bool clear = false;
    while(target.getSample(sample)) {
        pack.push_back(sample);
        clear = false;
        if (pack.size() == Packsize*Packsize) {
            sample_packs.push(SamplePack(pack));
            pack.clear();
            clear = true;
        }
    }
    if (!clear)
        sample_packs.push(SamplePack(pack));

    auto thread_func = [&](){
        Ray ray;
        SamplePack pack;
        while (sample_packs.try_pop(pack)) {
            for (auto& sample : pack) {
                camera.generateRay(sample, ray);

                Intersection Hit = scene_->trace(ray, 0);

                target.commit(sample, Hit.color);
            }
        }
    };

    // start rendering
    auto start = std::chrono::system_clock::now();
    std::vector<std::future<void>> futs;
    while (numCPU > 0) {
        // start thread
        futs.push_back(std::async(thread_func));
        --numCPU;
    }

    for (auto& fut : futs)
        fut.get();

    target.done();

    // rendering done!
    auto diff = std::chrono::system_clock::now() - start;
    render_duration_ = std::chrono::duration_cast<std::chrono::milliseconds>(diff);
}

std::chrono::milliseconds RayTracer::getRenderDuration() const {
    return render_duration_;
}

void RayTracer::stop() {

}
<commit_msg>constructing the AABBs is now part of the timing<commit_after>#include <RayTracer/RayTracer.h>

// system header
#include <RayTracer/windows_includes.h>
#include <iostream>
#include <future>
#include <vector>

// other framework header
#include <concurrent_queue.h>

// project header
#include <RayTracer/Scene/Scene.h>
#include <RayTracer/Scene/Camera.h>
#include <RayTracer/Scene/Primitives/Primitive.h>
#include <RayTracer/SceneReader/SceneReader.h>
#include <String/StringHelper.h>

// class definition
RayTracer::RayTracer()
    : scene_()
{}

RayTracer::~RayTracer()
{}

void RayTracer::load(std::string scene_file) {
    try {
        scene_ = loadScene(scene_file);
    } catch (std::exception& e) {
        std::cout << e.what() << std::endl;
        scene_ = nullptr;
    }
}

void RayTracer::renderInto(IRenderTarget* render_target) {
    if (nullptr == scene_)
        return;

    if (!scene_->_camera) {
        std::cout << "No Camera detected! Aborting..." << std::endl;
        return;
    }

    auto& camera = *scene_->_camera;
    IRenderTarget& target = *render_target;

    // if the scene definition has a size
    // then initialize the target accordingly
    if (scene_->hasSize()) {
        // set size on target
        auto& size = scene_->_size;
        target.init(size.width, size.height);
    }

    camera.initFov(static_cast<float>(target.width()), static_cast<float>(target.height()));

    SYSTEM_INFO sysinfo;
    GetSystemInfo(&sysinfo);
    auto numCPU = sysinfo.dwNumberOfProcessors;

#ifdef MULTICORE_DISABLED
    numCPU = 1;
#endif

    // decrease process priority to prevent system hangs
    /*
    REALTIME_PRIORITY_CLASS------highest
    HIGH_PRIORITY_CLASS
    ABOVE_NORMAL_PRIORITY_CLASS
    NORMAL_PRIORITY_CLASS
    BELOW_NORMAL_PRIORITY_CLASS
    IDLE_PRIORITY_CLASS------lowest
    */
    SetPriorityClass(GetCurrentProcess(), BELOW_NORMAL_PRIORITY_CLASS);

    // load all samples
    // TODO: split into tiles (32x32) and package them that each thread can work on one package
    //       use a concurrent_queue
    typedef std::vector<Sample> SamplePack;
    concurrency::concurrent_queue<SamplePack> sample_packs;

    const auto Packsize = 32u;

    // generating sample packs
    SamplePack pack;
    Sample sample;
    bool clear = false;
    while(target.getSample(sample)) {
        pack.push_back(sample);
        clear = false;
        if (pack.size() == Packsize*Packsize) {
            sample_packs.push(SamplePack(pack));
            pack.clear();
            clear = true;
        }
    }
    if (!clear)
        sample_packs.push(SamplePack(pack));

    auto thread_func = [&](){
        Ray ray;
        SamplePack pack;
        while (sample_packs.try_pop(pack)) {
            for (auto& sample : pack) {
                camera.generateRay(sample, ray);

                Intersection Hit = scene_->trace(ray, 0);

                target.commit(sample, Hit.color);
            }
        }
    };

    // start rendering and timing
    auto start = std::chrono::system_clock::now();

    // Compute Axis aligned bounding boxes
    // for each Primitive and
    // construct some kind of hirarchy tree from them
    // for example a 'fixed' grid (divide scene bounding box into 10*10*10 boxes)
    scene_->createAABB();

    std::vector<std::future<void>> futs;
    while (numCPU > 0) {
        // start thread
        futs.push_back(std::async(thread_func));
        --numCPU;
    }

    for (auto& fut : futs)
        fut.get();

    target.done();

    // rendering done!
    auto diff = std::chrono::system_clock::now() - start;
    render_duration_ = std::chrono::duration_cast<std::chrono::milliseconds>(diff);
}

std::chrono::milliseconds RayTracer::getRenderDuration() const {
    return render_duration_;
}

void RayTracer::stop() {

}
<|endoftext|>


<commit_before>//
//  RefractAPI.cc
//  drafter
//
//  Created by Jiri Kratochvil on 31/07/15.
//  Copyright (c) 2015 Apiary Inc. All rights reserved.
//

#include "StringUtility.h"
#include "BlueprintUtility.h"

#include "RefractAPI.h"
#include "refract/Element.h"
#include "refract/Registry.h"
#include "refract/Visitors.h"

namespace drafter {

    // Forward Declarations
    refract::IElement* ElementToRefract(const snowcrash::Element& element);

    namespace {

        typedef std::vector<refract::IElement*> RefractElements;

        template <typename T>
        refract::ArrayElement* CreateArrayElement(const T& content)
        {
            refract::ArrayElement* array = new refract::ArrayElement;
            array->push_back(refract::IElement::Create(content));
            return array;
        }

        template <typename T>
        bool IsNull(const T* ptr)
        {
            return ptr == NULL;
        }
    }

    refract::IElement* MetadataToRefract(const snowcrash::Metadata metadata)
    {
        refract::MemberElement* element = new refract::MemberElement;

        element->meta["classes"] = CreateArrayElement("user");
        element->meta["classes"].renderType(refract::IElement::rCompact);
        element->set(refract::IElement::Create(metadata.first), refract::IElement::Create(metadata.second));
        element->renderType(refract::IElement::rFull);

        return element;
    }

    refract::IElement* MetadataCollectionToRefract(const snowcrash::MetadataCollection metadata)
    {
        refract::ArrayElement* element = new refract::ArrayElement;
        RefractElements content;

        std::transform(metadata.begin(), metadata.end(), std::back_inserter(content), MetadataToRefract);
        element->set(content);
        element->renderType(refract::IElement::rCompact);

        return element;
    }

    refract::IElement* CopyToRefract(const std::string& copy)
    {
        if (copy.empty()) {
            return NULL;
        }

        refract::IElement* element = refract::IElement::Create(copy);
        element->element("copy");

        return element;
    }

    template<typename T>
    refract::IElement* ParameterValuesToRefract(const snowcrash::Parameter& parameter)
    {
        refract::ArrayElement* element = new refract::ArrayElement;
        RefractElements content;

        element->element("enum");

        if (!parameter.exampleValue.empty()) {
            element->attributes["samples"] = CreateArrayElement(LiteralTo<T>(parameter.exampleValue));
        }

        for (snowcrash::Values::const_iterator it = parameter.values.begin();
             it != parameter.values.end();
             ++it) {

            content.push_back(refract::IElement::Create(LiteralTo<T>(*it)));
        }

        element->set(content);

        return element;
    }

    refract::IElement* ParameterToRefract(const snowcrash::Parameter& parameter)
    {
        refract::MemberElement* element = new refract::MemberElement;
        refract::IElement *value, *defaultValue;

        // Parameter type
        if (parameter.type == "boolean") {
            value = refract::IElement::Create(LiteralTo<bool>(parameter.exampleValue));
            defaultValue = refract::IElement::Create(LiteralTo<bool>(parameter.defaultValue));
        }
        else if (parameter.type == "number") {
            value = refract::IElement::Create(LiteralTo<double>(parameter.exampleValue));
            defaultValue = refract::IElement::Create(LiteralTo<double>(parameter.defaultValue));
        }
        else {
            value = refract::IElement::Create(parameter.exampleValue);
            defaultValue = refract::IElement::Create(parameter.defaultValue);
        }

        // Values
        if (!parameter.values.empty()) {
            if (parameter.type == "boolean") {
                value = ParameterValuesToRefract<bool>(parameter);
            }
            else if (parameter.type == "number") {
                value = ParameterValuesToRefract<double>(parameter);
            }
            else {
                value = ParameterValuesToRefract<std::string>(parameter);
            }
        }

        // Default Value
        if (!parameter.defaultValue.empty()) {
            value->attributes["default"] = defaultValue;
        }

        element->set(refract::IElement::Create(parameter.name), value);
        element->meta["description"] = refract::IElement::Create(parameter.description);

        // Parameter use
        if (parameter.use == snowcrash::RequiredParameterUse || parameter.use == snowcrash::OptionalParameterUse) {
            refract::ArrayElement* typeAttributes = new refract::ArrayElement;

            typeAttributes->push_back(refract::IElement::Create(parameter.use == snowcrash::RequiredParameterUse ? "required" : "optional"));
            element->attributes["typeAttributes"] = typeAttributes;
        }

        return element;
    }

    refract::IElement* ParametersToRefract(const snowcrash::Parameters& parameters)
    {
        refract::ObjectElement* element = new refract::ObjectElement;
        RefractElements content;

        element->element("hrefVariables");
        std::transform(parameters.begin(), parameters.end(), std::back_inserter(content), ParameterToRefract);
        element->renderType(refract::IElement::rFull);

        element->set(content);

        return element;
    }

    refract::IElement* HeaderToRefract(const snowcrash::Header& header)
    {
        refract::MemberElement* element = new refract::MemberElement;
        element->set(refract::IElement::Create(header.first), refract::IElement::Create(header.second));

        return element;
    }

    refract::IElement* HeadersToRefract(const snowcrash::Headers& headers)
    {
        refract::ObjectElement* element = new refract::ObjectElement;
        RefractElements content;

        element->element("httpHeaders");
        std::transform(headers.begin(), headers.end(), std::back_inserter(content), HeaderToRefract);
        element->renderType(refract::IElement::rFull);

        element->set(content);

        return element;
    }

    refract::IElement* AssetToRefract(const snowcrash::Asset& asset, const std::string& contentType, bool messageBody = true)
    {
        if (asset.empty()) {
            return NULL;
        }

        refract::IElement* element = refract::IElement::Create(asset);

        element->element("asset");
        element->meta["classes"] = refract::ArrayElement::Create(messageBody ? "messageBody" : "messageSchema");

        if (!contentType.empty()) {
            element->attributes["contentType"] = refract::IElement::Create(contentType);
        }

        return element;
    }

    refract::IElement* PayloadToRefract(const snowcrash::Payload* payload, const snowcrash::HTTPMethod& method = "")
    {
        refract::ArrayElement* element = new refract::ArrayElement;
        RefractElements content;

        // Use HTTP method to recognize if request or response
        if (method.empty()) {
            element->element("httpResponse");

            if (payload != NULL && !payload->name.empty()) {
                element->attributes["statusCode"] = refract::IElement::Create(payload->name);
            }
        }
        else {
            element->element("httpRequest");
            element->attributes["method"] = refract::IElement::Create(method);

            if (payload != NULL) {
                element->attributes["title"] = refract::IElement::Create(payload->name);
            }

            // FIXME: Expand href
        }

        // If no payload, return immediately
        if (payload == NULL) {
            element->set(content);
            return element;
        }

        if (!payload->headers.empty()) {
            element->attributes["headers"] = HeadersToRefract(payload->headers);
        }

        content.push_back(CopyToRefract(payload->description));
        content.push_back(DataStructureToRefract(payload->attributes));

        // Get content type
        std::string contentType = "";
        snowcrash::Headers::const_iterator it;

        it = std::find_if(payload->headers.begin(),
                          payload->headers.end(),
                          std::bind2nd(snowcrash::MatchFirstWith<snowcrash::Header, std::string, snowcrash::IEqual<std::string> >(),
                                       snowcrash::HTTPHeaderName::ContentType));

        if (it != payload->headers.end()) {
            contentType = it->second;
        }

        // Assets
        content.push_back(AssetToRefract(payload->body, contentType));
        content.push_back(AssetToRefract(payload->schema, contentType, false));

        // Remove NULL elements
        content.erase(std::remove_if(content.begin(), content.end(), IsNull<refract::IElement>), content.end());
        element->set(content);

        return element;
    }

    refract::IElement* TransactionToRefract(const snowcrash::TransactionExample& transaction,
                                            const snowcrash::HTTPMethod& method,
                                            const snowcrash::Request* request = NULL,
                                            const snowcrash::Response* response = NULL)
    {
        refract::ArrayElement* element = new refract::ArrayElement;
        RefractElements content;

        element->element("httpTransaction");
        content.push_back(CopyToRefract(transaction.description));

        content.push_back(PayloadToRefract(request, method));
        content.push_back(PayloadToRefract(response));

        // Remove NULL elements
        content.erase(std::remove_if(content.begin(), content.end(), IsNull<refract::IElement>), content.end());
        element->set(content);

        return element;
    }

    refract::IElement* ActionToRefract(const snowcrash::Action& action)
    {
        refract::ArrayElement* element = new refract::ArrayElement;
        RefractElements content;

        element->element("transition");
        element->meta["title"] = refract::IElement::Create(action.name);

        if (!action.relation.str.empty()) {
            element->attributes["relation"] = refract::IElement::Create(action.relation.str);
        }

        if (!action.uriTemplate.empty()) {
            element->attributes["href"] = refract::IElement::Create(action.uriTemplate);
        }

        if (!action.parameters.empty()) {
            element->attributes["hrefVariables"] = ParametersToRefract(action.parameters);
        }

        if (!action.attributes.empty()) {
            refract::IElement* dataStructure = DataStructureToRefract(action.attributes);
            dataStructure->renderType(refract::IElement::rFull);
            element->attributes["data"] = dataStructure;
        }

        content.push_back(CopyToRefract(action.description));

        for (snowcrash::TransactionExamples::const_iterator it = action.examples.begin();
             it != action.examples.end();
             ++it) {

            // When there are only responses
            if (it->requests.empty() && !it->responses.empty()) {

                for (snowcrash::Responses::const_iterator tmpResIt = it->responses.begin();
                     tmpResIt != it->responses.end();
                     ++tmpResIt) {

                    content.push_back(TransactionToRefract(*it, action.method, NULL, &*tmpResIt));
                }
            }

            // When there are only requests or both responses and requests
            for (snowcrash::Requests::const_iterator reqIt = it->requests.begin();
                 reqIt != it->requests.end();
                 ++reqIt) {

                if (it->responses.empty()) {
                    content.push_back(TransactionToRefract(*it, action.method, &*reqIt));
                }

                for (snowcrash::Responses::const_iterator resIt = it->responses.begin();
                     resIt != it->responses.end();
                     ++resIt) {

                    content.push_back(TransactionToRefract(*it, action.method, &*reqIt, &*resIt));
                }
            }
        }

        // Remove NULL elements
        content.erase(std::remove_if(content.begin(), content.end(), IsNull<refract::IElement>), content.end());
        element->set(content);

        return element;
    }

    refract::IElement* ResourceToRefract(const snowcrash::Resource& resource)
    {
        refract::ArrayElement* element = new refract::ArrayElement;
        RefractElements content;

        element->element("resource");
        element->meta["title"] = refract::IElement::Create(resource.name);
        element->attributes["href"] = refract::IElement::Create(resource.uriTemplate);

        if (!resource.parameters.empty()) {
            element->attributes["hrefVariables"] = ParametersToRefract(resource.parameters);
        }

        content.push_back(CopyToRefract(resource.description));
        content.push_back(DataStructureToRefract(resource.attributes));

        std::transform(resource.actions.begin(), resource.actions.end(), std::back_inserter(content), ActionToRefract);

        // Remove NULL elements
        content.erase(std::remove_if(content.begin(), content.end(), IsNull<refract::IElement>), content.end());
        element->set(content);

        return element;
    }

    refract::IElement* CategoryToRefract(const snowcrash::Element& element)
    {
        refract::ArrayElement* category = new refract::ArrayElement;
        RefractElements content;

        category->element("category");

        if (element.category == snowcrash::Element::ResourceGroupCategory) {
            category->meta["classes"] = CreateArrayElement("resourceGroup");
            category->meta["title"] = refract::IElement::Create(element.attributes.name);
        }
        else if (element.category == snowcrash::Element::DataStructureGroupCategory) {
            category->meta["classes"] = CreateArrayElement("dataStructures");
        }

        snowcrash::Elements elements = element.content.elements();
        std::transform(elements.begin(), elements.end(), std::back_inserter(content), ElementToRefract);

        // Remove NULL elements
        content.erase(std::remove_if(content.begin(), content.end(), IsNull<refract::IElement>), content.end());
        category->set(content);

        return category;
    }

    refract::IElement* ElementToRefract(const snowcrash::Element& element)
    {
        switch (element.element) {
            case snowcrash::Element::ResourceElement:
                return ResourceToRefract(element.content.resource);
            case snowcrash::Element::DataStructureElement:
                return DataStructureToRefract(element.content.dataStructure);
            case snowcrash::Element::CopyElement:
                return CopyToRefract(element.content.copy);
            case snowcrash::Element::CategoryElement:
                return CategoryToRefract(element);
            default:
                throw std::runtime_error("Not Implemented - Unhandled type of Element");
        }
    }

    refract::IElement* BlueprintToRefract(const snowcrash::Blueprint& blueprint)
    {
        refract::ArrayElement* ast = new refract::ArrayElement;
        RefractElements content;

        ast->element("category");
        ast->meta["classes"] = CreateArrayElement("api");
        ast->meta["title"] = refract::IElement::Create(blueprint.name);

        content.push_back(CopyToRefract(blueprint.description));

        if (!blueprint.metadata.empty()) {
            ast->attributes["meta"] = MetadataCollectionToRefract(blueprint.metadata);
        }

        // Append set of elements to content
        const snowcrash::Elements& scElements = blueprint.content.elements();
        std::transform(scElements.begin(), scElements.end(), std::back_inserter(content), ElementToRefract);

        // Remove NULL elements
        content.erase(std::remove_if(content.begin(), content.end(), IsNull<refract::IElement>), content.end());
        ast->set(content);

        return ast;
    }

} // namespace drafter
<commit_msg>Address reviews<commit_after>//
//  RefractAPI.cc
//  drafter
//
//  Created by Jiri Kratochvil on 31/07/15.
//  Copyright (c) 2015 Apiary Inc. All rights reserved.
//

#include "StringUtility.h"
#include "BlueprintUtility.h"

#include "RefractAPI.h"
#include "refract/Element.h"
#include "refract/Registry.h"
#include "refract/Visitors.h"

namespace drafter {

    // Forward Declarations
    refract::IElement* ElementToRefract(const snowcrash::Element& element);

    namespace {

        typedef std::vector<refract::IElement*> RefractElements;

        template <typename T>
        refract::ArrayElement* CreateArrayElement(const T& content)
        {
            refract::ArrayElement* array = new refract::ArrayElement;
            array->push_back(refract::IElement::Create(content));
            return array;
        }

        template <typename T>
        bool IsNull(const T* ptr)
        {
            return ptr == NULL;
        }
    }

    refract::IElement* MetadataToRefract(const snowcrash::Metadata metadata)
    {
        refract::MemberElement* element = new refract::MemberElement;

        element->meta["classes"] = CreateArrayElement("user");
        element->meta["classes"].renderType(refract::IElement::rCompact);
        element->set(refract::IElement::Create(metadata.first), refract::IElement::Create(metadata.second));
        element->renderType(refract::IElement::rFull);

        return element;
    }

    refract::IElement* MetadataCollectionToRefract(const snowcrash::MetadataCollection metadata)
    {
        refract::ArrayElement* element = new refract::ArrayElement;
        RefractElements content;

        std::transform(metadata.begin(), metadata.end(), std::back_inserter(content), MetadataToRefract);
        element->set(content);
        element->renderType(refract::IElement::rCompact);

        return element;
    }

    refract::IElement* CopyToRefract(const std::string& copy)
    {
        if (copy.empty()) {
            return NULL;
        }

        refract::IElement* element = refract::IElement::Create(copy);
        element->element("copy");

        return element;
    }

    template<typename T>
    refract::IElement* ParameterValuesToRefract(const snowcrash::Parameter& parameter)
    {
        refract::ArrayElement* element = new refract::ArrayElement;
        RefractElements content;

        element->element("enum");

        if (!parameter.exampleValue.empty()) {
            element->attributes["samples"] = CreateArrayElement(LiteralTo<T>(parameter.exampleValue));
        }

        for (snowcrash::Values::const_iterator it = parameter.values.begin();
             it != parameter.values.end();
             ++it) {

            content.push_back(refract::IElement::Create(LiteralTo<T>(*it)));
        }

        element->set(content);

        return element;
    }

    template<typename T>
    refract::IElement* ExtractParameter(const snowcrash::Parameter& parameter)
    {
        refract::IElement* element = NULL;

        if (parameter.values.empty()) {
            element = refract::IElement::Create(LiteralTo<T>(parameter.exampleValue));
        }
        else {
            element = ParameterValuesToRefract<T>(parameter);
        }

        if (!parameter.defaultValue.empty()) {
            element->attributes["default"] = refract::IElement::Create(LiteralTo<T>(parameter.defaultValue));
        }

        return element;
    }

    refract::IElement* ParameterToRefract(const snowcrash::Parameter& parameter)
    {
        refract::MemberElement* element = new refract::MemberElement;
        refract::IElement *value = NULL;

        // Parameter type, exampleValue, defaultValue, values
        if (parameter.type == "boolean") {
            value = ExtractParameter<bool>(parameter);
        }
        else if (parameter.type == "number") {
            value = ExtractParameter<double>(parameter);
        }
        else {
            value = ExtractParameter<std::string>(parameter);
        }

        element->set(refract::IElement::Create(parameter.name), value);

        // Description
        if (!parameter.description.empty()) {
            element->meta["description"] = refract::IElement::Create(parameter.description);
        }

        // Parameter use
        if (parameter.use == snowcrash::RequiredParameterUse || parameter.use == snowcrash::OptionalParameterUse) {
            refract::ArrayElement* typeAttributes = new refract::ArrayElement;

            typeAttributes->push_back(refract::IElement::Create(parameter.use == snowcrash::RequiredParameterUse ? "required" : "optional"));
            element->attributes["typeAttributes"] = typeAttributes;
        }

        return element;
    }

    refract::IElement* ParametersToRefract(const snowcrash::Parameters& parameters)
    {
        refract::ObjectElement* element = new refract::ObjectElement;
        RefractElements content;

        element->element("hrefVariables");
        std::transform(parameters.begin(), parameters.end(), std::back_inserter(content), ParameterToRefract);
        element->renderType(refract::IElement::rFull);

        element->set(content);

        return element;
    }

    refract::IElement* HeaderToRefract(const snowcrash::Header& header)
    {
        refract::MemberElement* element = new refract::MemberElement;
        element->set(refract::IElement::Create(header.first), refract::IElement::Create(header.second));

        return element;
    }

    refract::IElement* HeadersToRefract(const snowcrash::Headers& headers)
    {
        refract::ObjectElement* element = new refract::ObjectElement;
        RefractElements content;

        element->element("httpHeaders");
        std::transform(headers.begin(), headers.end(), std::back_inserter(content), HeaderToRefract);
        element->renderType(refract::IElement::rFull);

        element->set(content);

        return element;
    }

    refract::IElement* AssetToRefract(const snowcrash::Asset& asset, const std::string& contentType, bool messageBody = true)
    {
        if (asset.empty()) {
            return NULL;
        }

        refract::IElement* element = refract::IElement::Create(asset);

        element->element("asset");
        element->meta["classes"] = refract::ArrayElement::Create(messageBody ? "messageBody" : "messageSchema");

        if (!contentType.empty()) {
            element->attributes["contentType"] = refract::IElement::Create(contentType);
        }

        return element;
    }

    std::string GetPayloadContentType(const snowcrash::Payload& payload)
    {
        std::string contentType = "";
        snowcrash::Headers::const_iterator it;

        it = std::find_if(payload.headers.begin(),
                          payload.headers.end(),
                          std::bind2nd(snowcrash::MatchFirstWith<snowcrash::Header, std::string, snowcrash::IEqual<std::string> >(),
                                       snowcrash::HTTPHeaderName::ContentType));

        if (it != payload.headers.end()) {
            contentType = it->second;
        }

        return contentType;
    }

    refract::IElement* PayloadToRefract(const snowcrash::Payload* payload, const snowcrash::HTTPMethod& method = "")
    {
        refract::ArrayElement* element = new refract::ArrayElement;
        RefractElements content;

        // Use HTTP method to recognize if request or response
        if (method.empty()) {
            element->element("httpResponse");

            if (payload != NULL && !payload->name.empty()) {
                element->attributes["statusCode"] = refract::IElement::Create(payload->name);
            }
        }
        else {
            element->element("httpRequest");
            element->attributes["method"] = refract::IElement::Create(method);

            if (payload != NULL) {
                element->attributes["title"] = refract::IElement::Create(payload->name);
            }
        }

        // If no payload, return immediately
        if (payload == NULL) {
            element->set(content);
            return element;
        }

        if (!payload->headers.empty()) {
            element->attributes["headers"] = HeadersToRefract(payload->headers);
        }

        content.push_back(CopyToRefract(payload->description));
        content.push_back(DataStructureToRefract(payload->attributes));

        // Get content type
        std::string contentType = GetPayloadContentType(*payload);

        // Assets
        content.push_back(AssetToRefract(payload->body, contentType));
        content.push_back(AssetToRefract(payload->schema, contentType, false));

        // Remove NULL elements
        content.erase(std::remove_if(content.begin(), content.end(), IsNull<refract::IElement>), content.end());
        element->set(content);

        return element;
    }

    refract::IElement* TransactionToRefract(const snowcrash::TransactionExample& transaction,
                                            const snowcrash::HTTPMethod& method,
                                            const snowcrash::Request* request = NULL,
                                            const snowcrash::Response* response = NULL)
    {
        refract::ArrayElement* element = new refract::ArrayElement;
        RefractElements content;

        element->element("httpTransaction");
        content.push_back(CopyToRefract(transaction.description));

        content.push_back(PayloadToRefract(request, method));
        content.push_back(PayloadToRefract(response));

        // Remove NULL elements
        content.erase(std::remove_if(content.begin(), content.end(), IsNull<refract::IElement>), content.end());
        element->set(content);

        return element;
    }

    refract::IElement* ActionToRefract(const snowcrash::Action& action)
    {
        refract::ArrayElement* element = new refract::ArrayElement;
        RefractElements content;

        element->element("transition");
        element->meta["title"] = refract::IElement::Create(action.name);

        if (!action.relation.str.empty()) {
            element->attributes["relation"] = refract::IElement::Create(action.relation.str);
        }

        if (!action.uriTemplate.empty()) {
            element->attributes["href"] = refract::IElement::Create(action.uriTemplate);
        }

        if (!action.parameters.empty()) {
            element->attributes["hrefVariables"] = ParametersToRefract(action.parameters);
        }

        if (!action.attributes.empty()) {
            refract::IElement* dataStructure = DataStructureToRefract(action.attributes);
            dataStructure->renderType(refract::IElement::rFull);
            element->attributes["data"] = dataStructure;
        }

        content.push_back(CopyToRefract(action.description));

        for (snowcrash::TransactionExamples::const_iterator it = action.examples.begin();
             it != action.examples.end();
             ++it) {

            // When there are only responses
            if (it->requests.empty() && !it->responses.empty()) {

                for (snowcrash::Responses::const_iterator tmpResIt = it->responses.begin();
                     tmpResIt != it->responses.end();
                     ++tmpResIt) {

                    content.push_back(TransactionToRefract(*it, action.method, NULL, &*tmpResIt));
                }
            }

            // When there are only requests or both responses and requests
            for (snowcrash::Requests::const_iterator reqIt = it->requests.begin();
                 reqIt != it->requests.end();
                 ++reqIt) {

                if (it->responses.empty()) {
                    content.push_back(TransactionToRefract(*it, action.method, &*reqIt));
                }

                for (snowcrash::Responses::const_iterator resIt = it->responses.begin();
                     resIt != it->responses.end();
                     ++resIt) {

                    content.push_back(TransactionToRefract(*it, action.method, &*reqIt, &*resIt));
                }
            }
        }

        // Remove NULL elements
        content.erase(std::remove_if(content.begin(), content.end(), IsNull<refract::IElement>), content.end());
        element->set(content);

        return element;
    }

    refract::IElement* ResourceToRefract(const snowcrash::Resource& resource)
    {
        refract::ArrayElement* element = new refract::ArrayElement;
        RefractElements content;

        element->element("resource");
        element->meta["title"] = refract::IElement::Create(resource.name);
        element->attributes["href"] = refract::IElement::Create(resource.uriTemplate);

        if (!resource.parameters.empty()) {
            element->attributes["hrefVariables"] = ParametersToRefract(resource.parameters);
        }

        content.push_back(CopyToRefract(resource.description));
        content.push_back(DataStructureToRefract(resource.attributes));

        std::transform(resource.actions.begin(), resource.actions.end(), std::back_inserter(content), ActionToRefract);

        // Remove NULL elements
        content.erase(std::remove_if(content.begin(), content.end(), IsNull<refract::IElement>), content.end());
        element->set(content);

        return element;
    }

    refract::IElement* CategoryToRefract(const snowcrash::Element& element)
    {
        refract::ArrayElement* category = new refract::ArrayElement;
        RefractElements content;

        category->element("category");

        if (element.category == snowcrash::Element::ResourceGroupCategory) {
            category->meta["classes"] = CreateArrayElement("resourceGroup");
            category->meta["title"] = refract::IElement::Create(element.attributes.name);
        }
        else if (element.category == snowcrash::Element::DataStructureGroupCategory) {
            category->meta["classes"] = CreateArrayElement("dataStructures");
        }

        snowcrash::Elements elements = element.content.elements();
        std::transform(elements.begin(), elements.end(), std::back_inserter(content), ElementToRefract);

        // Remove NULL elements
        content.erase(std::remove_if(content.begin(), content.end(), IsNull<refract::IElement>), content.end());
        category->set(content);

        return category;
    }

    refract::IElement* ElementToRefract(const snowcrash::Element& element)
    {
        switch (element.element) {
            case snowcrash::Element::ResourceElement:
                return ResourceToRefract(element.content.resource);
            case snowcrash::Element::DataStructureElement:
                return DataStructureToRefract(element.content.dataStructure);
            case snowcrash::Element::CopyElement:
                return CopyToRefract(element.content.copy);
            case snowcrash::Element::CategoryElement:
                return CategoryToRefract(element);
            default:
                throw std::runtime_error("Not Implemented - Unhandled type of Element");
        }
    }

    refract::IElement* BlueprintToRefract(const snowcrash::Blueprint& blueprint)
    {
        refract::ArrayElement* ast = new refract::ArrayElement;
        RefractElements content;

        ast->element("category");
        ast->meta["classes"] = CreateArrayElement("api");
        ast->meta["title"] = refract::IElement::Create(blueprint.name);

        content.push_back(CopyToRefract(blueprint.description));

        if (!blueprint.metadata.empty()) {
            ast->attributes["meta"] = MetadataCollectionToRefract(blueprint.metadata);
        }

        // Append set of elements to content
        const snowcrash::Elements& scElements = blueprint.content.elements();
        std::transform(scElements.begin(), scElements.end(), std::back_inserter(content), ElementToRefract);

        // Remove NULL elements
        content.erase(std::remove_if(content.begin(), content.end(), IsNull<refract::IElement>), content.end());
        ast->set(content);

        return ast;
    }

} // namespace drafter
<|endoftext|>


<commit_before> /**
Copyright (c) 2017 Neon Edge Game.
File Name: Resources.cpp
Header File Name: Resources.h
Class Name: Resources
Objective: Class responsable to manager the games resources.

*/
#include <cstdio>
#include <cstdlib>
#include "Resources.h"
#include "Game.h"
#include "Logger.h"

// Inicializate unordered_maps.
std::unordered_map<std::string, SDL_Texture*> Resources::imageTable = std::unordered_map<std::string, SDL_Texture*>();
std::unordered_map<std::string, SDL_Surface*> Resources::surfaceTable = std::unordered_map<std::string, SDL_Surface*>();
std::unordered_map<std::string, Mix_Music*> Resources::musicTable = std::unordered_map<std::string, Mix_Music*>();
std::unordered_map<std::string, Mix_Chunk*> Resources::soundTable = std::unordered_map<std::string, Mix_Chunk*>();
std::unordered_map<std::string, TTF_Font*> Resources::fontTable = std::unordered_map<std::string, TTF_Font*>();

// Set the path of the resources.
std::string Resources::BASENAME = "resources/";
std::string Resources::BASENAME_IMAGE = "resources/img/";
std::string Resources::BASENAME_MUSIC = "resources/audio/music/";
std::string Resources::BASENAME_SOUND = "resources/audio/sound/";
std::string Resources::BASENAME_FONT = "resources/font/";

/**
   Objective: Get aimage that is requested.
   @param string file - name ofthe image on the unorded_map.
   @param bool forceDuplicate - force a duplication on the class.
   @return SDL_Texture imageTable - a texture of the  sdl library.

*/

SDL_Texture* Resources::GetImage(std::string file, bool forceDuplicate = false) {
	Log::instance.info("Get image " + file);
	std::string fileKey = file;

	// if ForceDuplicate is true, the code check the numbers of instances and add one asterisk to the file.
	if (forceDuplicate){
		while(imageTable.count(fileKey)) {
			fileKey += "*";
		}
	}

	// Check the existence of a file, if not exist the code construct and insert the element on the unorded_map.
	if(!imageTable.count(fileKey)) {
		if(surfaceTable.count(file)) {
			imageTable.emplace(fileKey, SDL_CreateTextureFromSurface(Game::GetInstance().GetRenderer(), surfaceTable[file]));
		} else {
			imageTable.emplace(fileKey, IMG_LoadTexture(Game::GetInstance().GetRenderer(), (Resources::BASENAME_IMAGE + file).c_str()));
		}
	}
	// Get a error if the SDL_Texture in the unorded_map is nullptr.
	if(imageTable.at(fileKey) == nullptr) {
		std::string error = SDL_GetError();
		Log::instance.error("Error: " + error);
	}
	return imageTable.at(fileKey);
}

/**
   Objective: Clear all image of the screen.
   @param None
   @return void

*/

void Resources::ClearImages() {
	Log::instance.info("Cleaning images");
	// Pass to all elements of the unorded_map and destroy then.
	for(auto& i : imageTable) {
		SDL_DestroyTexture(i.second);
	}
	imageTable.clear();
}

/**
   Objective: Get a surface in the unorded_map.
   @param string file - the path of the image.
   @return The asked SDL_surface.

*/
SDL_Surface *Resources::GetSurface(std::string file) {
	Log::instance.info("Get surface" + file);
	// Construct a insert the file element requested.
	if(!surfaceTable.count(file)) {
		surfaceTable.emplace(file, IMG_Load((Resources::BASENAME_IMAGE + file).c_str()));
	}

	// Put a error if fail to load the file.
	if(surfaceTable.at(file) == nullptr) {
		std::string error = SDL_GetError();
		Log::instance.error("IMG_Load failed:" + error);
		exit(EXIT_FAILURE);
	}
	return surfaceTable.at(file);
}

/**
   Objective: Clear the unorded_map of SDL_Surface.
   @param None
   @return void

*/
void Resources::ClearSurface() {
	Log::instance.info("Cleaning images");
	// Pass to all elements of the unorded_map and destroy then.
	for(auto& i : surfaceTable) {
		SDL_FreeSurface(i.second);
	}
	surfaceTable.clear();
}

/**
   Objective: Get a specific music in the unorded_map.
   @param string file - name file to search.
   @return Mix_Music - the Mix_music that was search.

*/
Mix_Music* Resources::GetMusic(std::string file) {
	Log::instance.info("Get music" + file);
	// Construct a insert the music element requested.
	if(!musicTable.count(file)) {
		musicTable.emplace(file, Mix_LoadMUS((Resources::BASENAME_MUSIC + file).c_str()));
	}
	// Prints a error if fails to open file.
	if(musicTable.at(file) == nullptr) {
		std::string error = SDL_GetError();
		Log::instance.error("Mix_LoadMUS failed: " + error);
		exit(EXIT_FAILURE);
	}
	return musicTable.at(file);
}

/**
   Objective: Clear the unordedmap of musics.
   @param None
   @return void

*/
void Resources::ClearMusics() {
	Log::instance.info("Clear all musics");
	// Pass to all elements of the unorded_map and destroy then.
	for(auto& i : musicTable) {
		Mix_FreeMusic(i.second);
	}
	musicTable.clear();
}

/**
   Objective: Get a specific sound in the unorded_map.
   @param string file - Name of the require sound.
   @return Mix_Chunk - the instance of the Mix_check(represent a soound in SDL).

*/
Mix_Chunk* Resources::GetSound(std::string file) {
	Log::instance.info("Get sound" + file);
	// Construct a insert the sound element requested.
	if(!soundTable.count(file)) {
		soundTable.emplace(file, Mix_LoadWAV((Resources::BASENAME_SOUND + file).c_str()));
	}
	// Prints a error if fails to open file.
	if(soundTable.at(file) == nullptr) {
		std::string error = SDL_GetError();
		Log::instance.error("Mix_LoadWAV failed: " + error);
		exit(EXIT_FAILURE);
	}
	return soundTable.at(file);
}

/**
   Objective: Clear the unordedmap of sounds.
   @param None.
   @return void.

*/
void Resources::ClearSounds() {
	Log::instance.info("Clear all sounds");
	// Pass to all elements of the unorded_map and destroy then.
	for(auto& i : soundTable) {
		Mix_FreeChunk(i.second);
	}
	soundTable.clear();
}

/**
   Objective: Get a specific Font for visual strings in the game in the unorded_map.
   @param string file - path to the font.
   @param int fontSize.
   @return TTF_Font - A instance of TTF_Font a graphic visualization to strings.

*/
TTF_Font* Resources::GetFont(std::string file, int fontSize) {
	Log::instance.info("Get font: " + file);
	char vetor[5]; //vector of char to store fontSize.
	sprintf(vetor, "%d", fontSize);
	std::string key = file + vetor; // Set the key value for the unorded_map

	// Construct a insert the font element requested.
	if(!fontTable.count(key)) {
		fontTable.emplace(key, TTF_OpenFont((Resources::BASENAME_FONT + file).c_str(), fontSize));
	}
	// Prints a error if fails to open file.
	if(fontTable.at(key) == nullptr) {
		std::string error = SDL_GetError();
		Log::instance.error("TTF_OpenFont failed: " + error);
		exit(EXIT_FAILURE);
	}
	return fontTable.at(key);
}

/**
   Objective: Clear the unordedmap of TTF_Fonts
   @param None
   @return void

*/
void Resources::ClearFonts() {
	Log::instance.info("Clear all fonts");
	// Pass to all elements of the unorded_map and destroy then.
	for(auto& i : fontTable) {
		TTF_CloseFont(i.second);
	}
	fontTable.clear();
}
<commit_msg>Aplicando verifique todo os valores de retorno 3<commit_after> /**
Copyright (c) 2017 Neon Edge Game.
File Name: Resources.cpp
Header File Name: Resources.h
Class Name: Resources
Objective: Class responsable to manager the games resources.

*/
#include <cstdio>
#include <cstdlib>
#include <assert.h>
#include "Resources.h"
#include "Game.h"
#include "Logger.h"

// Inicializate unordered_maps.
std::unordered_map<std::string, SDL_Texture*> Resources::imageTable = std::unordered_map<std::string, SDL_Texture*>();
std::unordered_map<std::string, SDL_Surface*> Resources::surfaceTable = std::unordered_map<std::string, SDL_Surface*>();
std::unordered_map<std::string, Mix_Music*> Resources::musicTable = std::unordered_map<std::string, Mix_Music*>();
std::unordered_map<std::string, Mix_Chunk*> Resources::soundTable = std::unordered_map<std::string, Mix_Chunk*>();
std::unordered_map<std::string, TTF_Font*> Resources::fontTable = std::unordered_map<std::string, TTF_Font*>();

// Set the path of the resources.
std::string Resources::BASENAME = "resources/";
std::string Resources::BASENAME_IMAGE = "resources/img/";
std::string Resources::BASENAME_MUSIC = "resources/audio/music/";
std::string Resources::BASENAME_SOUND = "resources/audio/sound/";
std::string Resources::BASENAME_FONT = "resources/font/";

/**
   Objective: Get aimage that is requested.
   @param string file - name ofthe image on the unorded_map.
   @param bool forceDuplicate - force a duplication on the class.
   @return SDL_Texture imageTable - a texture of the  sdl library.

*/

SDL_Texture* Resources::GetImage(std::string file, bool forceDuplicate = false) {
	Log::instance.info("Get image " + file);
	std::string fileKey = file;

	// if ForceDuplicate is true, the code check the numbers of instances and add one asterisk to the file.
	if (forceDuplicate){
		while(imageTable.count(fileKey)) {
			fileKey += "*";
		}
	}

	// Check the existence of a file, if not exist the code construct and insert the element on the unorded_map.
	if(!imageTable.count(fileKey)) {
		if(surfaceTable.count(file)) {
			imageTable.emplace(fileKey, SDL_CreateTextureFromSurface(Game::GetInstance().GetRenderer(), surfaceTable[file]));
		} else {
			imageTable.emplace(fileKey, IMG_LoadTexture(Game::GetInstance().GetRenderer(), (Resources::BASENAME_IMAGE + file).c_str()));
		}
	}
	// Get a error if the SDL_Texture in the unorded_map is nullptr.
	if(imageTable.at(fileKey) == nullptr) {
		std::string error = SDL_GetError();
		Log::instance.error("Error: " + error);
	}

	assert(imageTable.at(file) != nullptr);
	return imageTable.at(fileKey);
}

/**
   Objective: Clear all image of the screen.
   @param None
   @return void

*/

void Resources::ClearImages() {
	Log::instance.info("Cleaning images");
	// Pass to all elements of the unorded_map and destroy then.
	for(auto& i : imageTable) {
		SDL_DestroyTexture(i.second);
	}
	imageTable.clear();
}

/**
   Objective: Get a surface in the unorded_map.
   @param string file - the path of the image.
   @return The asked SDL_surface.

*/
SDL_Surface *Resources::GetSurface(std::string file) {
	Log::instance.info("Get surface" + file);
	// Construct a insert the file element requested.
	if(!surfaceTable.count(file)) {
		surfaceTable.emplace(file, IMG_Load((Resources::BASENAME_IMAGE + file).c_str()));
	}

	// Put a error if fail to load the file.
	if(surfaceTable.at(file) == nullptr) {
		std::string error = SDL_GetError();
		Log::instance.error("IMG_Load failed:" + error);
		exit(EXIT_FAILURE);
	}

	assert(surfaceTable.at(file) != nullptr);
	return surfaceTable.at(file);
}

/**
   Objective: Clear the unorded_map of SDL_Surface.
   @param None
   @return void

*/
void Resources::ClearSurface() {
	Log::instance.info("Cleaning images");
	// Pass to all elements of the unorded_map and destroy then.
	for(auto& i : surfaceTable) {
		SDL_FreeSurface(i.second);
	}
	surfaceTable.clear();
}

/**
   Objective: Get a specific music in the unorded_map.
   @param string file - name file to search.
   @return Mix_Music - the Mix_music that was search.

*/
Mix_Music* Resources::GetMusic(std::string file) {
	Log::instance.info("Get music" + file);
	// Construct a insert the music element requested.
	if(!musicTable.count(file)) {
		musicTable.emplace(file, Mix_LoadMUS((Resources::BASENAME_MUSIC + file).c_str()));
	}
	// Prints a error if fails to open file.
	if(musicTable.at(file) == nullptr) {
		std::string error = SDL_GetError();
		Log::instance.error("Mix_LoadMUS failed: " + error);
		exit(EXIT_FAILURE);
	}

	assert(musicTable.at(file) != nullptr);
	return musicTable.at(file);
}

/**
   Objective: Clear the unordedmap of musics.
   @param None
   @return void

*/
void Resources::ClearMusics() {
	Log::instance.info("Clear all musics");
	// Pass to all elements of the unorded_map and destroy then.
	for(auto& i : musicTable) {
		Mix_FreeMusic(i.second);
	}
	musicTable.clear();
}

/**
   Objective: Get a specific sound in the unorded_map.
   @param string file - Name of the require sound.
   @return Mix_Chunk - the instance of the Mix_check(represent a soound in SDL).

*/
Mix_Chunk* Resources::GetSound(std::string file) {
	Log::instance.info("Get sound" + file);
	// Construct a insert the sound element requested.
	if(!soundTable.count(file)) {
		soundTable.emplace(file, Mix_LoadWAV((Resources::BASENAME_SOUND + file).c_str()));
	}
	// Prints a error if fails to open file.
	if(soundTable.at(file) == nullptr) {
		std::string error = SDL_GetError();
		Log::instance.error("Mix_LoadWAV failed: " + error);
		exit(EXIT_FAILURE);
	}

	assert(soundTable.at(file) != nullptr);
	return soundTable.at(file);
}

/**
   Objective: Clear the unordedmap of sounds.
   @param None.
   @return void.

*/
void Resources::ClearSounds() {
	Log::instance.info("Clear all sounds");
	// Pass to all elements of the unorded_map and destroy then.
	for(auto& i : soundTable) {
		Mix_FreeChunk(i.second);
	}
	soundTable.clear();
}

/**
   Objective: Get a specific Font for visual strings in the game in the unorded_map.
   @param string file - path to the font.
   @param int fontSize.
   @return TTF_Font - A instance of TTF_Font a graphic visualization to strings.

*/
TTF_Font* Resources::GetFont(std::string file, int fontSize) {
	Log::instance.info("Get font: " + file);
	char vetor[5]; //vector of char to store fontSize.
	sprintf(vetor, "%d", fontSize);
	std::string key = file + vetor; // Set the key value for the unorded_map

	// Construct a insert the font element requested.
	if(!fontTable.count(key)) {
		fontTable.emplace(key, TTF_OpenFont((Resources::BASENAME_FONT + file).c_str(), fontSize));
	}
	// Prints a error if fails to open file.
	if(fontTable.at(key) == nullptr) {
		std::string error = SDL_GetError();
		Log::instance.error("TTF_OpenFont failed: " + error);
		exit(EXIT_FAILURE);
	}

	assert(fontTable.at(file) != nullptr);
	return fontTable.at(key);
}

/**
   Objective: Clear the unordedmap of TTF_Fonts
   @param None
   @return void

*/
void Resources::ClearFonts() {
	Log::instance.info("Clear all fonts");
	// Pass to all elements of the unorded_map and destroy then.
	for(auto& i : fontTable) {
		TTF_CloseFont(i.second);
	}
	fontTable.clear();
}
<|endoftext|>


<commit_before>#ifndef AMGCL_COARSENING_DETAIL_GALERKIN_HPP
#define AMGCL_COARSENING_DETAIL_GALERKIN_HPP

/*
The MIT License

Copyright (c) 2012-2015 Denis Demidov <dennis.demidov@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

/**
 * \file   amgcl/coarsening/detail/galerkin.hpp
 * \author Denis Demidov <dennis.demidov@gmail.com>
 * \brief  Galerkin operator.
 */

#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <amgcl/backend/builtin.hpp>

namespace amgcl {
namespace coarsening {
namespace detail {

template <class Matrix>
boost::shared_ptr<Matrix> galerkin(
        const Matrix &A, const Matrix &P, const Matrix &R
        )
{
    boost::shared_ptr<Matrix> a = boost::make_shared<Matrix>();
    *a = product(product(R, A), P);
    return a;
}

} // namespace detail
} // namespace coarsening
} // namespace amgcl

#endif
<commit_msg>Reorder products in galerkin<commit_after>#ifndef AMGCL_COARSENING_DETAIL_GALERKIN_HPP
#define AMGCL_COARSENING_DETAIL_GALERKIN_HPP

/*
The MIT License

Copyright (c) 2012-2015 Denis Demidov <dennis.demidov@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

/**
 * \file   amgcl/coarsening/detail/galerkin.hpp
 * \author Denis Demidov <dennis.demidov@gmail.com>
 * \brief  Galerkin operator.
 */

#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <amgcl/backend/builtin.hpp>

namespace amgcl {
namespace coarsening {
namespace detail {

template <class Matrix>
boost::shared_ptr<Matrix> galerkin(
        const Matrix &A, const Matrix &P, const Matrix &R
        )
{
    boost::shared_ptr<Matrix> a = boost::make_shared<Matrix>();
    *a = product(R, product(A, P));
    return a;
}

} // namespace detail
} // namespace coarsening
} // namespace amgcl

#endif
<|endoftext|>


<commit_before>/* Copyright (c) 2011 Facebook
 * Copyright (c) 2012 Stanford University
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIM ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include "StringUtil.h"

#include <regex.h>
#include <sstream>

namespace RAMCloud {
namespace StringUtil {

/// Return true if haystack begins with needle.
bool
startsWith(const string& haystack, const string& needle)
{
    return (haystack.compare(0, needle.length(), needle) == 0);
}

/// Return true if haystack ends with needle.
bool
endsWith(const string& haystack, const string& needle)
{
    if (haystack.length() < needle.length())
        return false;
    return (haystack.compare(haystack.length() - needle.length(),
                             needle.length(), needle) == 0);
}

/// Return true if needle exists somewhere in haystack.
bool
contains(const string& haystack, const string& needle)
{
    if (haystack.length() < needle.length())
        return false;
    return haystack.find(needle) != string::npos;
}

/**
 * Basic regular expression substitution.
 * \param subject
 *      String on which to perform substitution.
 * \param pattern
 *      A POSIX regular expression (supports extended syntax, including
 *      "+" etc.).
 * \param replacement
 *      Literal string to replace each instance of \a pattern
 *      in \a subject.
 *
 * \return
 *      The return value consists of \a subject with each instance of
 *      \a pattern replaced with \a replacement. If there are no
 *      instances of \a pattern in \a subject, then \a subject is returned.
 *      If there is an error in \a pattern, then the returned value is the
 *      regex error message.
 */
string
regsub(const string& subject, const string& pattern, const string& replacement)
{
    regex_t pregStorage;
    int r;

    r = regcomp(&pregStorage, pattern.c_str(), REG_EXTENDED);
    if (r != 0) {
        char message[1000];
        regerror(r, &pregStorage, message, sizeof(message));
        regfree(&pregStorage);
        return message;
    }

    string result;
    uint32_t cursor = 0;

    // Each iteration through the following loop finds the next match and
    // performs the corresponding substitution.
    while (cursor < subject.size()) {
        regmatch_t matches[1];
        r = regexec(&pregStorage, subject.c_str() + cursor, 1, matches, 0);
        if (r != 0) {
            break;
        }

        result.append(subject, cursor, matches[0].rm_so);
        result.append(replacement);
        cursor += matches[0].rm_eo;
    }

    // Copy to the result their unmatched text at the end of the subject.
    result.append(subject, cursor, subject.size() - cursor);
    regfree(&pregStorage);
    return result;
}

/**
 * Take the binary string given and convert it into a printable string.
 * Any printable ASCII characters (including space, but not other
 * whitespace) will be unchanged. Any non-printable characters will
 * be represented in escaped hexadecimal form, for example "\xf8\x07".
 *
 * \param input
 *      Pointer to some memory that may or may not contain ascii
 *      characters.
 * \param length
 *      Length of the input in bytes.
 */
string
binaryToString(const void* input, uint32_t length)
{
    string s = "";
    const unsigned char* c = reinterpret_cast<const unsigned char*>(input);

    for (uint16_t i = 0; i < length; i++) {
        if (isprint(c[i]))
            s += c[i];
        else
            s += format("\\x%02x", static_cast<uint32_t>(c[i]));
    }

    return s;
}

/**
 * Split a std::string based on a character delimiter.
 * \param s
 *      String to be split.
 * \param delim
 *      Delimiter to split string on.
 */
std::vector<std::string> split(const std::string &s, char delim) {
    std::vector<std::string> elems;
    std::stringstream ss(s);
    std::string item;
    while (std::getline(ss, item, delim))
        elems.push_back(item);
    return elems;
}

/**
 * Convenience method for converting strings to integers.
 * \param s
 *      String consisting of whitespace following by a positive or
 *      negative number.
 * \param error
 *      Set to true if s did not contain a syntactically valid number,
 *      the number was out of range for a long int, or there was extra
 *      information in s after the number.
 * \return
 *      The number corresponding to s, or 0 in the case of an error.
 */
int64_t
stringToInt(const char* s, bool* error)
{
    char* end;
    int64_t result = strtol(s, &end, 0);
    if ((end == s) || (*end != 0) || (result == LONG_MAX)
            || (result == LONG_MIN)) {
        *error = true;
        return 0;
    }
    *error = false;
    return result;
}

} // namespace StringUtil
} // namespace RAMCloud
<commit_msg>Added "#include <climits>" to StringUtil.cc.<commit_after>/* Copyright (c) 2011 Facebook
 * Copyright (c) 2012 Stanford University
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIM ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include "StringUtil.h"

#include <regex.h>
#include <climits>
#include <sstream>

namespace RAMCloud {
namespace StringUtil {

/// Return true if haystack begins with needle.
bool
startsWith(const string& haystack, const string& needle)
{
    return (haystack.compare(0, needle.length(), needle) == 0);
}

/// Return true if haystack ends with needle.
bool
endsWith(const string& haystack, const string& needle)
{
    if (haystack.length() < needle.length())
        return false;
    return (haystack.compare(haystack.length() - needle.length(),
                             needle.length(), needle) == 0);
}

/// Return true if needle exists somewhere in haystack.
bool
contains(const string& haystack, const string& needle)
{
    if (haystack.length() < needle.length())
        return false;
    return haystack.find(needle) != string::npos;
}

/**
 * Basic regular expression substitution.
 * \param subject
 *      String on which to perform substitution.
 * \param pattern
 *      A POSIX regular expression (supports extended syntax, including
 *      "+" etc.).
 * \param replacement
 *      Literal string to replace each instance of \a pattern
 *      in \a subject.
 *
 * \return
 *      The return value consists of \a subject with each instance of
 *      \a pattern replaced with \a replacement. If there are no
 *      instances of \a pattern in \a subject, then \a subject is returned.
 *      If there is an error in \a pattern, then the returned value is the
 *      regex error message.
 */
string
regsub(const string& subject, const string& pattern, const string& replacement)
{
    regex_t pregStorage;
    int r;

    r = regcomp(&pregStorage, pattern.c_str(), REG_EXTENDED);
    if (r != 0) {
        char message[1000];
        regerror(r, &pregStorage, message, sizeof(message));
        regfree(&pregStorage);
        return message;
    }

    string result;
    uint32_t cursor = 0;

    // Each iteration through the following loop finds the next match and
    // performs the corresponding substitution.
    while (cursor < subject.size()) {
        regmatch_t matches[1];
        r = regexec(&pregStorage, subject.c_str() + cursor, 1, matches, 0);
        if (r != 0) {
            break;
        }

        result.append(subject, cursor, matches[0].rm_so);
        result.append(replacement);
        cursor += matches[0].rm_eo;
    }

    // Copy to the result their unmatched text at the end of the subject.
    result.append(subject, cursor, subject.size() - cursor);
    regfree(&pregStorage);
    return result;
}

/**
 * Take the binary string given and convert it into a printable string.
 * Any printable ASCII characters (including space, but not other
 * whitespace) will be unchanged. Any non-printable characters will
 * be represented in escaped hexadecimal form, for example "\xf8\x07".
 *
 * \param input
 *      Pointer to some memory that may or may not contain ascii
 *      characters.
 * \param length
 *      Length of the input in bytes.
 */
string
binaryToString(const void* input, uint32_t length)
{
    string s = "";
    const unsigned char* c = reinterpret_cast<const unsigned char*>(input);

    for (uint16_t i = 0; i < length; i++) {
        if (isprint(c[i]))
            s += c[i];
        else
            s += format("\\x%02x", static_cast<uint32_t>(c[i]));
    }

    return s;
}

/**
 * Split a std::string based on a character delimiter.
 * \param s
 *      String to be split.
 * \param delim
 *      Delimiter to split string on.
 */
std::vector<std::string> split(const std::string &s, char delim) {
    std::vector<std::string> elems;
    std::stringstream ss(s);
    std::string item;
    while (std::getline(ss, item, delim))
        elems.push_back(item);
    return elems;
}

/**
 * Convenience method for converting strings to integers.
 * \param s
 *      String consisting of whitespace following by a positive or
 *      negative number.
 * \param error
 *      Set to true if s did not contain a syntactically valid number,
 *      the number was out of range for a long int, or there was extra
 *      information in s after the number.
 * \return
 *      The number corresponding to s, or 0 in the case of an error.
 */
int64_t
stringToInt(const char* s, bool* error)
{
    char* end;
    int64_t result = strtol(s, &end, 0);
    if ((end == s) || (*end != 0) || (result == LONG_MAX)
            || (result == LONG_MIN)) {
        *error = true;
        return 0;
    }
    *error = false;
    return result;
}

} // namespace StringUtil
} // namespace RAMCloud
<|endoftext|>


<commit_before>/**********************************************************************/
/*                     DO NOT MODIFY THIS HEADER                      */
/* MAGPIE - Mesoscale Atomistic Glue Program for Integrated Execution */
/*                                                                    */
/*            Copyright 2017 Battelle Energy Alliance, LLC            */
/*                        ALL RIGHTS RESERVED                         */
/**********************************************************************/

#include "RadialAverage.h"
#include "ThreadedRadialAverageLoop.h"
#include "NonlinearSystemBase.h"
#include "FEProblemBase.h"

#include "libmesh/nanoflann.hpp"
#include "libmesh/parallel_algebra.h"
#include "libmesh/mesh_tools.h"

#include <list>
#include <iterator>
#include <algorithm>

registerMooseObject("MooseApp", RadialAverage);

// specialization for PointListAdaptor<RadialAverage::QPData>
template <>
const Point &
PointListAdaptor<RadialAverage::QPData>::getPoint(const RadialAverage::QPData & item) const
{
  return item._q_point;
}

InputParameters
RadialAverage::validParams()
{
  InputParameters params = ElementUserObject::validParams();
  params.addClassDescription("Perform a radial equal weight average of a material property");
  params.addRequiredParam<std::string>("material_name", "Name of the material to average.");
  params.addRequiredParam<Real>("r_cut", "Cut-off radius for the averaging");

  // we run this object once at the beginning of the timestep by default
  params.set<ExecFlagEnum>("execute_on") = EXEC_TIMESTEP_BEGIN;

  // make sure we always have geometric point neighbors ghosted
  params.addRelationshipManager("ElementPointNeighborLayers",
                                Moose::RelationshipManagerType::GEOMETRIC |
                                    Moose::RelationshipManagerType::ALGEBRAIC);

  return params;
}

RadialAverage::RadialAverage(const InputParameters & parameters)
  : ElementUserObject(parameters),
    _v_name(getParam<std::string>("material_name")),
    _v(getMaterialProperty<Real>(_v_name)),
    _r_cut(getParam<Real>("r_cut")),
    _dof_map(_fe_problem.getNonlinearSystemBase().dofMap()),
    _update_communication_lists(false),
    _my_pid(processor_id()),
    _perf_meshchanged(registerTimedSection("meshChanged", 3)),
    _perf_updatelists(registerTimedSection("updateCommunicationLists", 3)),
    _perf_finalize(registerTimedSection("finalize", 2))
{
}

void
RadialAverage::initialSetup()
{
  // set up processor boundary node list
  meshChanged();
}

void
RadialAverage::initialize()
{
  _qp_data.clear();
}

void
RadialAverage::execute()
{
  auto id = _current_elem->id();

  // collect all QP data
  for (unsigned int qp = 0; qp < _qrule->n_points(); ++qp)
    _qp_data.emplace_back(_q_point[qp], id, qp, _JxW[qp] * _coord[qp], _v[qp]);

  // make sure the result map entry for the current element is sized correctly
  auto i = _average.find(id);
  if (i == _average.end())
    _average.insert(std::make_pair(id, std::vector<Real>(_qrule->n_points())));
  else
    i->second.resize(_qrule->n_points());
}

void
RadialAverage::finalize()
{
  TIME_SECTION(_perf_finalize);

  // the first chunk of data is always the local data - remember its size
  unsigned int local_size = _qp_data.size();

  // communicate the qp data list if n_proc > 1
  if (_app.n_processors() > 1)
  {
    // !!!!!!!!!!!
    // !!CAREFUL!! Is it guaranteed that _qp_data is in the same order if the mesh has not changed?
    // According to @friedmud it is not guaranteed if threads are used
    // !!!!!!!!!!!

    // update after mesh changes and/or if a displaced problem exists
    if (_update_communication_lists || _fe_problem.getDisplacedProblem() ||
        libMesh::n_threads() > 1)
      updateCommunicationLists();

    // sparse send data (processor ID,)
    std::vector<std::size_t> non_zero_comm;
    for (auto i = beginIndex(_communication_lists); i < _communication_lists.size(); ++i)
      if (!_communication_lists[i].empty())
        non_zero_comm.push_back(i);

    // data structures for sparse point to point communication
    std::vector<std::vector<QPData>> send(non_zero_comm.size());
    std::vector<Parallel::Request> send_requests(non_zero_comm.size());
    Parallel::MessageTag send_tag = _communicator.get_unique_tag(4711);
    std::vector<QPData> receive;

    const auto item_type = StandardType<QPData>(&(_qp_data[0]));

#if 0
    // output local qp locations
    // _console << name() << ' ' << receive.size() << '\n' << name() << std::flush;
    for (auto item : _qp_data)
      _console << name() << ' ' << _my_pid << ' '
               << item._q_point(0) << ' '
               << item._q_point(1) << ' '
               << item._q_point(2) << std::flush;
#endif

    // fill buffer and send structures
    for (auto i = beginIndex(non_zero_comm); i < non_zero_comm.size(); ++i)
    {
      const auto pid = non_zero_comm[i];
      const auto & list = _communication_lists[pid];

      // fill send buffer for transfer to pid
      send[i].reserve(list.size());
      for (const auto & item : list)
      {
        send[i].push_back(_qp_data[item]);
#if 0
        // output sent qp locations
        _console << name() << ' '
                 << _qp_data[item]._q_point(0) << ' '
                 << _qp_data[item]._q_point(1) << ' '
                 << _qp_data[item]._q_point(2) << ' '
                 << pid << std::flush;
#endif
      }

      // issue non-blocking send
      _communicator.send(pid, send[i], send_requests[i], send_tag);
    }

    // receive messages - we assume that we receive as many messages as we send!
    for (auto i = beginIndex(non_zero_comm); i < non_zero_comm.size(); ++i)
    {
      // inspect incoming message
      Parallel::Status status(_communicator.probe(Parallel::any_source, send_tag));
      const auto source_pid = TIMPI::cast_int<processor_id_type>(status.source());
      const auto message_size = status.size(item_type);

      // resize receive buffer accordingly and receive data
      receive.resize(message_size);
      _communicator.receive(source_pid, receive, send_tag);

#if 0
      // output received qp locations
      // _console << name() << ' ' << receive.size() << '\n' << name() << std::flush;
      for (auto item : receive)
        _console << name() << ' ' << source_pid << ' '
                 << item._q_point(0) << ' '
                 << item._q_point(1) << ' '
                 << item._q_point(2) << std::flush;
#endif

      // append communicated data
      _qp_data.insert(_qp_data.end(), receive.begin(), receive.end());
    }

    // wait until all send requests are at least buffered and we can destroy
    // the send buffers by going out of scope
    Parallel::wait(send_requests);
  }

  // build KD-Tree using data we just received
  const unsigned int max_leaf_size = 20; // slightly affects runtime
  auto point_list = PointListAdaptor<QPData>(_qp_data.begin(), _qp_data.end());
  _kd_tree = libmesh_make_unique<KDTreeType>(
      LIBMESH_DIM, point_list, nanoflann::KDTreeSingleIndexAdaptorParams(max_leaf_size));

  mooseAssert(_kd_tree != nullptr, "KDTree was not properly initialized.");
  _kd_tree->buildIndex();

  // build thread loop functor
  ThreadedRadialAverageLoop rgcl(*this);

  // run threads
  auto local_range_begin = _qp_data.begin();
  auto local_range_end = local_range_begin;
  std::advance(local_range_end, local_size);
  Threads::parallel_reduce(QPDataRange(local_range_begin, local_range_end), rgcl);
}

void
RadialAverage::threadJoin(const UserObject & y)
{
  const RadialAverage & uo = static_cast<const RadialAverage &>(y);
  _qp_data.insert(_qp_data.begin(), uo._qp_data.begin(), uo._qp_data.end());
  _average.insert(uo._average.begin(), uo._average.end());
}

void
RadialAverage::insertNotLocalPointNeighbors(dof_id_type node)
{
  mooseAssert(!_nodes_to_elem_map[node].empty(), "Node not found in _nodes_to_elem_map");

  for (const auto * elem : _nodes_to_elem_map[node])
    if (elem->processor_id() != _my_pid && elem->active())
      _point_neighbors.insert(elem);
}

void
RadialAverage::meshChanged()
{
  TIME_SECTION(_perf_meshchanged);

  // get underlying libMesh mesh
  auto & mesh = _mesh.getMesh();

  // get a fresh point locator
  _point_locator = _mesh.getPointLocator();

  // Build a new node to element map
  _nodes_to_elem_map.clear();
  MeshTools::build_nodes_to_elem_map(_mesh.getMesh(), _nodes_to_elem_map);

  // clear point neighbor set
  _point_neighbors.clear();

  // my processor id
  const auto my_pid = processor_id();

  // iterate over active local elements
  const auto end = mesh.active_local_elements_end();
  for (auto it = mesh.active_local_elements_begin(); it != end; ++it)
    // find a face that faces either a boundary (nullptr) or a different processor
    for (unsigned int s = 0; s < (*it)->n_sides(); ++s)
    {
      const auto * neighbor = (*it)->neighbor_ptr(s);
      if (neighbor)
      {
        if (neighbor->processor_id() != my_pid)
        {
          // add all face node touching elements directly
          for (unsigned int n = 0; n < (*it)->n_nodes(); ++n)
            if ((*it)->is_node_on_side(n, s))
              insertNotLocalPointNeighbors((*it)->node_id(n));
        }
      }
    }
  // request communication list update
  _update_communication_lists = true;
}

void
RadialAverage::updateCommunicationLists()
{
  TIME_SECTION(_perf_updatelists);

  // clear communication lists
  _communication_lists.clear();
  _communication_lists.resize(n_processors());

  // build KD-Tree using local qpoint data
  const unsigned int max_leaf_size = 20; // slightly affects runtime
  auto point_list = PointListAdaptor<QPData>(_qp_data.begin(), _qp_data.end());
  auto kd_tree = libmesh_make_unique<KDTreeType>(
      LIBMESH_DIM, point_list, nanoflann::KDTreeSingleIndexAdaptorParams(max_leaf_size));
  mooseAssert(kd_tree != nullptr, "KDTree was not properly initialized.");
  kd_tree->buildIndex();

  std::vector<std::pair<std::size_t, Real>> ret_matches;
  nanoflann::SearchParams search_params;

  // iterate over non periodic point neighbor elements
  for (auto elem : _point_neighbors)
  {
    ret_matches.clear();
    Point centroid = elem->vertex_average();
    const Real r_cut2 = _r_cut + elem->hmax() / 2.0;
    kd_tree->radiusSearch(&(centroid(0)), r_cut2, ret_matches, search_params);
    for (auto & match : ret_matches)
      _communication_lists[elem->processor_id()].insert(match.first);
  }

  _update_communication_lists = false;
}

namespace TIMPI
{

StandardType<RadialAverage::QPData>::StandardType(const RadialAverage::QPData * example)
{
  // We need an example for MPI_Address to use
  static const RadialAverage::QPData p;
  if (!example)
    example = &p;

#ifdef LIBMESH_HAVE_MPI

  // Get the sub-data-types, and make sure they live long enough
  // to construct the derived type
  StandardType<Point> d1(&example->_q_point);
  StandardType<dof_id_type> d2(&example->_elem_id);
  StandardType<short> d3(&example->_qp);
  StandardType<Real> d4(&example->_volume);
  StandardType<Real> d5(&example->_value);

  MPI_Datatype types[] = {
      (data_type)d1, (data_type)d2, (data_type)d3, (data_type)d4, (data_type)d5};
  int blocklengths[] = {1, 1, 1, 1, 1};
  MPI_Aint displs[5], start;

  libmesh_call_mpi(MPI_Get_address(const_cast<RadialAverage::QPData *>(example), &start));
  libmesh_call_mpi(MPI_Get_address(const_cast<Point *>(&example->_q_point), &displs[0]));
  libmesh_call_mpi(MPI_Get_address(const_cast<dof_id_type *>(&example->_elem_id), &displs[1]));
  libmesh_call_mpi(MPI_Get_address(const_cast<short *>(&example->_qp), &displs[2]));
  libmesh_call_mpi(MPI_Get_address(const_cast<Real *>(&example->_volume), &displs[3]));
  libmesh_call_mpi(MPI_Get_address(const_cast<Real *>(&example->_value), &displs[4]));

  for (std::size_t i = 0; i < 5; ++i)
    displs[i] -= start;

  // create a prototype structure
  MPI_Datatype tmptype;
  libmesh_call_mpi(MPI_Type_create_struct(5, blocklengths, displs, types, &tmptype));
  libmesh_call_mpi(MPI_Type_commit(&tmptype));

  // resize the structure type to account for padding, if any
  libmesh_call_mpi(MPI_Type_create_resized(tmptype, 0, sizeof(RadialAverage::QPData), &_datatype));
  libmesh_call_mpi(MPI_Type_free(&tmptype));

  this->commit();

#endif // LIBMESH_HAVE_MPI
}
} // namespace TIMPI

StandardType<RadialAverage::QPData>::StandardType(const StandardType<RadialAverage::QPData> & t)
{
#ifdef LIBMESH_HAVE_MPI
  libmesh_call_mpi(MPI_Type_dup(t._datatype, &_datatype));
#endif
}
<commit_msg>Fixed header, but still trying to setup patch<commit_after>//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#include "RadialAverage.h"
#include "ThreadedRadialAverageLoop.h"
#include "NonlinearSystemBase.h"
#include "FEProblemBase.h"

#include "libmesh/nanoflann.hpp"
#include "libmesh/parallel_algebra.h"
#include "libmesh/mesh_tools.h"

#include <list>
#include <iterator>
#include <algorithm>

registerMooseObject("MooseApp", RadialAverage);

// specialization for PointListAdaptor<RadialAverage::QPData>
template <>
const Point &
PointListAdaptor<RadialAverage::QPData>::getPoint(const RadialAverage::QPData & item) const
{
  return item._q_point;
}

InputParameters
RadialAverage::validParams()
{
  InputParameters params = ElementUserObject::validParams();
  params.addClassDescription("Perform a radial equal weight average of a material property");
  params.addRequiredParam<std::string>("material_name", "Name of the material to average.");
  params.addRequiredParam<Real>("r_cut", "Cut-off radius for the averaging");

  // we run this object once at the beginning of the timestep by default
  params.set<ExecFlagEnum>("execute_on") = EXEC_TIMESTEP_BEGIN;

  // make sure we always have geometric point neighbors ghosted
  params.addRelationshipManager("ElementPointNeighborLayers",
                                Moose::RelationshipManagerType::GEOMETRIC |
                                    Moose::RelationshipManagerType::ALGEBRAIC);

  return params;
}

RadialAverage::RadialAverage(const InputParameters & parameters)
  : ElementUserObject(parameters),
    _v_name(getParam<std::string>("material_name")),
    _v(getMaterialProperty<Real>(_v_name)),
    _r_cut(getParam<Real>("r_cut")),
    _dof_map(_fe_problem.getNonlinearSystemBase().dofMap()),
    _update_communication_lists(false),
    _my_pid(processor_id()),
    _perf_meshchanged(registerTimedSection("meshChanged", 3)),
    _perf_updatelists(registerTimedSection("updateCommunicationLists", 3)),
    _perf_finalize(registerTimedSection("finalize", 2))
{
}

void
RadialAverage::initialSetup()
{
  // set up processor boundary node list
  meshChanged();
}

void
RadialAverage::initialize()
{
  _qp_data.clear();
}

void
RadialAverage::execute()
{
  auto id = _current_elem->id();

  // collect all QP data
  for (unsigned int qp = 0; qp < _qrule->n_points(); ++qp)
    _qp_data.emplace_back(_q_point[qp], id, qp, _JxW[qp] * _coord[qp], _v[qp]);

  // make sure the result map entry for the current element is sized correctly
  auto i = _average.find(id);
  if (i == _average.end())
    _average.insert(std::make_pair(id, std::vector<Real>(_qrule->n_points())));
  else
    i->second.resize(_qrule->n_points());
}

void
RadialAverage::finalize()
{
  TIME_SECTION(_perf_finalize);

  // the first chunk of data is always the local data - remember its size
  unsigned int local_size = _qp_data.size();

  // communicate the qp data list if n_proc > 1
  if (_app.n_processors() > 1)
  {
    // !!!!!!!!!!!
    // !!CAREFUL!! Is it guaranteed that _qp_data is in the same order if the mesh has not changed?
    // According to @friedmud it is not guaranteed if threads are used
    // !!!!!!!!!!!

    // update after mesh changes and/or if a displaced problem exists
    if (_update_communication_lists || _fe_problem.getDisplacedProblem() ||
        libMesh::n_threads() > 1)
      updateCommunicationLists();

    // sparse send data (processor ID,)
    std::vector<std::size_t> non_zero_comm;
    for (auto i = beginIndex(_communication_lists); i < _communication_lists.size(); ++i)
      if (!_communication_lists[i].empty())
        non_zero_comm.push_back(i);

    // data structures for sparse point to point communication
    std::vector<std::vector<QPData>> send(non_zero_comm.size());
    std::vector<Parallel::Request> send_requests(non_zero_comm.size());
    Parallel::MessageTag send_tag = _communicator.get_unique_tag(4711);
    std::vector<QPData> receive;

    const auto item_type = StandardType<QPData>(&(_qp_data[0]));

#if 0
    // output local qp locations
    // _console << name() << ' ' << receive.size() << '\n' << name() << std::flush;
    for (auto item : _qp_data)
      _console << name() << ' ' << _my_pid << ' '
               << item._q_point(0) << ' '
               << item._q_point(1) << ' '
               << item._q_point(2) << std::flush;
#endif

    // fill buffer and send structures
    for (auto i = beginIndex(non_zero_comm); i < non_zero_comm.size(); ++i)
    {
      const auto pid = non_zero_comm[i];
      const auto & list = _communication_lists[pid];

      // fill send buffer for transfer to pid
      send[i].reserve(list.size());
      for (const auto & item : list)
      {
        send[i].push_back(_qp_data[item]);
#if 0
        // output sent qp locations
        _console << name() << ' '
                 << _qp_data[item]._q_point(0) << ' '
                 << _qp_data[item]._q_point(1) << ' '
                 << _qp_data[item]._q_point(2) << ' '
                 << pid << std::flush;
#endif
      }

      // issue non-blocking send
      _communicator.send(pid, send[i], send_requests[i], send_tag);
    }

    // receive messages - we assume that we receive as many messages as we send!
    for (auto i = beginIndex(non_zero_comm); i < non_zero_comm.size(); ++i)
    {
      // inspect incoming message
      Parallel::Status status(_communicator.probe(Parallel::any_source, send_tag));
      const auto source_pid = TIMPI::cast_int<processor_id_type>(status.source());
      const auto message_size = status.size(item_type);

      // resize receive buffer accordingly and receive data
      receive.resize(message_size);
      _communicator.receive(source_pid, receive, send_tag);

#if 0
      // output received qp locations
      // _console << name() << ' ' << receive.size() << '\n' << name() << std::flush;
      for (auto item : receive)
        _console << name() << ' ' << source_pid << ' '
                 << item._q_point(0) << ' '
                 << item._q_point(1) << ' '
                 << item._q_point(2) << std::flush;
#endif

      // append communicated data
      _qp_data.insert(_qp_data.end(), receive.begin(), receive.end());
    }

    // wait until all send requests are at least buffered and we can destroy
    // the send buffers by going out of scope
    Parallel::wait(send_requests);
  }

  // build KD-Tree using data we just received
  const unsigned int max_leaf_size = 20; // slightly affects runtime
  auto point_list = PointListAdaptor<QPData>(_qp_data.begin(), _qp_data.end());
  _kd_tree = libmesh_make_unique<KDTreeType>(
      LIBMESH_DIM, point_list, nanoflann::KDTreeSingleIndexAdaptorParams(max_leaf_size));

  mooseAssert(_kd_tree != nullptr, "KDTree was not properly initialized.");
  _kd_tree->buildIndex();

  // build thread loop functor
  ThreadedRadialAverageLoop rgcl(*this);

  // run threads
  auto local_range_begin = _qp_data.begin();
  auto local_range_end = local_range_begin;
  std::advance(local_range_end, local_size);
  Threads::parallel_reduce(QPDataRange(local_range_begin, local_range_end), rgcl);
}

void
RadialAverage::threadJoin(const UserObject & y)
{
  const RadialAverage & uo = static_cast<const RadialAverage &>(y);
  _qp_data.insert(_qp_data.begin(), uo._qp_data.begin(), uo._qp_data.end());
  _average.insert(uo._average.begin(), uo._average.end());
}

void
RadialAverage::insertNotLocalPointNeighbors(dof_id_type node)
{
  mooseAssert(!_nodes_to_elem_map[node].empty(), "Node not found in _nodes_to_elem_map");

  for (const auto * elem : _nodes_to_elem_map[node])
    if (elem->processor_id() != _my_pid && elem->active())
      _point_neighbors.insert(elem);
}

void
RadialAverage::meshChanged()
{
  TIME_SECTION(_perf_meshchanged);

  // get underlying libMesh mesh
  auto & mesh = _mesh.getMesh();

  // get a fresh point locator
  _point_locator = _mesh.getPointLocator();

  // Build a new node to element map
  _nodes_to_elem_map.clear();
  MeshTools::build_nodes_to_elem_map(_mesh.getMesh(), _nodes_to_elem_map);

  // clear point neighbor set
  _point_neighbors.clear();

  // my processor id
  const auto my_pid = processor_id();

  // iterate over active local elements
  const auto end = mesh.active_local_elements_end();
  for (auto it = mesh.active_local_elements_begin(); it != end; ++it)
    // find a face that faces either a boundary (nullptr) or a different processor
    for (unsigned int s = 0; s < (*it)->n_sides(); ++s)
    {
      const auto * neighbor = (*it)->neighbor_ptr(s);
      if (neighbor)
      {
        if (neighbor->processor_id() != my_pid)
        {
          // add all face node touching elements directly
          for (unsigned int n = 0; n < (*it)->n_nodes(); ++n)
            if ((*it)->is_node_on_side(n, s))
              insertNotLocalPointNeighbors((*it)->node_id(n));
        }
      }
    }
  // request communication list update
  _update_communication_lists = true;
}

void
RadialAverage::updateCommunicationLists()
{
  TIME_SECTION(_perf_updatelists);

  // clear communication lists
  _communication_lists.clear();
  _communication_lists.resize(n_processors());

  // build KD-Tree using local qpoint data
  const unsigned int max_leaf_size = 20; // slightly affects runtime
  auto point_list = PointListAdaptor<QPData>(_qp_data.begin(), _qp_data.end());
  auto kd_tree = libmesh_make_unique<KDTreeType>(
      LIBMESH_DIM, point_list, nanoflann::KDTreeSingleIndexAdaptorParams(max_leaf_size));
  mooseAssert(kd_tree != nullptr, "KDTree was not properly initialized.");
  kd_tree->buildIndex();

  std::vector<std::pair<std::size_t, Real>> ret_matches;
  nanoflann::SearchParams search_params;

  // iterate over non periodic point neighbor elements
  for (auto elem : _point_neighbors)
  {
    ret_matches.clear();
    Point centroid = elem->vertex_average();
    const Real r_cut2 = _r_cut + elem->hmax() / 2.0;
    kd_tree->radiusSearch(&(centroid(0)), r_cut2, ret_matches, search_params);
    for (auto & match : ret_matches)
      _communication_lists[elem->processor_id()].insert(match.first);
  }

  _update_communication_lists = false;
}

namespace TIMPI
{

StandardType<RadialAverage::QPData>::StandardType(const RadialAverage::QPData * example)
{
  // We need an example for MPI_Address to use
  static const RadialAverage::QPData p;
  if (!example)
    example = &p;

#ifdef LIBMESH_HAVE_MPI

  // Get the sub-data-types, and make sure they live long enough
  // to construct the derived type
  StandardType<Point> d1(&example->_q_point);
  StandardType<dof_id_type> d2(&example->_elem_id);
  StandardType<short> d3(&example->_qp);
  StandardType<Real> d4(&example->_volume);
  StandardType<Real> d5(&example->_value);

  MPI_Datatype types[] = {
      (data_type)d1, (data_type)d2, (data_type)d3, (data_type)d4, (data_type)d5};
  int blocklengths[] = {1, 1, 1, 1, 1};
  MPI_Aint displs[5], start;

  libmesh_call_mpi(MPI_Get_address(const_cast<RadialAverage::QPData *>(example), &start));
  libmesh_call_mpi(MPI_Get_address(const_cast<Point *>(&example->_q_point), &displs[0]));
  libmesh_call_mpi(MPI_Get_address(const_cast<dof_id_type *>(&example->_elem_id), &displs[1]));
  libmesh_call_mpi(MPI_Get_address(const_cast<short *>(&example->_qp), &displs[2]));
  libmesh_call_mpi(MPI_Get_address(const_cast<Real *>(&example->_volume), &displs[3]));
  libmesh_call_mpi(MPI_Get_address(const_cast<Real *>(&example->_value), &displs[4]));

  for (std::size_t i = 0; i < 5; ++i)
    displs[i] -= start;

  // create a prototype structure
  MPI_Datatype tmptype;
  libmesh_call_mpi(MPI_Type_create_struct(5, blocklengths, displs, types, &tmptype));
  libmesh_call_mpi(MPI_Type_commit(&tmptype));

  // resize the structure type to account for padding, if any
  libmesh_call_mpi(MPI_Type_create_resized(tmptype, 0, sizeof(RadialAverage::QPData), &_datatype));
  libmesh_call_mpi(MPI_Type_free(&tmptype));

  this->commit();

#endif // LIBMESH_HAVE_MPI
}
} // namespace TIMPI

StandardType<RadialAverage::QPData>::StandardType(const StandardType<RadialAverage::QPData> & t)
{
#ifdef LIBMESH_HAVE_MPI
  libmesh_call_mpi(MPI_Type_dup(t._datatype, &_datatype));
#endif
}
<|endoftext|>