<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/p9_mss_memdiag.C $  */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file p9_mss_memdiag.C
/// @brief Mainstore pattern testing
///
// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB

#include <fapi2.H>
#include <p9_mss_memdiag.H>

#include <lib/utils/poll.H>
#include <generic/memory/lib/utils/find.H>
#include <lib/utils/count_dimm.H>
#include <lib/mcbist/address.H>
#include <lib/mcbist/memdiags.H>
#include <lib/mcbist/mcbist.H>
#include <lib/mc/port.H>
#include <lib/ecc/ecc.H>

using fapi2::TARGET_TYPE_MCBIST;
using fapi2::TARGET_TYPE_SYSTEM;
using fapi2::TARGET_TYPE_MCA;

extern "C"
{
    ///
    /// @brief Pattern test the DRAM
    /// @param[in] i_target the McBIST of the ports of the dram you're training
    /// @return FAPI2_RC_SUCCESS iff ok
    ///
    fapi2::ReturnCode p9_mss_memdiag( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target )
    {
        FAPI_INF("Start memdiag");

        // If there are no DIMM we don't need to bother. In fact, we can't as we didn't setup
        // attributes for the PHY, etc.
        if (mss::count_dimm(i_target) == 0)
        {
            FAPI_INF("... skipping mem_diags %s - no DIMM ...", mss::c_str(i_target));
            return fapi2::FAPI2_RC_SUCCESS;
        }

        uint8_t l_sim = false;
        FAPI_TRY( mss::is_simulation( l_sim) );

        // Read the bad_dq_bitmap attribute and place corresponding symbol and chip marks
        for (const auto& l_mca : mss::find_targets<TARGET_TYPE_MCA>(i_target))
        {
            fapi2::buffer<uint8_t> l_repairs_applied;
            fapi2::buffer<uint8_t> l_repairs_exceeded;
            std::vector<uint64_t> l_ranks;

            FAPI_TRY( mss::restore_repairs( l_mca, l_repairs_applied, l_repairs_exceeded) );

            // assert if we have exceeded the allowed repairs
            for (const auto& l_dimm : mss::find_targets<fapi2::TARGET_TYPE_DIMM>(l_mca))
            {
                // Note: using MCA here as the scoms used to collect FFDC data fail on the DIMM level target
                FAPI_ASSERT( !(l_repairs_exceeded.getBit(mss::index(l_dimm))),
                             fapi2::MSS_MEMDIAGS_REPAIRS_EXCEEDED().set_MCA_TARGET(l_mca),
                             "p9_mss_memdiag bad bit repairs exceeded %s", mss::c_str(l_mca) );
            }

#ifdef __HOSTBOOT_MODULE
            // assert if both chip and symbol marks exist for any given rank
            FAPI_TRY( mss::rank::ranks(l_mca, l_ranks) );

            for (const auto l_rank : l_ranks)
            {
                if (l_repairs_applied.getBit(l_rank))
                {
                    uint64_t l_galois = 0;
                    mss::states l_confirmed = mss::NO;
                    // check for chip mark in hardware mark store
                    FAPI_TRY( mss::ecc::get_hwms(l_mca, l_rank, l_galois, l_confirmed) );

                    if (l_confirmed)
                    {
                        auto l_type = mss::ecc::fwms::mark_type::CHIP;
                        auto l_region = mss::ecc::fwms::mark_region::DISABLED;
                        auto l_addr = mss::mcbist::address(0);
                        // check for symbol mark in firmware mark store
                        FAPI_TRY( mss::ecc::get_fwms(l_mca, l_rank, l_galois, l_type, l_region, l_addr) );

                        FAPI_ASSERT( l_region == mss::ecc::fwms::mark_region::DISABLED,
                                     fapi2::MSS_MEMDIAGS_CHIPMARK_AND_SYMBOLMARK().set_MCA_TARGET(l_mca).set_RANK(l_rank),
                                     "p9_mss_memdiag both chip mark and symbol mark on rank %d: %s", l_rank, mss::c_str(l_mca) );
                    }
                }
            }

#endif
        }

        // We start the sf_init (write 0's) and it'll tickle the MCBIST complete FIR. PRD will see that
        // and start a background scrub.
        FAPI_TRY( mss::memdiags::sf_init(i_target, mss::mcbist::PATTERN_0) );

        // If we're in the sim, we want to poll for the FIR bit. I don't think this ever really happens
        // unless we're expressly testing this API.
        if (l_sim)
        {
            // Poll for the fir bit. We expect this to be set ...
            fapi2::buffer<uint64_t> l_status;

            // A small vector of addresses to poll during the polling loop
            const std::vector<mss::poll_probe<fapi2::TARGET_TYPE_MCBIST>> l_probes =
            {
                {i_target, "mcbist current address", MCBIST_MCBMCATQ},
            };

            mss::poll_parameters l_poll_parameters;
            bool l_poll_results = mss::poll(i_target, MCBIST_MCBISTFIRQ, l_poll_parameters,
                                            [&l_status](const size_t poll_remaining,
                                                    const fapi2::buffer<uint64_t>& stat_reg) -> bool
            {
                FAPI_DBG("mcbist firq 0x%llx, remaining: %d", stat_reg, poll_remaining);
                l_status = stat_reg;
                return l_status.getBit<MCBIST_MCBISTFIRQ_MCBIST_PROGRAM_COMPLETE>() == true;
            },
            l_probes);

            FAPI_ASSERT( l_poll_results == true,
                         fapi2::MSS_MEMDIAGS_SUPERFAST_INIT_FAILED_TO_INIT().set_MCBIST_TARGET(i_target),
                         "p9_mss_memdiags timedout %s", mss::c_str(i_target) );
        }

    fapi_try_exit:
        FAPI_INF("End memdiag");
        return fapi2::current_err;
    }
}
<commit_msg>Updated MSS HWP's level and owner change<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/p9_mss_memdiag.C $  */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file p9_mss_memdiag.C
/// @brief Mainstore pattern testing
///
// *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 3
// *HWP Consumed by: FSP:HB

#include <fapi2.H>
#include <p9_mss_memdiag.H>

#include <lib/utils/poll.H>
#include <generic/memory/lib/utils/find.H>
#include <lib/utils/count_dimm.H>
#include <lib/mcbist/address.H>
#include <lib/mcbist/memdiags.H>
#include <lib/mcbist/mcbist.H>
#include <lib/mc/port.H>
#include <lib/ecc/ecc.H>

using fapi2::TARGET_TYPE_MCBIST;
using fapi2::TARGET_TYPE_SYSTEM;
using fapi2::TARGET_TYPE_MCA;

extern "C"
{
    ///
    /// @brief Pattern test the DRAM
    /// @param[in] i_target the McBIST of the ports of the dram you're training
    /// @return FAPI2_RC_SUCCESS iff ok
    ///
    fapi2::ReturnCode p9_mss_memdiag( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target )
    {
        FAPI_INF("Start memdiag");

        // If there are no DIMM we don't need to bother. In fact, we can't as we didn't setup
        // attributes for the PHY, etc.
        if (mss::count_dimm(i_target) == 0)
        {
            FAPI_INF("... skipping mem_diags %s - no DIMM ...", mss::c_str(i_target));
            return fapi2::FAPI2_RC_SUCCESS;
        }

        uint8_t l_sim = false;
        FAPI_TRY( mss::is_simulation( l_sim) );

        // Read the bad_dq_bitmap attribute and place corresponding symbol and chip marks
        for (const auto& l_mca : mss::find_targets<TARGET_TYPE_MCA>(i_target))
        {
            fapi2::buffer<uint8_t> l_repairs_applied;
            fapi2::buffer<uint8_t> l_repairs_exceeded;
            std::vector<uint64_t> l_ranks;

            FAPI_TRY( mss::restore_repairs( l_mca, l_repairs_applied, l_repairs_exceeded) );

            // assert if we have exceeded the allowed repairs
            for (const auto& l_dimm : mss::find_targets<fapi2::TARGET_TYPE_DIMM>(l_mca))
            {
                // Note: using MCA here as the scoms used to collect FFDC data fail on the DIMM level target
                FAPI_ASSERT( !(l_repairs_exceeded.getBit(mss::index(l_dimm))),
                             fapi2::MSS_MEMDIAGS_REPAIRS_EXCEEDED().set_MCA_TARGET(l_mca),
                             "p9_mss_memdiag bad bit repairs exceeded %s", mss::c_str(l_mca) );
            }

#ifdef __HOSTBOOT_MODULE
            // assert if both chip and symbol marks exist for any given rank
            FAPI_TRY( mss::rank::ranks(l_mca, l_ranks) );

            for (const auto l_rank : l_ranks)
            {
                if (l_repairs_applied.getBit(l_rank))
                {
                    uint64_t l_galois = 0;
                    mss::states l_confirmed = mss::NO;
                    // check for chip mark in hardware mark store
                    FAPI_TRY( mss::ecc::get_hwms(l_mca, l_rank, l_galois, l_confirmed) );

                    if (l_confirmed)
                    {
                        auto l_type = mss::ecc::fwms::mark_type::CHIP;
                        auto l_region = mss::ecc::fwms::mark_region::DISABLED;
                        auto l_addr = mss::mcbist::address(0);
                        // check for symbol mark in firmware mark store
                        FAPI_TRY( mss::ecc::get_fwms(l_mca, l_rank, l_galois, l_type, l_region, l_addr) );

                        FAPI_ASSERT( l_region == mss::ecc::fwms::mark_region::DISABLED,
                                     fapi2::MSS_MEMDIAGS_CHIPMARK_AND_SYMBOLMARK().set_MCA_TARGET(l_mca).set_RANK(l_rank),
                                     "p9_mss_memdiag both chip mark and symbol mark on rank %d: %s", l_rank, mss::c_str(l_mca) );
                    }
                }
            }

#endif
        }

        // We start the sf_init (write 0's) and it'll tickle the MCBIST complete FIR. PRD will see that
        // and start a background scrub.
        FAPI_TRY( mss::memdiags::sf_init(i_target, mss::mcbist::PATTERN_0) );

        // If we're in the sim, we want to poll for the FIR bit. I don't think this ever really happens
        // unless we're expressly testing this API.
        if (l_sim)
        {
            // Poll for the fir bit. We expect this to be set ...
            fapi2::buffer<uint64_t> l_status;

            // A small vector of addresses to poll during the polling loop
            const std::vector<mss::poll_probe<fapi2::TARGET_TYPE_MCBIST>> l_probes =
            {
                {i_target, "mcbist current address", MCBIST_MCBMCATQ},
            };

            mss::poll_parameters l_poll_parameters;
            bool l_poll_results = mss::poll(i_target, MCBIST_MCBISTFIRQ, l_poll_parameters,
                                            [&l_status](const size_t poll_remaining,
                                                    const fapi2::buffer<uint64_t>& stat_reg) -> bool
            {
                FAPI_DBG("mcbist firq 0x%llx, remaining: %d", stat_reg, poll_remaining);
                l_status = stat_reg;
                return l_status.getBit<MCBIST_MCBISTFIRQ_MCBIST_PROGRAM_COMPLETE>() == true;
            },
            l_probes);

            FAPI_ASSERT( l_poll_results == true,
                         fapi2::MSS_MEMDIAGS_SUPERFAST_INIT_FAILED_TO_INIT().set_MCBIST_TARGET(i_target),
                         "p9_mss_memdiags timedout %s", mss::c_str(i_target) );
        }

    fapi_try_exit:
        FAPI_INF("End memdiag");
        return fapi2::current_err;
    }
}
<|endoftext|>


<commit_before>/*
Copyright (C) 2016 - Gbor "Razzie" Grzsny

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
*/

#pragma once

#include <functional>
#include <future>
#include <mutex>
#include <list>
#include <thread>

namespace raz
{
	template<class T>
	class Thread
	{
	public:
		template<class... Args>
		Thread(Args... args) :
			m_object(std::forward<Args>(args)...)
		{
			m_thread = std::thread(&Thread<T>::run, this);
		}

		Thread(const Thread&) = delete;

		Thread& operator=(const Thread&) = delete;

		~Thread()
		{
			m_exit_token.set_value();
			m_thread.join();
		}

		template<class... Args>
		void operator()(Args... args)
		{
			std::lock_guard<std::mutex> guard(m_mutex);
			m_call_queue.emplace_back([this, args...]() { m_object(args...); });
		}

	private:
		std::thread m_thread;
		std::promise<void> m_exit_token;
		std::mutex m_mutex;
		std::list<std::function<void()>> m_call_queue;
		T m_object;

		class HasParenthesisOp
		{
			template<class U>
			static auto test(bool) -> decltype(std::declval<U>()(), void(), std::true_type{})
			{
				return {};
			}

			template<class U>
			static auto test(int) -> std::false_type
			{
				return {};
			}

		public:
			static constexpr bool value = decltype(test<T>(true))::value;
		};

		template<bool>
		void loop();

		template<>
		void loop<true>()
		{
			m_object();
		}

		template<>
		void loop<false>()
		{
		}

		void run()
		{
			std::future<void> exit_token = m_exit_token.get_future();
			std::list<std::function<void()>> call_queue;

			for (;;)
			{
				m_mutex.lock();
				std::swap(m_call_queue, call_queue);
				m_mutex.unlock();

				for (auto& call : call_queue)
					call();

				call_queue.clear();

				loop<HasParenthesisOp::value>();

				auto exit_status = exit_token.wait_for(std::chrono::milliseconds(1));
				if (exit_status == std::future_status::ready) return;
			}
		}
	};
}
<commit_msg>The internal object of Thread is constructed inside the newly started thread<commit_after>/*
Copyright (C) 2016 - Gbor "Razzie" Grzsny

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
*/

#pragma once

#include <functional>
#include <future>
#include <mutex>
#include <list>
#include <thread>

namespace raz
{
	template<class T>
	class Thread
	{
	public:
		template<class... Args>
		Thread(Args... args)
		{
			m_thread = std::thread(&Thread<T>::run<Args...>, this, std::forward<Args>(args)...);
		}

		Thread(const Thread&) = delete;

		Thread& operator=(const Thread&) = delete;

		~Thread()
		{
			m_exit_token.set_value();
			m_thread.join();
		}

		template<class... Args>
		void operator()(Args... args)
		{
			std::lock_guard<std::mutex> guard(m_mutex);
			m_call_queue.emplace_back([args...](T& object) { object(args...); });
		}

	private:
		typedef std::function<void(T&)> ForwardedCall;

		std::thread m_thread;
		std::promise<void> m_exit_token;
		std::mutex m_mutex;
		std::list<ForwardedCall> m_call_queue;

		class HasParenthesisOp
		{
			template<class U>
			static auto test(bool) -> decltype(std::declval<U>()(), void(), std::true_type{})
			{
				return {};
			}

			template<class U>
			static auto test(int) -> std::false_type
			{
				return {};
			}

		public:
			static constexpr bool value = decltype(test<T>(true))::value;
		};

		template<bool>
		void loop(T&);

		template<>
		void loop<true>(T& object)
		{
			object();
		}

		template<>
		void loop<false>(T& object)
		{
		}

		template<class... Args>
		void run(Args... args)
		{
			T object(std::forward<Args>(args)...);
			std::future<void> exit_token = m_exit_token.get_future();
			std::list<ForwardedCall> call_queue;

			for (;;)
			{
				m_mutex.lock();
				std::swap(m_call_queue, call_queue);
				m_mutex.unlock();

				for (auto& call : call_queue)
					call(object);

				call_queue.clear();

				loop<HasParenthesisOp::value>(object);

				auto exit_status = exit_token.wait_for(std::chrono::milliseconds(1));
				if (exit_status == std::future_status::ready) return;
			}
		}
	};
}
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/p9_mss_memdiag.C $  */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file p9_mss_memdiag.C
/// @brief Mainstore pattern testing
///
// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB

#include <fapi2.H>
#include <p9_mss_memdiag.H>

#include <lib/utils/poll.H>
#include <generic/memory/lib/utils/find.H>
#include <lib/utils/count_dimm.H>
#include <lib/mcbist/address.H>
#include <lib/mcbist/memdiags.H>
#include <lib/mcbist/mcbist.H>
#include <lib/mc/port.H>
#include <lib/ecc/ecc.H>

using fapi2::TARGET_TYPE_MCBIST;
using fapi2::TARGET_TYPE_SYSTEM;
using fapi2::TARGET_TYPE_MCA;

extern "C"
{
    ///
    /// @brief Pattern test the DRAM
    /// @param[in] i_target the McBIST of the ports of the dram you're training
    /// @return FAPI2_RC_SUCCESS iff ok
    ///
    fapi2::ReturnCode p9_mss_memdiag( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target )
    {
        FAPI_INF("Start memdiag");

        // If there are no DIMM we don't need to bother. In fact, we can't as we didn't setup
        // attributes for the PHY, etc.
        if (mss::count_dimm(i_target) == 0)
        {
            FAPI_INF("... skipping mem_diags %s - no DIMM ...", mss::c_str(i_target));
            return fapi2::FAPI2_RC_SUCCESS;
        }

        uint8_t l_sim = false;
        FAPI_TRY( mss::is_simulation( l_sim) );

        // Read the bad_dq_bitmap attribute and place corresponding symbol and chip marks
        for (const auto& l_mca : mss::find_targets<TARGET_TYPE_MCA>(i_target))
        {
            fapi2::buffer<uint8_t> l_repairs_applied;
            fapi2::buffer<uint8_t> l_repairs_exceeded;
            std::vector<uint64_t> l_ranks;

            FAPI_TRY( mss::restore_repairs( l_mca, l_repairs_applied, l_repairs_exceeded) );

            // assert if we have exceeded the allowed repairs
            for (const auto& l_dimm : mss::find_targets<fapi2::TARGET_TYPE_DIMM>(l_mca))
            {
                FAPI_ASSERT( !(l_repairs_exceeded.getBit(mss::index(l_dimm))),
                             fapi2::MSS_MEMDIAGS_REPAIRS_EXCEEDED().set_TARGET(l_dimm),
                             "p9_mss_memdiag bad bit repairs exceeded %s", mss::c_str(l_dimm) );
            }

#ifdef __HOSTBOOT_MODULE
            // assert if both chip and symbol marks exist for any given rank
            FAPI_TRY( mss::rank::ranks(l_mca, l_ranks) );

            for (const auto l_rank : l_ranks)
            {
                if (l_repairs_applied.getBit(l_rank))
                {
                    uint64_t l_galois = 0;
                    mss::states l_confirmed = mss::NO;
                    // check for chip mark in hardware mark store
                    FAPI_TRY( mss::ecc::get_hwms(l_mca, l_rank, l_galois, l_confirmed) );

                    if (l_confirmed)
                    {
                        auto l_type = mss::ecc::fwms::mark_type::CHIP;
                        auto l_region = mss::ecc::fwms::mark_region::DISABLED;
                        auto l_addr = mss::mcbist::address(0);
                        // check for symbol mark in firmware mark store
                        FAPI_TRY( mss::ecc::get_fwms(l_mca, l_rank, l_galois, l_type, l_region, l_addr) );

                        FAPI_ASSERT( l_region == mss::ecc::fwms::mark_region::DISABLED,
                                     fapi2::MSS_MEMDIAGS_CHIPMARK_AND_SYMBOLMARK().set_TARGET(l_mca).set_RANK(l_rank),
                                     "p9_mss_memdiag both chip mark and symbol mark on rank %d: %s", l_rank, mss::c_str(l_mca) );
                    }
                }
            }

#endif
        }

        // We start the sf_init (write 0's) and it'll tickle the MCBIST complete FIR. PRD will see that
        // and start a background scrub.
        FAPI_TRY( memdiags::sf_init(i_target, mss::mcbist::PATTERN_0) );

        // If we're in the sim, we want to poll for the FIR bit. I don't think this ever really happens
        // unless we're expressly testing this API.
        if (l_sim)
        {
            // Poll for the fir bit. We expect this to be set ...
            fapi2::buffer<uint64_t> l_status;

            // A small vector of addresses to poll during the polling loop
            const std::vector<mss::poll_probe<fapi2::TARGET_TYPE_MCBIST>> l_probes =
            {
                {i_target, "mcbist current address", MCBIST_MCBMCATQ},
            };

            mss::poll_parameters l_poll_parameters;
            bool l_poll_results = mss::poll(i_target, MCBIST_MCBISTFIRQ, l_poll_parameters,
                                            [&l_status](const size_t poll_remaining,
                                                    const fapi2::buffer<uint64_t>& stat_reg) -> bool
            {
                FAPI_DBG("mcbist firq 0x%llx, remaining: %d", stat_reg, poll_remaining);
                l_status = stat_reg;
                return l_status.getBit<MCBIST_MCBISTFIRQ_MCBIST_PROGRAM_COMPLETE>() == true;
            },
            l_probes);

            FAPI_ASSERT( l_poll_results == true,
                         fapi2::MSS_MEMDIAGS_SUPERFAST_INIT_FAILED_TO_INIT().set_TARGET(i_target),
                         "p9_mss_memdiags timedout %s", mss::c_str(i_target) );
        }

    fapi_try_exit:
        FAPI_INF("End memdiag");
        return fapi2::current_err;
    }
}
<commit_msg>Fixed memdiags fail<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/p9_mss_memdiag.C $  */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file p9_mss_memdiag.C
/// @brief Mainstore pattern testing
///
// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB

#include <fapi2.H>
#include <p9_mss_memdiag.H>

#include <lib/utils/poll.H>
#include <generic/memory/lib/utils/find.H>
#include <lib/utils/count_dimm.H>
#include <lib/mcbist/address.H>
#include <lib/mcbist/memdiags.H>
#include <lib/mcbist/mcbist.H>
#include <lib/mc/port.H>
#include <lib/ecc/ecc.H>

using fapi2::TARGET_TYPE_MCBIST;
using fapi2::TARGET_TYPE_SYSTEM;
using fapi2::TARGET_TYPE_MCA;

extern "C"
{
    ///
    /// @brief Pattern test the DRAM
    /// @param[in] i_target the McBIST of the ports of the dram you're training
    /// @return FAPI2_RC_SUCCESS iff ok
    ///
    fapi2::ReturnCode p9_mss_memdiag( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target )
    {
        FAPI_INF("Start memdiag");

        // If there are no DIMM we don't need to bother. In fact, we can't as we didn't setup
        // attributes for the PHY, etc.
        if (mss::count_dimm(i_target) == 0)
        {
            FAPI_INF("... skipping mem_diags %s - no DIMM ...", mss::c_str(i_target));
            return fapi2::FAPI2_RC_SUCCESS;
        }

        uint8_t l_sim = false;
        FAPI_TRY( mss::is_simulation( l_sim) );

        // Read the bad_dq_bitmap attribute and place corresponding symbol and chip marks
        for (const auto& l_mca : mss::find_targets<TARGET_TYPE_MCA>(i_target))
        {
            fapi2::buffer<uint8_t> l_repairs_applied;
            fapi2::buffer<uint8_t> l_repairs_exceeded;
            std::vector<uint64_t> l_ranks;

            FAPI_TRY( mss::restore_repairs( l_mca, l_repairs_applied, l_repairs_exceeded) );

            // assert if we have exceeded the allowed repairs
            for (const auto& l_dimm : mss::find_targets<fapi2::TARGET_TYPE_DIMM>(l_mca))
            {
                // Note: using MCA here as the scoms used to collect FFDC data fail on the DIMM level target
                FAPI_ASSERT( !(l_repairs_exceeded.getBit(mss::index(l_dimm))),
                             fapi2::MSS_MEMDIAGS_REPAIRS_EXCEEDED().set_TARGET(l_mca),
                             "p9_mss_memdiag bad bit repairs exceeded %s", mss::c_str(l_mca) );
            }

#ifdef __HOSTBOOT_MODULE
            // assert if both chip and symbol marks exist for any given rank
            FAPI_TRY( mss::rank::ranks(l_mca, l_ranks) );

            for (const auto l_rank : l_ranks)
            {
                if (l_repairs_applied.getBit(l_rank))
                {
                    uint64_t l_galois = 0;
                    mss::states l_confirmed = mss::NO;
                    // check for chip mark in hardware mark store
                    FAPI_TRY( mss::ecc::get_hwms(l_mca, l_rank, l_galois, l_confirmed) );

                    if (l_confirmed)
                    {
                        auto l_type = mss::ecc::fwms::mark_type::CHIP;
                        auto l_region = mss::ecc::fwms::mark_region::DISABLED;
                        auto l_addr = mss::mcbist::address(0);
                        // check for symbol mark in firmware mark store
                        FAPI_TRY( mss::ecc::get_fwms(l_mca, l_rank, l_galois, l_type, l_region, l_addr) );

                        FAPI_ASSERT( l_region == mss::ecc::fwms::mark_region::DISABLED,
                                     fapi2::MSS_MEMDIAGS_CHIPMARK_AND_SYMBOLMARK().set_TARGET(l_mca).set_RANK(l_rank),
                                     "p9_mss_memdiag both chip mark and symbol mark on rank %d: %s", l_rank, mss::c_str(l_mca) );
                    }
                }
            }

#endif
        }

        // We start the sf_init (write 0's) and it'll tickle the MCBIST complete FIR. PRD will see that
        // and start a background scrub.
        FAPI_TRY( memdiags::sf_init(i_target, mss::mcbist::PATTERN_0) );

        // If we're in the sim, we want to poll for the FIR bit. I don't think this ever really happens
        // unless we're expressly testing this API.
        if (l_sim)
        {
            // Poll for the fir bit. We expect this to be set ...
            fapi2::buffer<uint64_t> l_status;

            // A small vector of addresses to poll during the polling loop
            const std::vector<mss::poll_probe<fapi2::TARGET_TYPE_MCBIST>> l_probes =
            {
                {i_target, "mcbist current address", MCBIST_MCBMCATQ},
            };

            mss::poll_parameters l_poll_parameters;
            bool l_poll_results = mss::poll(i_target, MCBIST_MCBISTFIRQ, l_poll_parameters,
                                            [&l_status](const size_t poll_remaining,
                                                    const fapi2::buffer<uint64_t>& stat_reg) -> bool
            {
                FAPI_DBG("mcbist firq 0x%llx, remaining: %d", stat_reg, poll_remaining);
                l_status = stat_reg;
                return l_status.getBit<MCBIST_MCBISTFIRQ_MCBIST_PROGRAM_COMPLETE>() == true;
            },
            l_probes);

            FAPI_ASSERT( l_poll_results == true,
                         fapi2::MSS_MEMDIAGS_SUPERFAST_INIT_FAILED_TO_INIT().set_TARGET(i_target),
                         "p9_mss_memdiags timedout %s", mss::c_str(i_target) );
        }

    fapi_try_exit:
        FAPI_INF("End memdiag");
        return fapi2::current_err;
    }
}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */
#ifndef INCLUDED_TOOLS_LINK_HXX
#define INCLUDED_TOOLS_LINK_HXX

#include <tools/toolsdllapi.h>
#include <sal/config.h>
#include <sal/types.h>
#include <tools/solar.h>

typedef sal_IntPtr (*PSTUB)( void*, void* );

#define DECL_LINK( Method, ArgType ) \
    sal_IntPtr Method( ArgType ); \
    static sal_IntPtr LinkStub##Method( void* pThis, void* )

#define DECL_STATIC_LINK( Class, Method, ArgType ) \
    static sal_IntPtr LinkStub##Method( void* pThis, void* ); \
    static sal_IntPtr Method( Class*, ArgType )

#define DECL_DLLPRIVATE_LINK(Method, ArgType) \
    SAL_DLLPRIVATE sal_IntPtr Method(ArgType); \
    SAL_DLLPRIVATE static sal_IntPtr LinkStub##Method(void * pThis, void *)

#define DECL_DLLPRIVATE_STATIC_LINK(Class, Method, ArgType) \
    SAL_DLLPRIVATE static sal_IntPtr LinkStub##Method( void* pThis, void* ); \
    SAL_DLLPRIVATE static sal_IntPtr Method(Class *, ArgType)

#define IMPL_STUB(Class, Method, ArgType) \
    sal_IntPtr Class::LinkStub##Method( void* pThis, void* pCaller) \
    { \
        return static_cast<Class*>(pThis)->Method( static_cast<ArgType>(pCaller) ); \
    }

#define IMPL_STATIC_LINK( Class, Method, ArgType, ArgName ) \
    sal_IntPtr Class::LinkStub##Method( void* pThis, void* pCaller) \
    { \
        return Method( static_cast<Class*>(pThis), static_cast<ArgType>(pCaller) ); \
    } \
    sal_IntPtr Class::Method( Class* pThis, ArgType ArgName )

#define IMPL_STATIC_LINK_NOINSTANCE( Class, Method, ArgType, ArgName ) \
    sal_IntPtr Class::LinkStub##Method( void* pThis, void* pCaller) \
    { \
        return Method( static_cast<Class*>(pThis), static_cast<ArgType>(pCaller) ); \
    } \
    sal_IntPtr Class::Method( SAL_UNUSED_PARAMETER Class*, ArgType ArgName )

#define IMPL_STATIC_LINK_NOINSTANCE_NOARG( Class, Method ) \
    sal_IntPtr Class::LinkStub##Method( void* pThis, void* pCaller) \
    { \
        return Method( static_cast<Class*>(pThis), pCaller ); \
    } \
    sal_IntPtr Class::Method( SAL_UNUSED_PARAMETER Class*, SAL_UNUSED_PARAMETER void* )

#define LINK( Inst, Class, Member ) \
    Link( static_cast<Class*>(Inst), (PSTUB)&Class::LinkStub##Member )

#define STATIC_LINK( Inst, Class, Member ) LINK(Inst, Class, Member)

#define IMPL_LINK( Class, Method, ArgType, ArgName ) \
    IMPL_STUB( Class, Method, ArgType ) \
    sal_IntPtr Class::Method( ArgType ArgName )

#define IMPL_LINK_NOARG( Class, Method ) \
    IMPL_STUB( Class, Method, void* ) \
    sal_IntPtr Class::Method( SAL_UNUSED_PARAMETER void* )

#define IMPL_LINK_INLINE_START( Class, Method, ArgType, ArgName ) \
    inline sal_IntPtr Class::Method( ArgType ArgName )

#define IMPL_LINK_INLINE_END( Class, Method, ArgType, ArgName ) \
    IMPL_STUB( Class, Method, ArgType )

#define IMPL_LINK_NOARG_INLINE_START( Class, Method ) \
    inline sal_IntPtr Class::Method( SAL_UNUSED_PARAMETER void* )

#define IMPL_LINK_NOARG_INLINE_END( Class, Method ) \
    IMPL_STUB( Class, Method, void* )

#define IMPL_LINK_INLINE( Class, Method, ArgType, ArgName, Body ) \
    sal_IntPtr Class::Method( ArgType ArgName ) \
    Body \
    IMPL_STUB( Class, Method, ArgType )

#define EMPTYARG

class TOOLS_DLLPUBLIC Link
{
    void*       pInst;
    PSTUB       pFunc;

public:
                Link();
                Link( void* pLinkHdl, PSTUB pMemFunc );

    sal_IntPtr      Call( void* pCaller ) const;

    bool            IsSet() const;
    bool            operator !() const;

    bool            operator==( const Link& rLink ) const;
    bool            operator!=( const Link& rLink ) const
                    { return !(Link::operator==( rLink )); }
    bool            operator<( const Link& rLink ) const
                    { return reinterpret_cast<sal_uIntPtr>(rLink.pFunc) < reinterpret_cast<sal_uIntPtr>(pFunc); }
};

inline Link::Link()
{
    pInst = 0;
    pFunc = 0;
}

inline Link::Link( void* pLinkHdl, PSTUB pMemFunc )
{
    pInst = pLinkHdl;
    pFunc = pMemFunc;
}

inline sal_IntPtr Link::Call(void *pCaller) const
{
    return pFunc ? (*pFunc)(pInst, pCaller) : 0;
}

inline bool Link::IsSet() const
{
    if ( pFunc )
        return true;
    else
        return false;
}

inline bool Link::operator !() const
{
    if ( !pFunc )
        return true;
    else
        return false;
}

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>Remove redundant C-style cast<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */
#ifndef INCLUDED_TOOLS_LINK_HXX
#define INCLUDED_TOOLS_LINK_HXX

#include <tools/toolsdllapi.h>
#include <sal/config.h>
#include <sal/types.h>
#include <tools/solar.h>

typedef sal_IntPtr (*PSTUB)( void*, void* );

#define DECL_LINK( Method, ArgType ) \
    sal_IntPtr Method( ArgType ); \
    static sal_IntPtr LinkStub##Method( void* pThis, void* )

#define DECL_STATIC_LINK( Class, Method, ArgType ) \
    static sal_IntPtr LinkStub##Method( void* pThis, void* ); \
    static sal_IntPtr Method( Class*, ArgType )

#define DECL_DLLPRIVATE_LINK(Method, ArgType) \
    SAL_DLLPRIVATE sal_IntPtr Method(ArgType); \
    SAL_DLLPRIVATE static sal_IntPtr LinkStub##Method(void * pThis, void *)

#define DECL_DLLPRIVATE_STATIC_LINK(Class, Method, ArgType) \
    SAL_DLLPRIVATE static sal_IntPtr LinkStub##Method( void* pThis, void* ); \
    SAL_DLLPRIVATE static sal_IntPtr Method(Class *, ArgType)

#define IMPL_STUB(Class, Method, ArgType) \
    sal_IntPtr Class::LinkStub##Method( void* pThis, void* pCaller) \
    { \
        return static_cast<Class*>(pThis)->Method( static_cast<ArgType>(pCaller) ); \
    }

#define IMPL_STATIC_LINK( Class, Method, ArgType, ArgName ) \
    sal_IntPtr Class::LinkStub##Method( void* pThis, void* pCaller) \
    { \
        return Method( static_cast<Class*>(pThis), static_cast<ArgType>(pCaller) ); \
    } \
    sal_IntPtr Class::Method( Class* pThis, ArgType ArgName )

#define IMPL_STATIC_LINK_NOINSTANCE( Class, Method, ArgType, ArgName ) \
    sal_IntPtr Class::LinkStub##Method( void* pThis, void* pCaller) \
    { \
        return Method( static_cast<Class*>(pThis), static_cast<ArgType>(pCaller) ); \
    } \
    sal_IntPtr Class::Method( SAL_UNUSED_PARAMETER Class*, ArgType ArgName )

#define IMPL_STATIC_LINK_NOINSTANCE_NOARG( Class, Method ) \
    sal_IntPtr Class::LinkStub##Method( void* pThis, void* pCaller) \
    { \
        return Method( static_cast<Class*>(pThis), pCaller ); \
    } \
    sal_IntPtr Class::Method( SAL_UNUSED_PARAMETER Class*, SAL_UNUSED_PARAMETER void* )

#define LINK( Inst, Class, Member ) \
    Link( static_cast<Class*>(Inst), &Class::LinkStub##Member )

#define STATIC_LINK( Inst, Class, Member ) LINK(Inst, Class, Member)

#define IMPL_LINK( Class, Method, ArgType, ArgName ) \
    IMPL_STUB( Class, Method, ArgType ) \
    sal_IntPtr Class::Method( ArgType ArgName )

#define IMPL_LINK_NOARG( Class, Method ) \
    IMPL_STUB( Class, Method, void* ) \
    sal_IntPtr Class::Method( SAL_UNUSED_PARAMETER void* )

#define IMPL_LINK_INLINE_START( Class, Method, ArgType, ArgName ) \
    inline sal_IntPtr Class::Method( ArgType ArgName )

#define IMPL_LINK_INLINE_END( Class, Method, ArgType, ArgName ) \
    IMPL_STUB( Class, Method, ArgType )

#define IMPL_LINK_NOARG_INLINE_START( Class, Method ) \
    inline sal_IntPtr Class::Method( SAL_UNUSED_PARAMETER void* )

#define IMPL_LINK_NOARG_INLINE_END( Class, Method ) \
    IMPL_STUB( Class, Method, void* )

#define IMPL_LINK_INLINE( Class, Method, ArgType, ArgName, Body ) \
    sal_IntPtr Class::Method( ArgType ArgName ) \
    Body \
    IMPL_STUB( Class, Method, ArgType )

#define EMPTYARG

class TOOLS_DLLPUBLIC Link
{
    void*       pInst;
    PSTUB       pFunc;

public:
                Link();
                Link( void* pLinkHdl, PSTUB pMemFunc );

    sal_IntPtr      Call( void* pCaller ) const;

    bool            IsSet() const;
    bool            operator !() const;

    bool            operator==( const Link& rLink ) const;
    bool            operator!=( const Link& rLink ) const
                    { return !(Link::operator==( rLink )); }
    bool            operator<( const Link& rLink ) const
                    { return reinterpret_cast<sal_uIntPtr>(rLink.pFunc) < reinterpret_cast<sal_uIntPtr>(pFunc); }
};

inline Link::Link()
{
    pInst = 0;
    pFunc = 0;
}

inline Link::Link( void* pLinkHdl, PSTUB pMemFunc )
{
    pInst = pLinkHdl;
    pFunc = pMemFunc;
}

inline sal_IntPtr Link::Call(void *pCaller) const
{
    return pFunc ? (*pFunc)(pInst, pCaller) : 0;
}

inline bool Link::IsSet() const
{
    if ( pFunc )
        return true;
    else
        return false;
}

inline bool Link::operator !() const
{
    if ( !pFunc )
        return true;
    else
        return false;
}

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before><commit_msg>[TDF] Use right Doxy syntax to display image with link.<commit_after><|endoftext|>


<commit_before>/* $Id: ex18.C,v 1.13 2006-12-11 23:17:54 roystgnr Exp $ */

/* The Next Great Finite Element Library. */
/* Copyright (C) 2003  Benjamin S. Kirk */

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

/* This library is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU */
/* Lesser General Public License for more details. */

/* You should have received a copy of the GNU Lesser General Public */
/* License along with this library; if not, write to the Free Software */
/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

 //
Example 18 - Unsteady Navier-Stokes Equations with DiffSystem

 //
 // This example shows how the transient nonlinear problem from
 // example 13 can be solved using the new (and experimental)
 // DiffSystem class framework

// Basic include files
#include "equation_systems.h"
#include "error_vector.h"
#include "getpot.h"
#include "gmv_io.h"
#include "kelly_error_estimator.h"
#include "mesh.h"
#include "mesh_generation.h"
#include "mesh_refinement.h"
#include "uniform_refinement_estimator.h"

// Some (older) compilers do not offer full stream
// functionality, OStringStream works around this.
#include "o_string_stream.h"

// The systems and solvers we may use
#include "naviersystem.h"
#include "diff_solver.h"
#include "euler_solver.h"
#include "steady_solver.h"

// The main program.
int main (int argc, char** argv)
{
  // Initialize libMesh.
  libMesh::init (argc, argv);
  {
    // Parse the input file
    GetPot infile("ex18.in");

    // Read in parameters from the input file
    const Real global_tolerance          = infile("global_tolerance", 0.);
    const unsigned int nelem_target      = infile("n_elements", 400);
    const bool transient                 = infile("transient", true);
    const Real deltat                    = infile("deltat", 0.005);
    unsigned int n_timesteps             = infile("n_timesteps", 20);
    const unsigned int write_interval    = infile("write_interval", 5);
    const unsigned int coarsegridsize    = infile("coarsegridsize", 1);
    const unsigned int coarserefinements = infile("coarserefinements", 0);
    const unsigned int max_adaptivesteps = infile("max_adaptivesteps", 10);
    const unsigned int dim               = infile("dimension", 2);

    assert (dim == 2 || dim == 3);
    // Create a n-dimensional mesh.
    Mesh mesh (dim);

    // And an object to refine it
    MeshRefinement mesh_refinement(mesh);
    mesh_refinement.coarsen_by_parents() = true;
    mesh_refinement.absolute_global_tolerance() = global_tolerance;
    mesh_refinement.nelem_target() = nelem_target;
    mesh_refinement.refine_fraction() = 0.3;
    mesh_refinement.coarsen_fraction() = 0.3;
    mesh_refinement.coarsen_threshold() = 0.1;

    // Use the MeshTools::Generation mesh generator to create a uniform
    // grid on the square [-1,1]^D.  We instruct the mesh generator
    // to build a mesh of 8x8 \p Quad9 elements in 2D, or \p Hex27
    // elements in 3D.  Building these higher-order elements allows
    // us to use higher-order approximation, as in example 3.
    if (dim == 2)
      MeshTools::Generation::build_square (mesh,
                                           coarsegridsize,
                                           coarsegridsize,
                                           0., 1.,
                                           0., 1.,
                                           QUAD9);
    else if (dim == 3)
      MeshTools::Generation::build_cube (mesh,
                                         coarsegridsize,
                                         coarsegridsize,
                                         coarsegridsize,
                                         0., 1.,
                                         0., 1.,
                                         0., 1.,
                                         HEX27);

    mesh_refinement.uniformly_refine(coarserefinements);

    // Print information about the mesh to the screen.
    mesh.print_info();

    // Create an equation systems object.
    EquationSystems equation_systems (mesh);

    // Declare the system "Navier-Stokes" and its variables.
    NavierSystem & system =
      equation_systems.add_system<NavierSystem> ("Navier-Stokes");

    // Solve this as a time-dependent or steady system
    if (transient)
      system.time_solver =
        AutoPtr<TimeSolver>(new EulerSolver(system));
    else
      {
        system.time_solver =
          AutoPtr<TimeSolver>(new SteadySolver(system));
        assert(n_timesteps == 1);
      }

    // Initialize the system
    equation_systems.init ();

    // Set the time stepping options
    system.deltat = deltat;

    // And the nonlinear solver options
    DiffSolver &solver = *system.time_solver->diff_solver;
    solver.quiet = infile("solver_quiet", true);
    solver.max_nonlinear_iterations =
      infile("max_nonlinear_iterations", 15);
    solver.relative_step_tolerance =
      infile("relative_step_tolerance", 1.e-3);
    solver.relative_residual_tolerance =
      infile("relative_residual_tolerance", 0);

    // And the linear solver options
    solver.max_linear_iterations =
      infile("max_linear_iterations", 50000);
    solver.initial_linear_tolerance =
      infile("initial_linear_tolerance", 1.e-3);

    // Print information about the system to the screen.
    equation_systems.print_info();

    // Now we begin the timestep loop to compute the time-accurate
    // solution of the equations.
    for (unsigned int t_step=0; t_step != n_timesteps; ++t_step)
      {
        // A pretty update message
        std::cout << " Solving time step " << t_step << ", time = "
                  << system.time << std::endl;

        // Adaptively solve the timestep
        unsigned int a_step = 0;
        for (; a_step != max_adaptivesteps; ++a_step)
          {
            system.solve();

            ErrorVector error;

            AutoPtr<ErrorEstimator> error_estimator;

            // To solve to a tolerance in this problem we
            // need a better estimator than Kelly
            if (global_tolerance != 0.)
              {
                // We can't adapt to both a tolerance and a mesh
                // size at once
                assert (nelem_target == 0);

                UniformRefinementEstimator *u =
                  new UniformRefinementEstimator;

                // The lid-driven cavity problem isn't in H1, so
                // lets estimate H0 (i.e. L2) error
                u->sobolev_order() = 0;

                error_estimator.reset(u);
              }
            else
              {
                // If we aren't adapting to a tolerance we need a
                // target mesh size
                assert (nelem_target > 0);

                // Kelly is a lousy estimator to use for a problem
                // not in H1 - if we were doing more than a few
                // timesteps we'd need to turn off or limit the
                // maximum level of our adaptivity eventually
                error_estimator.reset(new KellyErrorEstimator);
              }

            // Calculate error based on u and v but not p
            error_estimator->component_scale.push_back(1.0); // u
            error_estimator->component_scale.push_back(1.0); // v
            if (dim == 3)
              error_estimator->component_scale.push_back(1.0); // w
            error_estimator->component_scale.push_back(0.0); // p

            error_estimator->estimate_error(system, error);

            // Print out status at each adaptive step.
            Real global_error = error.l2_norm();
            std::cout << "adaptive step " << a_step << ": ";
            if (global_tolerance != 0.)
              std::cout << "global_error = " << global_error
                        << " with ";
            std::cout << mesh.n_active_elem()
                      << " active elements and "
                      << equation_systems.n_active_dofs()
                      << " active dofs." << std::endl;
            if (global_tolerance != 0.)
              std::cout << "worst element error = " << error.maximum()
                        << ", mean = " << error.mean() << std::endl;

            if (global_tolerance != 0.)
              {
                // If we've reached our desired tolerance, we
                // don't need any more adaptive steps
                if (global_error < global_tolerance)
                  break;
                mesh_refinement.flag_elements_by_error_tolerance(error);
              }
            else
              {
                // If flag_elements_by_nelem_target returns true, this
                // should be our last adaptive step.
                if (mesh_refinement.flag_elements_by_nelem_target(error))
                  {
                    mesh_refinement.refine_and_coarsen_elements();
                    equation_systems.reinit();
                    break;
                  }
              }

            // Carry out the adaptive mesh refinement/coarsening
            mesh_refinement.refine_and_coarsen_elements();
            equation_systems.reinit();
          }
        // Do one last solve if necessary
        if (a_step == max_adaptivesteps)
          {
            system.solve();
          }

        // Advance to the next timestep in a transient problem
        system.time_solver->advance_timestep();

        // Write out this timestep if we're requested to
        if ((t_step+1)%write_interval == 0)
          {
            OStringStream file_name;

            // We write the file name in the gmv auto-read format.
            file_name << "out.gmv.";
            OSSRealzeroright(file_name,3,0, t_step + 1);

            GMVIO(mesh).write_equation_systems (file_name.str(),
                                                equation_systems);
          }
      }
  }

  // All done.
  return libMesh::close ();
}
<commit_msg>time_solver->diff_solver() is now a function returning an AutoPtr.<commit_after>/* $Id: ex18.C,v 1.14 2007-02-27 16:02:58 jwpeterson Exp $ */

/* The Next Great Finite Element Library. */
/* Copyright (C) 2003  Benjamin S. Kirk */

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

/* This library is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU */
/* Lesser General Public License for more details. */

/* You should have received a copy of the GNU Lesser General Public */
/* License along with this library; if not, write to the Free Software */
/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

 //
Example 18 - Unsteady Navier-Stokes Equations with DiffSystem

 //
 // This example shows how the transient nonlinear problem from
 // example 13 can be solved using the new (and experimental)
 // DiffSystem class framework

// Basic include files
#include "equation_systems.h"
#include "error_vector.h"
#include "getpot.h"
#include "gmv_io.h"
#include "kelly_error_estimator.h"
#include "mesh.h"
#include "mesh_generation.h"
#include "mesh_refinement.h"
#include "uniform_refinement_estimator.h"

// Some (older) compilers do not offer full stream
// functionality, OStringStream works around this.
#include "o_string_stream.h"

// The systems and solvers we may use
#include "naviersystem.h"
#include "diff_solver.h"
#include "euler_solver.h"
#include "steady_solver.h"

// The main program.
int main (int argc, char** argv)
{
  // Initialize libMesh.
  libMesh::init (argc, argv);
  {
    // Parse the input file
    GetPot infile("ex18.in");

    // Read in parameters from the input file
    const Real global_tolerance          = infile("global_tolerance", 0.);
    const unsigned int nelem_target      = infile("n_elements", 400);
    const bool transient                 = infile("transient", true);
    const Real deltat                    = infile("deltat", 0.005);
    unsigned int n_timesteps             = infile("n_timesteps", 20);
    const unsigned int write_interval    = infile("write_interval", 5);
    const unsigned int coarsegridsize    = infile("coarsegridsize", 1);
    const unsigned int coarserefinements = infile("coarserefinements", 0);
    const unsigned int max_adaptivesteps = infile("max_adaptivesteps", 10);
    const unsigned int dim               = infile("dimension", 2);

    assert (dim == 2 || dim == 3);
    // Create a n-dimensional mesh.
    Mesh mesh (dim);

    // And an object to refine it
    MeshRefinement mesh_refinement(mesh);
    mesh_refinement.coarsen_by_parents() = true;
    mesh_refinement.absolute_global_tolerance() = global_tolerance;
    mesh_refinement.nelem_target() = nelem_target;
    mesh_refinement.refine_fraction() = 0.3;
    mesh_refinement.coarsen_fraction() = 0.3;
    mesh_refinement.coarsen_threshold() = 0.1;

    // Use the MeshTools::Generation mesh generator to create a uniform
    // grid on the square [-1,1]^D.  We instruct the mesh generator
    // to build a mesh of 8x8 \p Quad9 elements in 2D, or \p Hex27
    // elements in 3D.  Building these higher-order elements allows
    // us to use higher-order approximation, as in example 3.
    if (dim == 2)
      MeshTools::Generation::build_square (mesh,
                                           coarsegridsize,
                                           coarsegridsize,
                                           0., 1.,
                                           0., 1.,
                                           QUAD9);
    else if (dim == 3)
      MeshTools::Generation::build_cube (mesh,
                                         coarsegridsize,
                                         coarsegridsize,
                                         coarsegridsize,
                                         0., 1.,
                                         0., 1.,
                                         0., 1.,
                                         HEX27);

    mesh_refinement.uniformly_refine(coarserefinements);

    // Print information about the mesh to the screen.
    mesh.print_info();

    // Create an equation systems object.
    EquationSystems equation_systems (mesh);

    // Declare the system "Navier-Stokes" and its variables.
    NavierSystem & system =
      equation_systems.add_system<NavierSystem> ("Navier-Stokes");

    // Solve this as a time-dependent or steady system
    if (transient)
      system.time_solver =
        AutoPtr<TimeSolver>(new EulerSolver(system));
    else
      {
        system.time_solver =
          AutoPtr<TimeSolver>(new SteadySolver(system));
        assert(n_timesteps == 1);
      }

    // Initialize the system
    equation_systems.init ();

    // Set the time stepping options
    system.deltat = deltat;

    // And the nonlinear solver options
    DiffSolver &solver = *(system.time_solver->diff_solver().get());
    solver.quiet = infile("solver_quiet", true);
    solver.max_nonlinear_iterations =
      infile("max_nonlinear_iterations", 15);
    solver.relative_step_tolerance =
      infile("relative_step_tolerance", 1.e-3);
    solver.relative_residual_tolerance =
      infile("relative_residual_tolerance", 0);

    // And the linear solver options
    solver.max_linear_iterations =
      infile("max_linear_iterations", 50000);
    solver.initial_linear_tolerance =
      infile("initial_linear_tolerance", 1.e-3);

    // Print information about the system to the screen.
    equation_systems.print_info();

    // Now we begin the timestep loop to compute the time-accurate
    // solution of the equations.
    for (unsigned int t_step=0; t_step != n_timesteps; ++t_step)
      {
        // A pretty update message
        std::cout << " Solving time step " << t_step << ", time = "
                  << system.time << std::endl;

        // Adaptively solve the timestep
        unsigned int a_step = 0;
        for (; a_step != max_adaptivesteps; ++a_step)
          {
            system.solve();

            ErrorVector error;

            AutoPtr<ErrorEstimator> error_estimator;

            // To solve to a tolerance in this problem we
            // need a better estimator than Kelly
            if (global_tolerance != 0.)
              {
                // We can't adapt to both a tolerance and a mesh
                // size at once
                assert (nelem_target == 0);

                UniformRefinementEstimator *u =
                  new UniformRefinementEstimator;

                // The lid-driven cavity problem isn't in H1, so
                // lets estimate H0 (i.e. L2) error
                u->sobolev_order() = 0;

                error_estimator.reset(u);
              }
            else
              {
                // If we aren't adapting to a tolerance we need a
                // target mesh size
                assert (nelem_target > 0);

                // Kelly is a lousy estimator to use for a problem
                // not in H1 - if we were doing more than a few
                // timesteps we'd need to turn off or limit the
                // maximum level of our adaptivity eventually
                error_estimator.reset(new KellyErrorEstimator);
              }

            // Calculate error based on u and v but not p
            error_estimator->component_scale.push_back(1.0); // u
            error_estimator->component_scale.push_back(1.0); // v
            if (dim == 3)
              error_estimator->component_scale.push_back(1.0); // w
            error_estimator->component_scale.push_back(0.0); // p

            error_estimator->estimate_error(system, error);

            // Print out status at each adaptive step.
            Real global_error = error.l2_norm();
            std::cout << "adaptive step " << a_step << ": ";
            if (global_tolerance != 0.)
              std::cout << "global_error = " << global_error
                        << " with ";
            std::cout << mesh.n_active_elem()
                      << " active elements and "
                      << equation_systems.n_active_dofs()
                      << " active dofs." << std::endl;
            if (global_tolerance != 0.)
              std::cout << "worst element error = " << error.maximum()
                        << ", mean = " << error.mean() << std::endl;

            if (global_tolerance != 0.)
              {
                // If we've reached our desired tolerance, we
                // don't need any more adaptive steps
                if (global_error < global_tolerance)
                  break;
                mesh_refinement.flag_elements_by_error_tolerance(error);
              }
            else
              {
                // If flag_elements_by_nelem_target returns true, this
                // should be our last adaptive step.
                if (mesh_refinement.flag_elements_by_nelem_target(error))
                  {
                    mesh_refinement.refine_and_coarsen_elements();
                    equation_systems.reinit();
                    break;
                  }
              }

            // Carry out the adaptive mesh refinement/coarsening
            mesh_refinement.refine_and_coarsen_elements();
            equation_systems.reinit();
          }
        // Do one last solve if necessary
        if (a_step == max_adaptivesteps)
          {
            system.solve();
          }

        // Advance to the next timestep in a transient problem
        system.time_solver->advance_timestep();

        // Write out this timestep if we're requested to
        if ((t_step+1)%write_interval == 0)
          {
            OStringStream file_name;

            // We write the file name in the gmv auto-read format.
            file_name << "out.gmv.";
            OSSRealzeroright(file_name,3,0, t_step + 1);

            GMVIO(mesh).write_equation_systems (file_name.str(),
                                                equation_systems);
          }
      }
  }

  // All done.
  return libMesh::close ();
}
<|endoftext|>


<commit_before>#pragma once

/** @file GaussLegendre.hpp
  * @brief
  * @author C.D. Clark III
  * @date 08/04/17
  */

#include<array>

namespace _2D {
namespace GQ {

template<typename T, size_t Order>
class GaussLegendreQuadrature
{
  public:
    _1D::GQ::GaussLegendreQuadrature<T,Order> _1dInt;

    GaussLegendreQuadrature() = default;

    // This version will integrate a callable between four points
    template<typename F, typename X, typename Y>
    T operator()( F f, X a, X b, Y c, Y d ) const;

  protected:
};

template<typename T, size_t Order>
template<typename F, typename X, typename Y>
T GaussLegendreQuadrature<T,Order>::operator()(F f, X a, X b, Y c, Y d) const
{
  // A 2D integral I = \int \int f(x,y) dx dy
  // can be written as two 1D integrals
  //
  // g(x) = \int f(x,y) dy
  // I = \int g(x) dx
  //
  // first, integrate over y at each of the required points (i.e. create g(x_i))

  X apb = (b + a)/2;
  X amb = (b - a)/2;
  std::array<T, Order> sums;

  #pragma parallel for
  for(size_t i = 0; i < Order; i++)
    sums[i] = _1dInt( [&](Y y){ return f(apb + amb*_1dInt.getX()[i], y); }, c, d );

  // now integrate over x
  T sum = 0;
  for(size_t i = 0; i < Order; i++)
    sum += _1dInt.getW()[i]*sums[i];
  sum *= amb;

  return sum;
}

}

}
<commit_msg>feat: added missing header to 2D Gaussian quadrature.<commit_after>#pragma once

/** @file GaussLegendre.hpp
  * @brief
  * @author C.D. Clark III
  * @date 08/04/17
  */

#include<array>
#include "../../_1D/GaussianQuadratures/GaussLegendre.hpp"

namespace _2D {
namespace GQ {

template<typename T, size_t Order>
class GaussLegendreQuadrature
{
  public:
    _1D::GQ::GaussLegendreQuadrature<T,Order> _1dInt;

    GaussLegendreQuadrature() = default;

    // This version will integrate a callable between four points
    template<typename F, typename X, typename Y>
    T operator()( F f, X a, X b, Y c, Y d ) const;

  protected:
};

template<typename T, size_t Order>
template<typename F, typename X, typename Y>
T GaussLegendreQuadrature<T,Order>::operator()(F f, X a, X b, Y c, Y d) const
{
  // A 2D integral I = \int \int f(x,y) dx dy
  // can be written as two 1D integrals
  //
  // g(x) = \int f(x,y) dy
  // I = \int g(x) dx
  //
  // first, integrate over y at each of the required points (i.e. create g(x_i))

  X apb = (b + a)/2;
  X amb = (b - a)/2;
  std::array<T, Order> sums;

  #pragma parallel for
  for(size_t i = 0; i < Order; i++)
    sums[i] = _1dInt( [&](Y y){ return f(apb + amb*_1dInt.getX()[i], y); }, c, d );

  // now integrate over x
  T sum = 0;
  for(size_t i = 0; i < Order; i++)
    sum += _1dInt.getW()[i]*sums[i];
  sum *= amb;

  return sum;
}

}

}
<|endoftext|>


<commit_before>/***********************************************************************
    filename:   TreeView.cpp
    created:    Fri Jun 06 2014
    author:     Timotei Dolean <timotei21@gmail.com>

    purpose:    Implementation of the base class for all item model-based views.
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2014 Paul D Turner & The CEGUI Development Team
 *
 *   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 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.
***************************************************************************/
#include "CEGUI/views/TreeView.h"
#include "CEGUI/CoordConverter.h"

namespace CEGUI
{
//----------------------------------------------------------------------------//
TreeViewWindowRenderer::TreeViewWindowRenderer(const String& type) :
    ItemViewWindowRenderer(type)
{
}

//----------------------------------------------------------------------------//
const String TreeView::EventNamespace("TreeView");
const String TreeView::WidgetTypeName("CEGUI/TreeView");

//----------------------------------------------------------------------------//
TreeViewItemRenderingState::TreeViewItemRenderingState() :
    d_totalChildCount(0),
    d_size(0, 0),
    d_isSelected(false),
    d_childId(0),
    d_subtreeIsExpanded(false)
{
}

//----------------------------------------------------------------------------//
TreeView::TreeView(const String& type, const String& name) :
    ItemView(type, name)
{
}

//----------------------------------------------------------------------------//
TreeView::~TreeView()
{
}

//----------------------------------------------------------------------------//
const TreeViewItemRenderingState& TreeView::getRootItemState() const
{
    return d_rootItemState;
}

//----------------------------------------------------------------------------//
void TreeView::prepareForRender()
{
    ItemView::prepareForRender();
    if (d_itemModel == 0 || !isDirty())
        return;

    ModelIndex root_index = d_itemModel->getRootIndex();
    d_renderedMaxWidth = 0;
    d_renderedTotalHeight = 0;

    d_rootItemState = TreeViewItemRenderingState();
    d_rootItemState.d_subtreeIsExpanded = true;

    computeRenderedChildrenForItem(d_rootItemState, root_index,
        d_renderedMaxWidth, d_renderedTotalHeight);

    updateScrollbars();
    setIsDirty(false);
}

//----------------------------------------------------------------------------//
bool TreeView::handleSelection(const Vector2f& position, bool should_select,
    bool is_cumulative, bool is_range)
{
    return handleSelection(
        indexAtWithAction(position, &TreeView::handleSelectionAction),
        should_select, is_cumulative, is_range);
}

//----------------------------------------------------------------------------//
bool TreeView::handleSelection(const ModelIndex& index, bool should_select,
    bool is_cumulative, bool is_range)
{
    return ItemView::handleSelection(index, should_select, is_cumulative, is_range);
}

//----------------------------------------------------------------------------//
TreeViewItemRenderingState TreeView::computeRenderingStateForIndex(
    const ModelIndex& index, float& rendered_max_width,
    float& rendered_total_height)
{
    if (d_itemModel == 0)
        return TreeViewItemRenderingState();

    TreeViewItemRenderingState state;
    String text = d_itemModel->getData(index);
    RenderedString rendered_string = getRenderedStringParser().parse(
        text, getFont(), &d_textColourRect);
    state.d_string = rendered_string;
    state.d_size = Sizef(
        rendered_string.getHorizontalExtent(this),
        rendered_string.getVerticalExtent(this));

    rendered_max_width = ceguimax(rendered_max_width, state.d_size.d_width);
    rendered_total_height += state.d_size.d_height;

    state.d_isSelected = isIndexSelected(index);

    computeRenderedChildrenForItem(state, index, rendered_max_width,
        rendered_total_height);

    return state;
}

//----------------------------------------------------------------------------//
ModelIndex TreeView::indexAt(const Vector2f& position)
{
    return indexAtWithAction(position, &TreeView::noopAction);
}

//----------------------------------------------------------------------------//
CEGUI::ModelIndex TreeView::indexAtWithAction(const Vector2f& position,
    TreeViewItemAction action)
{
    if (d_itemModel == 0)
        return ModelIndex();

    //TODO: add prepareForLayout() as a cheaper operation alternative?
    prepareForRender();

    Vector2f window_position = CoordConverter::screenToWindow(*this, position);
    Rectf render_area(getViewRenderer()->getViewRenderArea());
    if (!render_area.isPointInRect(window_position))
        return ModelIndex();

    float cur_height = render_area.d_min.d_y - getVertScrollbar()->getScrollPosition();
    bool handled = false;
    return indexAtRecursive(d_rootItemState, cur_height, window_position,
        handled, action);
}

//----------------------------------------------------------------------------//
ModelIndex TreeView::indexAtRecursive(TreeViewItemRenderingState& item,
    float& cur_height, const Vector2f& window_position, bool& handled,
    TreeViewItemAction action)
{
    float next_height = cur_height + item.d_size.d_height;

    if (window_position.d_y >= cur_height &&
        window_position.d_y <= next_height)
    {
        handled = true;

        float subtree_expander_width = getViewRenderer()->getSubtreeExpanderSize().d_width;
        if (window_position.d_x >= 0 && window_position.d_x <= subtree_expander_width)
        {
            (this->*action)(item, true);
            return ModelIndex();
        }

        (this->*action)(item, false);
        return ModelIndex(d_itemModel->makeIndex(item.d_childId, item.d_parentIndex));
    }

    cur_height = next_height;

    for (size_t i = 0; i < item.d_renderedChildren.size(); ++i)
    {
        ModelIndex index = indexAtRecursive(item.d_renderedChildren.at(i),
            cur_height, window_position, handled, action);
        if (handled)
            return index;
    }

    return ModelIndex();
}

//----------------------------------------------------------------------------//
TreeViewWindowRenderer* TreeView::getViewRenderer()
{
    return static_cast<TreeViewWindowRenderer*>(ItemView::getViewRenderer());
}

//----------------------------------------------------------------------------//
void TreeView::toggleSubtree(TreeViewItemRenderingState& item)
{
    item.d_subtreeIsExpanded = !item.d_subtreeIsExpanded;
    std::cout << "Toggled. " << item.d_text << std::endl;

    if (item.d_subtreeIsExpanded)
    {
        computeRenderedChildrenForItem(item,
            d_itemModel->makeIndex(item.d_childId, item.d_parentIndex),
            d_renderedMaxWidth, d_renderedTotalHeight);
    }
    else
    {
        clearItemRenderedChildren(item, d_renderedTotalHeight);
    }

    updateScrollbars();
    invalidate(false);
}

//----------------------------------------------------------------------------//
void TreeView::computeRenderedChildrenForItem(TreeViewItemRenderingState &item,
    const ModelIndex& index, float& rendered_max_width, float& rendered_total_height)
{
    if (d_itemModel == 0)
        return;

    size_t child_count = d_itemModel->getChildCount(index);
    item.d_totalChildCount = child_count;

    if (!item.d_subtreeIsExpanded)
        return;

    for (size_t child = 0; child < child_count; ++child)
    {
        ModelIndex child_index = d_itemModel->makeIndex(child, index);
        TreeViewItemRenderingState child_state =
            computeRenderingStateForIndex(child_index, rendered_max_width,
                rendered_total_height);
        child_state.d_parentIndex = index;
        child_state.d_childId = child;
        item.d_renderedChildren.push_back(child_state);
    }
}

//----------------------------------------------------------------------------//
void TreeView::clearItemRenderedChildren(TreeViewItemRenderingState& item,
    float& renderedTotalHeight)
{
    std::vector<TreeViewItemRenderingState>::iterator itor =
        item.d_renderedChildren.begin();

    while (itor != item.d_renderedChildren.end())
    {
        clearItemRenderedChildren(*itor, renderedTotalHeight);

        d_renderedTotalHeight -= item.d_size.d_height;
        itor = item.d_renderedChildren.erase(itor);
    }
}

//----------------------------------------------------------------------------//
void TreeView::handleSelectionAction(TreeViewItemRenderingState& item, bool toggles_expander)
{
    if (!toggles_expander)
        return;

    toggleSubtree(item);
}
}
<commit_msg>Remove debug leftover line :D<commit_after>/***********************************************************************
    filename:   TreeView.cpp
    created:    Fri Jun 06 2014
    author:     Timotei Dolean <timotei21@gmail.com>

    purpose:    Implementation of the base class for all item model-based views.
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2014 Paul D Turner & The CEGUI Development Team
 *
 *   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 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.
***************************************************************************/
#include "CEGUI/views/TreeView.h"
#include "CEGUI/CoordConverter.h"

namespace CEGUI
{
//----------------------------------------------------------------------------//
TreeViewWindowRenderer::TreeViewWindowRenderer(const String& type) :
    ItemViewWindowRenderer(type)
{
}

//----------------------------------------------------------------------------//
const String TreeView::EventNamespace("TreeView");
const String TreeView::WidgetTypeName("CEGUI/TreeView");

//----------------------------------------------------------------------------//
TreeViewItemRenderingState::TreeViewItemRenderingState() :
    d_totalChildCount(0),
    d_size(0, 0),
    d_isSelected(false),
    d_childId(0),
    d_subtreeIsExpanded(false)
{
}

//----------------------------------------------------------------------------//
TreeView::TreeView(const String& type, const String& name) :
    ItemView(type, name)
{
}

//----------------------------------------------------------------------------//
TreeView::~TreeView()
{
}

//----------------------------------------------------------------------------//
const TreeViewItemRenderingState& TreeView::getRootItemState() const
{
    return d_rootItemState;
}

//----------------------------------------------------------------------------//
void TreeView::prepareForRender()
{
    ItemView::prepareForRender();
    if (d_itemModel == 0 || !isDirty())
        return;

    ModelIndex root_index = d_itemModel->getRootIndex();
    d_renderedMaxWidth = 0;
    d_renderedTotalHeight = 0;

    d_rootItemState = TreeViewItemRenderingState();
    d_rootItemState.d_subtreeIsExpanded = true;

    computeRenderedChildrenForItem(d_rootItemState, root_index,
        d_renderedMaxWidth, d_renderedTotalHeight);

    updateScrollbars();
    setIsDirty(false);
}

//----------------------------------------------------------------------------//
bool TreeView::handleSelection(const Vector2f& position, bool should_select,
    bool is_cumulative, bool is_range)
{
    return handleSelection(
        indexAtWithAction(position, &TreeView::handleSelectionAction),
        should_select, is_cumulative, is_range);
}

//----------------------------------------------------------------------------//
bool TreeView::handleSelection(const ModelIndex& index, bool should_select,
    bool is_cumulative, bool is_range)
{
    return ItemView::handleSelection(index, should_select, is_cumulative, is_range);
}

//----------------------------------------------------------------------------//
TreeViewItemRenderingState TreeView::computeRenderingStateForIndex(
    const ModelIndex& index, float& rendered_max_width,
    float& rendered_total_height)
{
    if (d_itemModel == 0)
        return TreeViewItemRenderingState();

    TreeViewItemRenderingState state;
    String text = d_itemModel->getData(index);
    RenderedString rendered_string = getRenderedStringParser().parse(
        text, getFont(), &d_textColourRect);
    state.d_string = rendered_string;
    state.d_size = Sizef(
        rendered_string.getHorizontalExtent(this),
        rendered_string.getVerticalExtent(this));

    rendered_max_width = ceguimax(rendered_max_width, state.d_size.d_width);
    rendered_total_height += state.d_size.d_height;

    state.d_isSelected = isIndexSelected(index);

    computeRenderedChildrenForItem(state, index, rendered_max_width,
        rendered_total_height);

    return state;
}

//----------------------------------------------------------------------------//
ModelIndex TreeView::indexAt(const Vector2f& position)
{
    return indexAtWithAction(position, &TreeView::noopAction);
}

//----------------------------------------------------------------------------//
CEGUI::ModelIndex TreeView::indexAtWithAction(const Vector2f& position,
    TreeViewItemAction action)
{
    if (d_itemModel == 0)
        return ModelIndex();

    //TODO: add prepareForLayout() as a cheaper operation alternative?
    prepareForRender();

    Vector2f window_position = CoordConverter::screenToWindow(*this, position);
    Rectf render_area(getViewRenderer()->getViewRenderArea());
    if (!render_area.isPointInRect(window_position))
        return ModelIndex();

    float cur_height = render_area.d_min.d_y - getVertScrollbar()->getScrollPosition();
    bool handled = false;
    return indexAtRecursive(d_rootItemState, cur_height, window_position,
        handled, action);
}

//----------------------------------------------------------------------------//
ModelIndex TreeView::indexAtRecursive(TreeViewItemRenderingState& item,
    float& cur_height, const Vector2f& window_position, bool& handled,
    TreeViewItemAction action)
{
    float next_height = cur_height + item.d_size.d_height;

    if (window_position.d_y >= cur_height &&
        window_position.d_y <= next_height)
    {
        handled = true;

        float subtree_expander_width = getViewRenderer()->getSubtreeExpanderSize().d_width;
        if (window_position.d_x >= 0 && window_position.d_x <= subtree_expander_width)
        {
            (this->*action)(item, true);
            return ModelIndex();
        }

        (this->*action)(item, false);
        return ModelIndex(d_itemModel->makeIndex(item.d_childId, item.d_parentIndex));
    }

    cur_height = next_height;

    for (size_t i = 0; i < item.d_renderedChildren.size(); ++i)
    {
        ModelIndex index = indexAtRecursive(item.d_renderedChildren.at(i),
            cur_height, window_position, handled, action);
        if (handled)
            return index;
    }

    return ModelIndex();
}

//----------------------------------------------------------------------------//
TreeViewWindowRenderer* TreeView::getViewRenderer()
{
    return static_cast<TreeViewWindowRenderer*>(ItemView::getViewRenderer());
}

//----------------------------------------------------------------------------//
void TreeView::toggleSubtree(TreeViewItemRenderingState& item)
{
    item.d_subtreeIsExpanded = !item.d_subtreeIsExpanded;

    if (item.d_subtreeIsExpanded)
    {
        computeRenderedChildrenForItem(item,
            d_itemModel->makeIndex(item.d_childId, item.d_parentIndex),
            d_renderedMaxWidth, d_renderedTotalHeight);
    }
    else
    {
        clearItemRenderedChildren(item, d_renderedTotalHeight);
    }

    updateScrollbars();
    invalidate(false);
}

//----------------------------------------------------------------------------//
void TreeView::computeRenderedChildrenForItem(TreeViewItemRenderingState &item,
    const ModelIndex& index, float& rendered_max_width, float& rendered_total_height)
{
    if (d_itemModel == 0)
        return;

    size_t child_count = d_itemModel->getChildCount(index);
    item.d_totalChildCount = child_count;

    if (!item.d_subtreeIsExpanded)
        return;

    for (size_t child = 0; child < child_count; ++child)
    {
        ModelIndex child_index = d_itemModel->makeIndex(child, index);
        TreeViewItemRenderingState child_state =
            computeRenderingStateForIndex(child_index, rendered_max_width,
                rendered_total_height);
        child_state.d_parentIndex = index;
        child_state.d_childId = child;
        item.d_renderedChildren.push_back(child_state);
    }
}

//----------------------------------------------------------------------------//
void TreeView::clearItemRenderedChildren(TreeViewItemRenderingState& item,
    float& renderedTotalHeight)
{
    std::vector<TreeViewItemRenderingState>::iterator itor =
        item.d_renderedChildren.begin();

    while (itor != item.d_renderedChildren.end())
    {
        clearItemRenderedChildren(*itor, renderedTotalHeight);

        d_renderedTotalHeight -= item.d_size.d_height;
        itor = item.d_renderedChildren.erase(itor);
    }
}

//----------------------------------------------------------------------------//
void TreeView::handleSelectionAction(TreeViewItemRenderingState& item, bool toggles_expander)
{
    if (!toggles_expander)
        return;

    toggleSubtree(item);
}
}
<|endoftext|>


<commit_before><commit_msg>[Oops] Accidentally added file<commit_after><|endoftext|>