diff --git a/branches/master/singlehtml/_downloads/15487131c52c6487f27ab78c60499d37/1d_stencil_1.cpp b/branches/master/singlehtml/_downloads/15487131c52c6487f27ab78c60499d37/1d_stencil_1.cpp
new file mode 100644
index 00000000000..0837a596732
--- /dev/null
+++ b/branches/master/singlehtml/_downloads/15487131c52c6487f27ab78c60499d37/1d_stencil_1.cpp
@@ -0,0 +1,139 @@
+// Copyright (c) 2014 Hartmut Kaiser
+// Copyright (c) 2014 Patricia Grubel
+//
+// SPDX-License-Identifier: BSL-1.0
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// This is the first in a series of examples demonstrating the development of a
+// fully distributed solver for a simple 1D heat distribution problem.
+//
+// This example provides a serial base line implementation. No parallelization
+// is performed.
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include "print_time_results.hpp"
+
+///////////////////////////////////////////////////////////////////////////////
+// Command-line variables
+bool header = true; // print csv heading
+double k = 0.5; // heat transfer coefficient
+double dt = 1.; // time step
+double dx = 1.; // grid spacing
+
+///////////////////////////////////////////////////////////////////////////////
+//[stepper_1
+struct stepper
+{
+ // Our partition type
+ typedef double partition;
+
+ // Our data for one time step
+ typedef std::vector space;
+
+ // Our operator
+ static double heat(double left, double middle, double right)
+ {
+ return middle + (k * dt / (dx * dx)) * (left - 2 * middle + right);
+ }
+
+ // do all the work on 'nx' data points for 'nt' time steps
+ space do_work(std::size_t nx, std::size_t nt)
+ {
+ // U[t][i] is the state of position i at time t.
+ std::vector U(2);
+ for (space& s : U)
+ s.resize(nx);
+
+ // Initial conditions: f(0, i) = i
+ for (std::size_t i = 0; i != nx; ++i)
+ U[0][i] = double(i);
+
+ // Actual time step loop
+ for (std::size_t t = 0; t != nt; ++t)
+ {
+ space const& current = U[t % 2];
+ space& next = U[(t + 1) % 2];
+
+ next[0] = heat(current[nx - 1], current[0], current[1]);
+
+ for (std::size_t i = 1; i != nx - 1; ++i)
+ next[i] = heat(current[i - 1], current[i], current[i + 1]);
+
+ next[nx - 1] = heat(current[nx - 2], current[nx - 1], current[0]);
+ }
+
+ // Return the solution at time-step 'nt'.
+ return U[nt % 2];
+ }
+};
+//]
+///////////////////////////////////////////////////////////////////////////////
+int hpx_main(hpx::program_options::variables_map& vm)
+{
+ std::uint64_t nx =
+ vm["nx"].as(); // Number of grid points.
+ std::uint64_t nt = vm["nt"].as(); // Number of steps.
+
+ if (vm.count("no-header"))
+ header = false;
+
+ // Create the stepper object
+ stepper step;
+
+ // Measure execution time.
+ std::uint64_t t = hpx::chrono::high_resolution_clock::now();
+
+ // Execute nt time steps on nx grid points.
+ stepper::space solution = step.do_work(nx, nt);
+
+ // Print the final solution
+ if (vm.count("results"))
+ {
+ for (std::size_t i = 0; i != nx; ++i)
+ std::cout << "U[" << i << "] = " << solution[i] << std::endl;
+ }
+
+ std::uint64_t elapsed = hpx::chrono::high_resolution_clock::now() - t;
+
+ std::uint64_t const os_thread_count = hpx::get_os_thread_count();
+ print_time_results(os_thread_count, elapsed, nx, nt, header);
+
+ return hpx::local::finalize();
+}
+
+int main(int argc, char* argv[])
+{
+ namespace po = hpx::program_options;
+
+ // clang-format off
+ po::options_description desc_commandline;
+ desc_commandline.add_options()
+ ("results", "print generated results (default: false)")
+ ("nx", po::value()->default_value(100),
+ "Local x dimension")
+ ("nt", po::value()->default_value(45),
+ "Number of time steps")
+ ("k", po::value(&k)->default_value(0.5),
+ "Heat transfer coefficient (default: 0.5)")
+ ("dt", po::value(&dt)->default_value(1.0),
+ "Timestep unit (default: 1.0[s])")
+ ("dx", po::value(&dx)->default_value(1.0),
+ "Local x dimension")
+ ( "no-header", "do not print out the csv header row")
+ ;
+ // clang-format on
+
+ // Initialize and run HPX
+ hpx::local::init_params init_args;
+ init_args.desc_cmdline = desc_commandline;
+
+ return hpx::local::init(hpx_main, argc, argv, init_args);
+}
diff --git a/branches/master/singlehtml/_downloads/2b583c3b9d65dd88ffc89d3a51ba81d8/interest_calculator.cpp b/branches/master/singlehtml/_downloads/2b583c3b9d65dd88ffc89d3a51ba81d8/interest_calculator.cpp
new file mode 100644
index 00000000000..296176cf6bd
--- /dev/null
+++ b/branches/master/singlehtml/_downloads/2b583c3b9d65dd88ffc89d3a51ba81d8/interest_calculator.cpp
@@ -0,0 +1,122 @@
+/////////////////////////// Interest Calculator ///////////////////////////////
+// Copyright (c) 2012 Adrian Serio
+//
+// SPDX-License-Identifier: BSL-1.0
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// Purpose: Calculates compound interest while using dataflow objects.
+//
+// In this example, you supply the program with the principal [$], the interest
+// rate [%], the length of the compound period [months], and the length of time
+// the money is invested [months]. The program will calculate the new total
+// amount of money you have and the amount of interest made. For example if
+// you have $100, an interest rate of 5%, a compound period of 6 months and
+// you leave your money in that account for 36 months you will end up with
+// $134.01 and will have made $34.01 in interest.
+///////////////////////////////////////////////////////////////////////////////
+
+#include
+#include
+
+#include
+#include
+
+#include
+
+using hpx::program_options::options_description;
+using hpx::program_options::value;
+using hpx::program_options::variables_map;
+
+///////////////////////////////////////////////////////////////////////////////
+//[interest_calc_add_action
+// Calculate interest for one period
+double calc(double principal, double rate)
+{
+ return principal * rate;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Add the amount made to the principal
+double add(double principal, double interest)
+{
+ return principal + interest;
+}
+//]
+
+///////////////////////////////////////////////////////////////////////////////
+//[interest_hpx_main
+int hpx_main(variables_map& vm)
+{
+ {
+ using hpx::dataflow;
+ using hpx::make_ready_future;
+ using hpx::shared_future;
+ using hpx::unwrapping;
+ hpx::id_type here = hpx::find_here();
+
+ double init_principal =
+ vm["principal"].as(); //Initial principal
+ double init_rate = vm["rate"].as(); //Interest rate
+ int cp = vm["cp"].as(); //Length of a compound period
+ int t = vm["time"].as(); //Length of time money is invested
+
+ init_rate /= 100; //Rate is a % and must be converted
+ t /= cp; //Determine how many times to iterate interest calculation:
+ //How many full compound periods can fit in the time invested
+
+ // In non-dataflow terms the implemented algorithm would look like:
+ //
+ // int t = 5; // number of time periods to use
+ // double principal = init_principal;
+ // double rate = init_rate;
+ //
+ // for (int i = 0; i < t; ++i)
+ // {
+ // double interest = calc(principal, rate);
+ // principal = add(principal, interest);
+ // }
+ //
+ // Please note the similarity with the code below!
+
+ shared_future principal = make_ready_future(init_principal);
+ shared_future rate = make_ready_future(init_rate);
+
+ for (int i = 0; i < t; ++i)
+ {
+ shared_future interest =
+ dataflow(unwrapping(calc), principal, rate);
+ principal = dataflow(unwrapping(add), principal, interest);
+ }
+
+ // wait for the dataflow execution graph to be finished calculating our
+ // overall interest
+ double result = principal.get();
+
+ std::cout << "Final amount: " << result << std::endl;
+ std::cout << "Amount made: " << result - init_principal << std::endl;
+ }
+
+ return hpx::finalize();
+}
+//]
+
+///////////////////////////////////////////////////////////////////////////////
+//[interest_main
+int main(int argc, char** argv)
+{
+ options_description cmdline("Usage: " HPX_APPLICATION_STRING " [options]");
+
+ cmdline.add_options()("principal", value()->default_value(1000),
+ "The principal [$]")("rate", value()->default_value(7),
+ "The interest rate [%]")("cp", value()->default_value(12),
+ "The compound period [months]")("time",
+ value()->default_value(12 * 30),
+ "The time money is invested [months]");
+
+ hpx::init_params init_args;
+ init_args.desc_cmdline = cmdline;
+
+ return hpx::init(argc, argv, init_args);
+}
+//]
diff --git a/branches/master/singlehtml/_downloads/3415f7f3f33e09003b63c9bd3b24a11b/1d_stencil_4.cpp b/branches/master/singlehtml/_downloads/3415f7f3f33e09003b63c9bd3b24a11b/1d_stencil_4.cpp
new file mode 100644
index 00000000000..c39fe45e4a4
--- /dev/null
+++ b/branches/master/singlehtml/_downloads/3415f7f3f33e09003b63c9bd3b24a11b/1d_stencil_4.cpp
@@ -0,0 +1,276 @@
+// Copyright (c) 2014-2022 Hartmut Kaiser
+// Copyright (c) 2014 Patricia Grubel
+//
+// SPDX-License-Identifier: BSL-1.0
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// This is the fourth in a series of examples demonstrating the development of
+// a fully distributed solver for a simple 1D heat distribution problem.
+//
+// This example builds on example three. It futurizes the code from that
+// example. Compared to example two this code runs much more efficiently. It
+// allows for changing the amount of work executed in one HPX thread which
+// enables tuning the performance for the optimal grain size of the
+// computation. This example is still fully local but demonstrates nice
+// scalability on SMP machines.
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "print_time_results.hpp"
+
+///////////////////////////////////////////////////////////////////////////////
+// Command-line variables
+bool header = true; // print csv heading
+double k = 0.5; // heat transfer coefficient
+double dt = 1.; // time step
+double dx = 1.; // grid spacing
+
+inline std::size_t idx(std::size_t i, int dir, std::size_t size)
+{
+ if (i == 0 && dir == -1)
+ return size - 1;
+ if (i == size - 1 && dir == +1)
+ return 0;
+
+ HPX_ASSERT((i + dir) < size);
+
+ return i + dir;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Our partition data type
+struct partition_data
+{
+public:
+ explicit partition_data(std::size_t size)
+ : data_(new double[size])
+ , size_(size)
+ {
+ }
+
+ partition_data(std::size_t size, double initial_value)
+ : data_(new double[size])
+ , size_(size)
+ {
+ double base_value = double(initial_value * size);
+ for (std::size_t i = 0; i != size; ++i)
+ data_[i] = base_value + double(i);
+ }
+
+ partition_data(partition_data&& other) noexcept
+ : data_(std::move(other.data_))
+ , size_(other.size_)
+ {
+ }
+
+ double& operator[](std::size_t idx)
+ {
+ return data_[idx];
+ }
+ double operator[](std::size_t idx) const
+ {
+ return data_[idx];
+ }
+
+ std::size_t size() const
+ {
+ return size_;
+ }
+
+private:
+ std::unique_ptr data_;
+ std::size_t size_;
+};
+
+std::ostream& operator<<(std::ostream& os, partition_data const& c)
+{
+ os << "{";
+ for (std::size_t i = 0; i != c.size(); ++i)
+ {
+ if (i != 0)
+ os << ", ";
+ os << c[i];
+ }
+ os << "}";
+ return os;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+struct stepper
+{
+ // Our data for one time step
+ typedef hpx::shared_future partition;
+ typedef std::vector space;
+
+ // Our operator
+ static double heat(double left, double middle, double right)
+ {
+ return middle + (k * dt / (dx * dx)) * (left - 2 * middle + right);
+ }
+
+ // The partitioned operator, it invokes the heat operator above on all
+ // elements of a partition.
+ static partition_data heat_part(partition_data const& left,
+ partition_data const& middle, partition_data const& right)
+ {
+ std::size_t size = middle.size();
+ partition_data next(size);
+
+ next[0] = heat(left[size - 1], middle[0], middle[1]);
+
+ for (std::size_t i = 1; i != size - 1; ++i)
+ {
+ next[i] = heat(middle[i - 1], middle[i], middle[i + 1]);
+ }
+
+ next[size - 1] = heat(middle[size - 2], middle[size - 1], right[0]);
+
+ return next;
+ }
+
+ // do all the work on 'np' partitions, 'nx' data points each, for 'nt'
+ // time steps, limit depth of dependency tree to 'nd'
+ hpx::future do_work(
+ std::size_t np, std::size_t nx, std::size_t nt, std::uint64_t nd)
+ {
+ using hpx::dataflow;
+ using hpx::unwrapping;
+
+ // U[t][i] is the state of position i at time t.
+ std::vector U(2);
+ for (space& s : U)
+ s.resize(np);
+
+ // Initial conditions: f(0, i) = i
+ auto range = hpx::util::counting_shape(np);
+ using hpx::execution::par;
+ hpx::ranges::for_each(par, range, [&U, nx](std::size_t i) {
+ U[0][i] = hpx::make_ready_future(partition_data(nx, double(i)));
+ });
+
+ // limit depth of dependency tree
+ auto sem = std::make_shared(nd);
+
+ auto Op = unwrapping(&stepper::heat_part);
+
+ // Actual time step loop
+ for (std::size_t t = 0; t != nt; ++t)
+ {
+ space const& current = U[t % 2];
+ space& next = U[(t + 1) % 2];
+
+ for (std::size_t i = 0; i != np; ++i)
+ {
+ next[i] =
+ dataflow(hpx::launch::async, Op, current[idx(i, -1, np)],
+ current[i], current[idx(i, +1, np)]);
+ }
+
+ // every nd time steps, attach additional continuation which will
+ // trigger the semaphore once computation has reached this point
+ if ((t % nd) == 0)
+ {
+ next[0].then([sem, t](partition&&) {
+ // inform semaphore about new lower limit
+ sem->signal(t);
+ });
+ }
+
+ // suspend if the tree has become too deep, the continuation above
+ // will resume this thread once the computation has caught up
+ sem->wait(t);
+ }
+
+ // Return the solution at time-step 'nt'.
+ return hpx::when_all(U[nt % 2]);
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+int hpx_main(hpx::program_options::variables_map& vm)
+{
+ std::uint64_t np = vm["np"].as(); // Number of partitions.
+ std::uint64_t nx =
+ vm["nx"].as(); // Number of grid points.
+ std::uint64_t nt = vm["nt"].as(); // Number of steps.
+ std::uint64_t nd =
+ vm["nd"].as(); // Max depth of dep tree.
+
+ if (vm.count("no-header"))
+ header = false;
+
+ // Create the stepper object
+ stepper step;
+
+ // Measure execution time.
+ std::uint64_t t = hpx::chrono::high_resolution_clock::now();
+
+ // Execute nt time steps on nx grid points and print the final solution.
+ hpx::future result = step.do_work(np, nx, nt, nd);
+
+ stepper::space solution = result.get();
+ hpx::wait_all(solution);
+
+ std::uint64_t elapsed = hpx::chrono::high_resolution_clock::now() - t;
+
+ // Print the final solution
+ if (vm.count("results"))
+ {
+ for (std::size_t i = 0; i != np; ++i)
+ std::cout << "U[" << i << "] = " << solution[i].get() << std::endl;
+ }
+
+ std::uint64_t const os_thread_count = hpx::get_os_thread_count();
+ print_time_results(os_thread_count, elapsed, nx, np, nt, header);
+
+ return hpx::local::finalize();
+}
+
+int main(int argc, char* argv[])
+{
+ using namespace hpx::program_options;
+
+ // Configure application-specific options.
+ options_description desc_commandline;
+
+ // clang-format off
+ desc_commandline.add_options()
+ ("results", "print generated results (default: false)")
+ ("nx", value()->default_value(10),
+ "Local x dimension (of each partition)")
+ ("nt", value()->default_value(45),
+ "Number of time steps")
+ ("nd", value()->default_value(10),
+ "Number of time steps to allow the dependency tree to grow to")
+ ("np", value()->default_value(10),
+ "Number of partitions")
+ ("k", value(&k)->default_value(0.5),
+ "Heat transfer coefficient (default: 0.5)")
+ ("dt", value(&dt)->default_value(1.0),
+ "Timestep unit (default: 1.0[s])")
+ ("dx", value(&dx)->default_value(1.0),
+ "Local x dimension")
+ ( "no-header", "do not print out the csv header row")
+ ;
+ // clang-format on
+
+ // Initialize and run HPX
+ hpx::local::init_params init_args;
+ init_args.desc_cmdline = desc_commandline;
+
+ return hpx::local::init(hpx_main, argc, argv, init_args);
+}
diff --git a/branches/master/singlehtml/_downloads/48f28094bcf0ac3599ad30d740006767/1d_stencil_6.cpp b/branches/master/singlehtml/_downloads/48f28094bcf0ac3599ad30d740006767/1d_stencil_6.cpp
new file mode 100644
index 00000000000..8dee84edae6
--- /dev/null
+++ b/branches/master/singlehtml/_downloads/48f28094bcf0ac3599ad30d740006767/1d_stencil_6.cpp
@@ -0,0 +1,453 @@
+// Copyright (c) 2014 Hartmut Kaiser
+//
+// SPDX-License-Identifier: BSL-1.0
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// This is the sixth in a series of examples demonstrating the development of a
+// fully distributed solver for a simple 1D heat distribution problem.
+//
+// This example builds on example five.
+
+#include
+#if !defined(HPX_COMPUTE_DEVICE_CODE)
+#include
+#include
+#include
+#include
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include "print_time_results.hpp"
+
+///////////////////////////////////////////////////////////////////////////////
+// Command-line variables
+bool header = true; // print csv heading
+double k = 0.5; // heat transfer coefficient
+double dt = 1.; // time step
+double dx = 1.; // grid spacing
+
+inline std::size_t idx(std::size_t i, int dir, std::size_t size)
+{
+ if (i == 0 && dir == -1)
+ return size - 1;
+ if (i == size - 1 && dir == +1)
+ return 0;
+
+ HPX_ASSERT((i + dir) < size);
+
+ return i + dir;
+}
+
+inline std::size_t locidx(std::size_t i, std::size_t np, std::size_t nl)
+{
+ return (i * nl) / np;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+struct partition_data
+{
+private:
+ typedef hpx::serialization::serialize_buffer buffer_type;
+
+public:
+ partition_data()
+ : size_(0)
+ , min_index_(0)
+ {
+ }
+
+ // Create a new (uninitialized) partition of the given size.
+ explicit partition_data(std::size_t size)
+ : data_(new double[size], size, buffer_type::take)
+ , size_(size)
+ , min_index_(0)
+ {
+ }
+
+ // Create a new (initialized) partition of the given size.
+ partition_data(std::size_t size, double initial_value)
+ : data_(new double[size], size, buffer_type::take)
+ , size_(size)
+ , min_index_(0)
+ {
+ double base_value = double(initial_value * size);
+ for (std::size_t i = 0; i != size; ++i)
+ data_[i] = base_value + double(i);
+ }
+
+ // Create a partition which acts as a proxy to a part of the embedded array.
+ // The proxy is assumed to refer to either the left or the right boundary
+ // element.
+ partition_data(partition_data const& base, std::size_t min_index)
+ : data_(base.data_.data() + min_index, 1, buffer_type::reference)
+ , size_(base.size())
+ , min_index_(min_index)
+ {
+ HPX_ASSERT(min_index < base.size());
+ }
+
+ double& operator[](std::size_t idx)
+ {
+ return data_[index(idx)];
+ }
+ double operator[](std::size_t idx) const
+ {
+ return data_[index(idx)];
+ }
+
+ std::size_t size() const
+ {
+ return size_;
+ }
+
+private:
+ std::size_t index(std::size_t idx) const
+ {
+ HPX_ASSERT(idx >= min_index_ && idx < size_);
+ return idx - min_index_;
+ }
+
+private:
+ // Serialization support: even if all of the code below runs on one
+ // locality only, we need to provide an (empty) implementation for the
+ // serialization as all arguments passed to actions have to support this.
+ friend class hpx::serialization::access;
+
+ template
+ void serialize(Archive& ar, const unsigned int)
+ {
+ // clang-format off
+ ar & data_ & size_ & min_index_;
+ // clang-format on
+ }
+
+private:
+ buffer_type data_;
+ std::size_t size_;
+ std::size_t min_index_;
+};
+
+std::ostream& operator<<(std::ostream& os, partition_data const& c)
+{
+ os << "{";
+ for (std::size_t i = 0; i != c.size(); ++i)
+ {
+ if (i != 0)
+ os << ", ";
+ os << c[i];
+ }
+ os << "}";
+ return os;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// This is the server side representation of the data. We expose this as a HPX
+// component which allows for it to be created and accessed remotely through
+// a global address (hpx::id_type).
+struct partition_server : hpx::components::component_base
+{
+ enum partition_type
+ {
+ left_partition,
+ middle_partition,
+ right_partition
+ };
+
+ // construct new instances
+ partition_server() {}
+
+ partition_server(partition_data const& data)
+ : data_(data)
+ {
+ }
+
+ partition_server(std::size_t size, double initial_value)
+ : data_(size, initial_value)
+ {
+ }
+
+ // Access data. The parameter specifies what part of the data should be
+ // accessed. As long as the result is used locally, no data is copied,
+ // however as soon as the result is requested from another locality only
+ // the minimally required amount of data will go over the wire.
+ partition_data get_data(partition_type t) const
+ {
+ switch (t)
+ {
+ case left_partition:
+ return partition_data(data_, data_.size() - 1);
+
+ case middle_partition:
+ break;
+
+ case right_partition:
+ return partition_data(data_, 0);
+
+ default:
+ HPX_ASSERT(false);
+ break;
+ }
+ return data_;
+ }
+
+ // Every member function which has to be invoked remotely needs to be
+ // wrapped into a component action. The macro below defines a new type
+ // 'get_data_action' which represents the (possibly remote) member function
+ // partition::get_data().
+ HPX_DEFINE_COMPONENT_DIRECT_ACTION(
+ partition_server, get_data, get_data_action)
+
+private:
+ partition_data data_;
+};
+
+// The macros below are necessary to generate the code required for exposing
+// our partition type remotely.
+//
+// HPX_REGISTER_COMPONENT() exposes the component creation
+// through hpx::new_<>().
+typedef hpx::components::component partition_server_type;
+HPX_REGISTER_COMPONENT(partition_server_type, partition_server)
+
+// HPX_REGISTER_ACTION() exposes the component member function for remote
+// invocation.
+typedef partition_server::get_data_action get_data_action;
+HPX_REGISTER_ACTION(get_data_action)
+
+///////////////////////////////////////////////////////////////////////////////
+// This is a client side helper class allowing to hide some of the tedious
+// boilerplate.
+struct partition : hpx::components::client_base
+{
+ typedef hpx::components::client_base base_type;
+
+ partition() {}
+
+ // Create new component on locality 'where' and initialize the held data
+ partition(hpx::id_type where, std::size_t size, double initial_value)
+ : base_type(hpx::new_(where, size, initial_value))
+ {
+ }
+
+ // Create a new component on the locality co-located to the id 'where'. The
+ // new instance will be initialized from the given partition_data.
+ partition(hpx::id_type where, partition_data const& data)
+ : base_type(hpx::new_(hpx::colocated(where), data))
+ {
+ }
+
+ // Attach a future representing a (possibly remote) partition.
+ partition(hpx::future&& id)
+ : base_type(std::move(id))
+ {
+ }
+
+ // Unwrap a future (a partition already holds a future to the
+ // id of the referenced object, thus unwrapping accesses this inner future).
+ partition(hpx::future&& c)
+ : base_type(std::move(c))
+ {
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Invoke the (remote) member function which gives us access to the data.
+ // This is a pure helper function hiding the async.
+ hpx::future get_data(
+ partition_server::partition_type t) const
+ {
+ partition_server::get_data_action act;
+ return hpx::async(act, get_id(), t);
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+struct stepper
+{
+ // Our data for one time step
+ typedef std::vector space;
+
+ // Our operator
+ static double heat(double left, double middle, double right)
+ {
+ return middle + (k * dt / (dx * dx)) * (left - 2 * middle + right);
+ }
+
+ // The partitioned operator, it invokes the heat operator above on all elements
+ // of a partition.
+ static partition_data heat_part_data(partition_data const& left,
+ partition_data const& middle, partition_data const& right)
+ {
+ std::size_t size = middle.size();
+ partition_data next(size);
+
+ next[0] = heat(left[size - 1], middle[0], middle[1]);
+
+ for (std::size_t i = 1; i != size - 1; ++i)
+ next[i] = heat(middle[i - 1], middle[i], middle[i + 1]);
+
+ next[size - 1] = heat(middle[size - 2], middle[size - 1], right[0]);
+
+ return next;
+ }
+
+ static partition heat_part(
+ partition const& left, partition const& middle, partition const& right)
+ {
+ using hpx::dataflow;
+ using hpx::unwrapping;
+
+ return dataflow(hpx::launch::async,
+ unwrapping([left, middle, right](partition_data const& l,
+ partition_data const& m, partition_data const& r) {
+ HPX_UNUSED(left);
+ HPX_UNUSED(right);
+
+ // The new partition_data will be allocated on the same locality
+ // as 'middle'.
+ return partition(middle.get_id(), heat_part_data(l, m, r));
+ }),
+ left.get_data(partition_server::left_partition),
+ middle.get_data(partition_server::middle_partition),
+ right.get_data(partition_server::right_partition));
+ }
+
+ // do all the work on 'np' partitions, 'nx' data points each, for 'nt'
+ // time steps
+ space do_work(std::size_t np, std::size_t nx, std::size_t nt);
+};
+
+// Global functions can be exposed as actions as well. That allows to invoke
+// those remotely. The macro HPX_PLAIN_ACTION() defines a new action type
+// 'heat_part_action' which wraps the global function heat_part(). It can be
+// used to call that function on a given locality.
+HPX_PLAIN_ACTION(stepper::heat_part, heat_part_action)
+
+///////////////////////////////////////////////////////////////////////////////
+// do all the work on 'np' partitions, 'nx' data points each, for 'nt'
+// time steps
+stepper::space stepper::do_work(std::size_t np, std::size_t nx, std::size_t nt)
+{
+ using hpx::dataflow;
+
+ std::vector localities = hpx::find_all_localities();
+ std::size_t nl = localities.size(); // Number of localities
+
+ // U[t][i] is the state of position i at time t.
+ std::vector U(2);
+ for (space& s : U)
+ s.resize(np);
+
+ // Initial conditions: f(0, i) = i
+ //[do_work_6
+ for (std::size_t i = 0; i != np; ++i)
+ U[0][i] = partition(localities[locidx(i, np, nl)], nx, double(i));
+ //]
+ heat_part_action act;
+ for (std::size_t t = 0; t != nt; ++t)
+ {
+ space const& current = U[t % 2];
+ space& next = U[(t + 1) % 2];
+
+ for (std::size_t i = 0; i != np; ++i)
+ {
+ // we execute the action on the locality of the middle partition
+ using hpx::placeholders::_1;
+ using hpx::placeholders::_2;
+ using hpx::placeholders::_3;
+ auto Op = hpx::bind(act, localities[locidx(i, np, nl)], _1, _2, _3);
+ next[i] = dataflow(hpx::launch::async, Op, current[idx(i, -1, np)],
+ current[i], current[idx(i, +1, np)]);
+ }
+ }
+
+ // Return the solution at time-step 'nt'.
+ return U[nt % 2];
+}
+
+///////////////////////////////////////////////////////////////////////////////
+int hpx_main(hpx::program_options::variables_map& vm)
+{
+ std::uint64_t np = vm["np"].as(); // Number of partitions.
+ std::uint64_t nx =
+ vm["nx"].as(); // Number of grid points.
+ std::uint64_t nt = vm["nt"].as(); // Number of steps.
+
+ if (vm.count("no-header"))
+ header = false;
+
+ std::vector localities = hpx::find_all_localities();
+ std::size_t nl = localities.size(); // Number of localities
+
+ if (np < nl)
+ {
+ std::cout << "The number of partitions should not be smaller than "
+ "the number of localities"
+ << std::endl;
+ return hpx::finalize();
+ }
+
+ // Create the stepper object
+ stepper step;
+
+ // Measure execution time.
+ std::uint64_t t = hpx::chrono::high_resolution_clock::now();
+
+ // Execute nt time steps on nx grid points and print the final solution.
+ stepper::space solution = step.do_work(np, nx, nt);
+ for (std::size_t i = 0; i != np; ++i)
+ solution[i].get_data(partition_server::middle_partition).wait();
+
+ std::uint64_t elapsed = hpx::chrono::high_resolution_clock::now() - t;
+
+ // Print the final solution
+ if (vm.count("results"))
+ {
+ for (std::size_t i = 0; i != np; ++i)
+ {
+ std::cout << "U[" << i << "] = "
+ << solution[i]
+ .get_data(partition_server::middle_partition)
+ .get()
+ << std::endl;
+ }
+ }
+ std::uint64_t const num_worker_threads = hpx::get_num_worker_threads();
+ hpx::future locs = hpx::get_num_localities();
+ print_time_results(
+ locs.get(), num_worker_threads, elapsed, nx, np, nt, header);
+
+ return hpx::finalize();
+}
+
+int main(int argc, char* argv[])
+{
+ using namespace hpx::program_options;
+
+ options_description desc_commandline;
+ desc_commandline.add_options()(
+ "results", "print generated results (default: false)")("nx",
+ value()->default_value(10),
+ "Local x dimension (of each partition)")("nt",
+ value()->default_value(45),
+ "Number of time steps")("np", value()->default_value(10),
+ "Number of partitions")("k", value(&k)->default_value(0.5),
+ "Heat transfer coefficient (default: 0.5)")("dt",
+ value(&dt)->default_value(1.0),
+ "Timestep unit (default: 1.0[s])")(
+ "dx", value(&dx)->default_value(1.0), "Local x dimension")(
+ "no-header", "do not print out the csv header row");
+
+ // Initialize and run HPX
+ hpx::init_params init_args;
+ init_args.desc_cmdline = desc_commandline;
+
+ return hpx::init(argc, argv, init_args);
+}
+#endif
diff --git a/branches/master/singlehtml/_downloads/4cb45820e6f6f8a05757084e21d17736/1d_stencil_3.cpp b/branches/master/singlehtml/_downloads/4cb45820e6f6f8a05757084e21d17736/1d_stencil_3.cpp
new file mode 100644
index 00000000000..c9cdd05f490
--- /dev/null
+++ b/branches/master/singlehtml/_downloads/4cb45820e6f6f8a05757084e21d17736/1d_stencil_3.cpp
@@ -0,0 +1,219 @@
+// Copyright (c) 2014 Hartmut Kaiser
+// Copyright (c) 2014 Patricia Grubel
+//
+// SPDX-License-Identifier: BSL-1.0
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// This is the third in a series of examples demonstrating the development of a
+// fully distributed solver for a simple 1D heat distribution problem.
+//
+// This example takes the code from example one and introduces a partitioning
+// of the 1D grid into groups of grid partitions which are handled at the same time.
+// The purpose is to be able to control the amount of work performed. The
+// example is still fully serial, no parallelization is performed.
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include "print_time_results.hpp"
+
+///////////////////////////////////////////////////////////////////////////////
+// Command-line variables
+bool header = true; // print csv heading
+double k = 0.5; // heat transfer coefficient
+double dt = 1.; // time step
+double dx = 1.; // grid spacing
+
+inline std::size_t idx(std::size_t i, int dir, std::size_t size)
+{
+ if (i == 0 && dir == -1)
+ return size - 1;
+ if (i == size - 1 && dir == +1)
+ return 0;
+
+ HPX_ASSERT((i + dir) < size);
+
+ return i + dir;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Our partition_data data type
+struct partition_data
+{
+ partition_data(std::size_t size = 0)
+ : data_(size)
+ {
+ }
+
+ partition_data(std::size_t size, double initial_value)
+ : data_(size)
+ {
+ double base_value = double(initial_value * size);
+ for (std::size_t i = 0; i != size; ++i)
+ data_[i] = base_value + double(i);
+ }
+
+ double& operator[](std::size_t idx)
+ {
+ return data_[idx];
+ }
+ double operator[](std::size_t idx) const
+ {
+ return data_[idx];
+ }
+
+ std::size_t size() const
+ {
+ return data_.size();
+ }
+
+private:
+ std::vector data_;
+};
+
+std::ostream& operator<<(std::ostream& os, partition_data const& c)
+{
+ os << "{";
+ for (std::size_t i = 0; i != c.size(); ++i)
+ {
+ if (i != 0)
+ os << ", ";
+ os << c[i];
+ }
+ os << "}";
+ return os;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+struct stepper
+{
+ // Our data for one time step
+ typedef partition_data partition;
+ typedef std::vector space;
+
+ // Our operator
+ static double heat(double left, double middle, double right)
+ {
+ return middle + (k * dt / (dx * dx)) * (left - 2 * middle + right);
+ }
+
+ // The partitioned operator, it invokes the heat operator above on all
+ // elements of a partition.
+ static partition_data heat_part(partition_data const& left,
+ partition_data const& middle, partition_data const& right)
+ {
+ std::size_t size = middle.size();
+ partition_data next(size);
+
+ next[0] = heat(left[size - 1], middle[0], middle[1]);
+
+ for (std::size_t i = 1; i != size - 1; ++i)
+ next[i] = heat(middle[i - 1], middle[i], middle[i + 1]);
+
+ next[size - 1] = heat(middle[size - 2], middle[size - 1], right[0]);
+
+ return next;
+ }
+
+ // do all the work on 'np' partitions, 'nx' data points each, for 'nt'
+ // time steps
+ space do_work(std::size_t np, std::size_t nx, std::size_t nt)
+ {
+ // U[t][i] is the state of position i at time t.
+ std::vector U(2);
+ for (space& s : U)
+ s.resize(np);
+
+ // Initial conditions: f(0, i) = i
+ for (std::size_t i = 0; i != np; ++i)
+ U[0][i] = partition_data(nx, double(i));
+
+ // Actual time step loop
+ for (std::size_t t = 0; t != nt; ++t)
+ {
+ space const& current = U[t % 2];
+ space& next = U[(t + 1) % 2];
+
+ for (std::size_t i = 0; i != np; ++i)
+ next[i] = heat_part(current[idx(i, -1, np)], current[i],
+ current[idx(i, +1, np)]);
+ }
+
+ // Return the solution at time-step 'nt'.
+ return U[nt % 2];
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+int hpx_main(hpx::program_options::variables_map& vm)
+{
+ std::uint64_t np = vm["np"].as(); // Number of partitions.
+ std::uint64_t nx =
+ vm["nx"].as(); // Number of grid points.
+ std::uint64_t nt = vm["nt"].as(); // Number of steps.
+
+ if (vm.count("no-header"))
+ header = false;
+
+ // Create the stepper object
+ stepper step;
+
+ // Measure execution time.
+ std::uint64_t t = hpx::chrono::high_resolution_clock::now();
+
+ // Execute nt time steps on nx grid points and print the final solution.
+ stepper::space solution = step.do_work(np, nx, nt);
+
+ std::uint64_t elapsed = hpx::chrono::high_resolution_clock::now() - t;
+
+ // Print the final solution
+ if (vm.count("results"))
+ {
+ for (std::size_t i = 0; i != np; ++i)
+ std::cout << "U[" << i << "] = " << solution[i] << std::endl;
+ }
+
+ std::uint64_t const os_thread_count = hpx::get_os_thread_count();
+ print_time_results(os_thread_count, elapsed, nx, np, nt, header);
+
+ return hpx::local::finalize();
+}
+
+int main(int argc, char* argv[])
+{
+ namespace po = hpx::program_options;
+
+ po::options_description desc_commandline;
+ // clang-format off
+ desc_commandline.add_options()
+ ("results", "print generated results (default: false)")
+ ("nx", po::value()->default_value(10),
+ "Local x dimension (of each partition)")
+ ("nt", po::value()->default_value(45),
+ "Number of time steps")
+ ("np", po::value()->default_value(10),
+ "Number of partitions")
+ ("k", po::value(&k)->default_value(0.5),
+ "Heat transfer coefficient (default: 0.5)")
+ ("dt", po::value(&dt)->default_value(1.0),
+ "Timestep unit (default: 1.0[s])")
+ ("dx", po::value(&dx)->default_value(1.0),
+ "Local x dimension")
+ ( "no-header", "do not print out the csv header row")
+ ;
+ // clang-format on
+
+ // Initialize and run HPX
+ hpx::local::init_params init_args;
+ init_args.desc_cmdline = desc_commandline;
+
+ return hpx::local::init(hpx_main, argc, argv, init_args);
+}
diff --git a/branches/master/singlehtml/_downloads/55606400a072008c0660a7909abc9866/simplest_performance_counter.cpp b/branches/master/singlehtml/_downloads/55606400a072008c0660a7909abc9866/simplest_performance_counter.cpp
new file mode 100644
index 00000000000..f5bc058f987
--- /dev/null
+++ b/branches/master/singlehtml/_downloads/55606400a072008c0660a7909abc9866/simplest_performance_counter.cpp
@@ -0,0 +1,106 @@
+// Copyright (c) 2007-2012 Hartmut Kaiser
+//
+// SPDX-License-Identifier: BSL-1.0
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// The purpose of this example is to demonstrate the simplest way to create and
+// use a performance counter for HPX.
+
+#include
+#if !defined(HPX_COMPUTE_DEVICE_CODE)
+#include
+#include
+
+#include
+#include
+
+///////////////////////////////////////////////////////////////////////////////
+// The atomic variable 'counter' ensures the thread safety of the counter.
+std::atomic counter(0);
+
+std::int64_t some_performance_data(bool reset)
+{
+ ++counter;
+ return hpx::util::get_and_reset_value(counter, reset);
+}
+
+void register_counter_type()
+{
+ // Call the HPX API function to register the counter type.
+ hpx::performance_counters::install_counter_type(
+ // counter type name
+ "/test/data",
+ // function providing counter data
+ &some_performance_data,
+ // description text
+ "returns a linearly increasing counter value",
+ // unit of measure
+ "",
+ // counter type
+ hpx::performance_counters::counter_type::monotonically_increasing);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+int hpx_main()
+{
+ {
+ // Now it is possible to instantiate a new counter instance based on
+ // the naming scheme "/test{locality#0/total}/data". Try invoking this
+ // example using the command line option:
+ //
+ // --hpx:print-counter=/test{locality#0/total}/data
+ //
+ // This will print something like:
+ //
+ // test{locality#0/total}/data,1,1.005240[s],1
+ //
+ // where the first value is a sequence counter of the invocation of the
+ // counter. The next is the timestamp marking the point in time since
+ // application startup at which this counter has been queried. The last
+ // value printed is the counter value retrieved at the listed point in
+ // time.
+
+ // By invoking this example with the command line options:
+ //
+ // --hpx:print-counter=/test{locality#0/total}/data
+ // --hpx:print-counter-interval=100
+ //
+ // the counter will be queried periodically and the output will look
+ // like:
+ //
+ // test{locality#0/total}/data,1,0.001937[s],1
+ // test{locality#0/total}/data,2,0.109625[s],2
+ // test{locality#0/total}/data,3,0.217192[s],3
+ // test{locality#0/total}/data,4,0.323497[s],4
+ // test{locality#0/total}/data,5,0.430867[s],5
+ // test{locality#0/total}/data,6,0.536965[s],6
+ // test{locality#0/total}/data,7,0.643422[s],7
+ // test{locality#0/total}/data,8,0.750788[s],8
+ // test{locality#0/total}/data,9,0.857031[s],9
+ // test{locality#0/total}/data,10,0.963330[s],10
+ // test{locality#0/total}/data,11,1.015063[s],11
+ //
+ // which shows that the counter has been queried roughly every 100
+ // milliseconds, as specified. Additionally it will be queried during
+ // application shutdown, as before.
+
+ hpx::this_thread::suspend(1000); // wait for one second
+ }
+ return hpx::finalize();
+}
+
+int main(int argc, char* argv[])
+{
+ // By registering the counter type we make it available to any consumer
+ // creating and querying an instance of the type "/test/data".
+ //
+ // This registration should be performed during startup. We register the
+ // function 'register_counter_type' to be executed as an HPX thread right
+ // before hpx_main will be executed.
+ hpx::register_startup_function(®ister_counter_type);
+
+ // Initialize and run HPX.
+ return hpx::init(argc, argv);
+}
+#endif
diff --git a/branches/master/singlehtml/_downloads/6c16f3445ab74741c294c956ec563399/matrix_multiplication.cpp b/branches/master/singlehtml/_downloads/6c16f3445ab74741c294c956ec563399/matrix_multiplication.cpp
new file mode 100644
index 00000000000..3453286d178
--- /dev/null
+++ b/branches/master/singlehtml/_downloads/6c16f3445ab74741c294c956ec563399/matrix_multiplication.cpp
@@ -0,0 +1,126 @@
+////////////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2021 Dimitra Karatza
+//
+// SPDX-License-Identifier: BSL-1.0
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+////////////////////////////////////////////////////////////////////////////////
+
+// Parallel implementation of matrix multiplication
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+std::mt19937 gen;
+
+///////////////////////////////////////////////////////////////////////////////
+//[mul_print_matrix
+void print_matrix(std::vector const& M, std::size_t rows, std::size_t cols,
+ char const* message)
+{
+ std::cout << "\nMatrix " << message << " is:" << std::endl;
+ for (std::size_t i = 0; i < rows; i++)
+ {
+ for (std::size_t j = 0; j < cols; j++)
+ std::cout << M[i * cols + j] << " ";
+ std::cout << "\n";
+ }
+}
+//]
+
+///////////////////////////////////////////////////////////////////////////////
+//[mul_hpx_main
+int hpx_main(hpx::program_options::variables_map& vm)
+{
+ using element_type = int;
+
+ // Define matrix sizes
+ std::size_t const rowsA = vm["n"].as();
+ std::size_t const colsA = vm["m"].as();
+ std::size_t const rowsB = colsA;
+ std::size_t const colsB = vm["k"].as();
+ std::size_t const rowsR = rowsA;
+ std::size_t const colsR = colsB;
+
+ // Initialize matrices A and B
+ std::vector A(rowsA * colsA);
+ std::vector B(rowsB * colsB);
+ std::vector R(rowsR * colsR);
+
+ // Define seed
+ unsigned int seed = std::random_device{}();
+ if (vm.count("seed"))
+ seed = vm["seed"].as();
+
+ gen.seed(seed);
+ std::cout << "using seed: " << seed << std::endl;
+
+ // Define range of values
+ int const lower = vm["l"].as();
+ int const upper = vm["u"].as();
+
+ // Matrices have random values in the range [lower, upper]
+ std::uniform_int_distribution dis(lower, upper);
+ auto generator = std::bind(dis, gen);
+ hpx::ranges::generate(A, generator);
+ hpx::ranges::generate(B, generator);
+
+ // Perform matrix multiplication
+ hpx::experimental::for_loop(hpx::execution::par, 0, rowsA, [&](auto i) {
+ hpx::experimental::for_loop(0, colsB, [&](auto j) {
+ R[i * colsR + j] = 0;
+ hpx::experimental::for_loop(0, rowsB, [&](auto k) {
+ R[i * colsR + j] += A[i * colsA + k] * B[k * colsB + j];
+ });
+ });
+ });
+
+ // Print all 3 matrices
+ print_matrix(A, rowsA, colsA, "A");
+ print_matrix(B, rowsB, colsB, "B");
+ print_matrix(R, rowsR, colsR, "R");
+
+ return hpx::local::finalize();
+}
+//]
+
+///////////////////////////////////////////////////////////////////////////////
+//[mul_main
+int main(int argc, char* argv[])
+{
+ using namespace hpx::program_options;
+ options_description cmdline("usage: " HPX_APPLICATION_STRING " [options]");
+ // clang-format off
+ cmdline.add_options()
+ ("n",
+ hpx::program_options::value()->default_value(2),
+ "Number of rows of first matrix")
+ ("m",
+ hpx::program_options::value()->default_value(3),
+ "Number of columns of first matrix (equal to the number of rows of "
+ "second matrix)")
+ ("k",
+ hpx::program_options::value()->default_value(2),
+ "Number of columns of second matrix")
+ ("seed,s",
+ hpx::program_options::value(),
+ "The random number generator seed to use for this run")
+ ("l",
+ hpx::program_options::value()->default_value(0),
+ "Lower limit of range of values")
+ ("u",
+ hpx::program_options::value()->default_value(10),
+ "Upper limit of range of values");
+ // clang-format on
+ hpx::local::init_params init_args;
+ init_args.desc_cmdline = cmdline;
+
+ return hpx::local::init(hpx_main, argc, argv, init_args);
+}
+//]
diff --git a/branches/master/singlehtml/_downloads/6fcd0e6fdb6ce242855e5c4b4773129f/1d_stencil_5.cpp b/branches/master/singlehtml/_downloads/6fcd0e6fdb6ce242855e5c4b4773129f/1d_stencil_5.cpp
new file mode 100644
index 00000000000..3895b76e8d6
--- /dev/null
+++ b/branches/master/singlehtml/_downloads/6fcd0e6fdb6ce242855e5c4b4773129f/1d_stencil_5.cpp
@@ -0,0 +1,387 @@
+// Copyright (c) 2014 Hartmut Kaiser
+//
+// SPDX-License-Identifier: BSL-1.0
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// This is the fifth in a series of examples demonstrating the development of a
+// fully distributed solver for a simple 1D heat distribution problem.
+//
+// This example builds on example four. It adds the possibility to distribute
+// both - the locality of the partitions and the locality of where the
+// heat_part code is executed. The overall code however still runs on one
+// locality only (it is always using hpx::find_here() as the target locality).
+//
+// This example adds all the boilerplate needed for enabling distributed
+// operation. Instead of calling (local) functions we invoke the corresponding
+// actions.
+
+#include
+#if !defined(HPX_COMPUTE_DEVICE_CODE)
+#include
+#include
+
+#if !defined(HPX_HAVE_CXX17_SHARED_PTR_ARRAY)
+#include
+#else
+#include
+#endif
+
+#include
+#include
+#include
+#include
+#include
+
+#include "print_time_results.hpp"
+
+///////////////////////////////////////////////////////////////////////////////
+// Command-line variables
+bool header = true; // print csv heading
+double k = 0.5; // heat transfer coefficient
+double dt = 1.; // time step
+double dx = 1.; // grid spacing
+
+inline std::size_t idx(std::size_t i, int dir, std::size_t size)
+{
+ if (i == 0 && dir == -1)
+ return size - 1;
+ if (i == size - 1 && dir == +1)
+ return 0;
+
+ HPX_ASSERT((i + dir) < size);
+
+ return i + dir;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+struct partition_data
+{
+private:
+#if defined(HPX_HAVE_CXX17_SHARED_PTR_ARRAY)
+ typedef std::shared_ptr buffer_type;
+#else
+ typedef boost::shared_array buffer_type;
+#endif
+
+public:
+ partition_data()
+ : size_(0)
+ {
+ }
+
+ explicit partition_data(std::size_t size)
+ : data_(new double[size])
+ , size_(size)
+ {
+ }
+
+ partition_data(std::size_t size, double initial_value)
+ : data_(new double[size])
+ , size_(size)
+ {
+ double base_value = double(initial_value * size);
+ for (std::size_t i = 0; i != size; ++i)
+ data_[i] = base_value + double(i);
+ }
+
+ double& operator[](std::size_t idx)
+ {
+ return data_[idx];
+ }
+ double operator[](std::size_t idx) const
+ {
+ return data_[idx];
+ }
+
+ std::size_t size() const
+ {
+ return size_;
+ }
+
+private:
+ // Serialization support: even if all of the code below runs on one
+ // locality only, we need to provide an (empty) implementation for the
+ // serialization as all arguments passed to actions have to support this.
+ friend class hpx::serialization::access;
+
+ template
+ void serialize(Archive&, const unsigned int) const
+ {
+ }
+
+private:
+ buffer_type data_;
+ std::size_t size_;
+};
+
+std::ostream& operator<<(std::ostream& os, partition_data const& c)
+{
+ os << "{";
+ for (std::size_t i = 0; i != c.size(); ++i)
+ {
+ if (i != 0)
+ os << ", ";
+ os << c[i];
+ }
+ os << "}";
+ return os;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// This is the server side representation of the data. We expose this as a HPX
+// component which allows for it to be created and accessed remotely through
+// a global address (hpx::id_type).
+struct partition_server : hpx::components::component_base
+{
+ // construct new instances
+ partition_server() {}
+
+ partition_server(partition_data const& data)
+ : data_(data)
+ {
+ }
+
+ partition_server(std::size_t size, double initial_value)
+ : data_(size, initial_value)
+ {
+ }
+
+ // access data
+ partition_data get_data() const
+ {
+ return data_;
+ }
+
+ // Every member function which has to be invoked remotely needs to be
+ // wrapped into a component action. The macro below defines a new type
+ // 'get_data_action' which represents the (possibly remote) member function
+ // partition::get_data().
+ HPX_DEFINE_COMPONENT_DIRECT_ACTION(
+ partition_server, get_data, get_data_action)
+
+private:
+ partition_data data_;
+};
+
+// The macros below are necessary to generate the code required for exposing
+// our partition type remotely.
+//
+// HPX_REGISTER_COMPONENT() exposes the component creation
+// through hpx::new_<>().
+typedef hpx::components::component partition_server_type;
+HPX_REGISTER_COMPONENT(partition_server_type, partition_server)
+
+// HPX_REGISTER_ACTION() exposes the component member function for remote
+// invocation.
+typedef partition_server::get_data_action get_data_action;
+HPX_REGISTER_ACTION(get_data_action)
+
+///////////////////////////////////////////////////////////////////////////////
+// This is a client side helper class allowing to hide some of the tedious
+// boilerplate.
+struct partition : hpx::components::client_base
+{
+ typedef hpx::components::client_base base_type;
+
+ partition() {}
+
+ // Create new component on locality 'where' and initialize the held data
+ partition(hpx::id_type where, std::size_t size, double initial_value)
+ : base_type(hpx::new_(where, size, initial_value))
+ {
+ }
+
+ // Create a new component on the locality co-located to the id 'where'. The
+ // new instance will be initialized from the given partition_data.
+ partition(hpx::id_type where, partition_data&& data)
+ : base_type(
+ hpx::new_(hpx::colocated(where), std::move(data)))
+ {
+ }
+
+ // Attach a future representing a (possibly remote) partition.
+ partition(hpx::future&& id)
+ : base_type(std::move(id))
+ {
+ }
+
+ // Unwrap a future (a partition already holds a future to the id of the
+ // referenced object, thus unwrapping accesses this inner future).
+ partition(hpx::future&& c)
+ : base_type(std::move(c))
+ {
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Invoke the (remote) member function which gives us access to the data.
+ // This is a pure helper function hiding the async.
+ hpx::future get_data() const
+ {
+ return hpx::async(get_data_action(), get_id());
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+struct stepper
+{
+ // Our data for one time step
+ typedef std::vector space;
+
+ // Our operator
+ static double heat(double left, double middle, double right)
+ {
+ return middle + (k * dt / (dx * dx)) * (left - 2 * middle + right);
+ }
+
+ // The partitioned operator, it invokes the heat operator above on all elements
+ // of a partition.
+ static partition_data heat_part_data(partition_data const& left,
+ partition_data const& middle, partition_data const& right)
+ {
+ // create new partition_data instance for next time step
+ std::size_t size = middle.size();
+ partition_data next(size);
+
+ next[0] = heat(left[size - 1], middle[0], middle[1]);
+
+ for (std::size_t i = 1; i != size - 1; ++i)
+ next[i] = heat(middle[i - 1], middle[i], middle[i + 1]);
+
+ next[size - 1] = heat(middle[size - 2], middle[size - 1], right[0]);
+
+ return next;
+ }
+
+ static partition heat_part(
+ partition const& left, partition const& middle, partition const& right)
+ {
+ using hpx::dataflow;
+ using hpx::unwrapping;
+
+ return dataflow(
+ unwrapping([middle](partition_data const& l,
+ partition_data const& m, partition_data const& r) {
+ // The new partition_data will be allocated on the same
+ // locality as 'middle'.
+ return partition(middle.get_id(), heat_part_data(l, m, r));
+ }),
+ left.get_data(), middle.get_data(), right.get_data());
+ }
+
+ // do all the work on 'np' partitions, 'nx' data points each, for 'nt'
+ // time steps
+ space do_work(std::size_t np, std::size_t nx, std::size_t nt);
+};
+
+// Global functions can be exposed as actions as well. That allows to invoke
+// those remotely. The macro HPX_PLAIN_ACTION() defines a new action type
+// 'heat_part_action' which wraps the global function heat_part(). It can be
+// used to call that function on a given locality.
+HPX_PLAIN_ACTION(stepper::heat_part, heat_part_action)
+
+///////////////////////////////////////////////////////////////////////////////
+// do all the work on 'np' partitions, 'nx' data points each, for 'nt'
+// time steps
+stepper::space stepper::do_work(std::size_t np, std::size_t nx, std::size_t nt)
+{
+ using hpx::dataflow;
+
+ // U[t][i] is the state of position i at time t.
+ std::vector U(2);
+ for (space& s : U)
+ s.resize(np);
+
+ // Initial conditions: f(0, i) = i
+ for (std::size_t i = 0; i != np; ++i)
+ U[0][i] = partition(hpx::find_here(), nx, double(i));
+
+ using hpx::placeholders::_1;
+ using hpx::placeholders::_2;
+ using hpx::placeholders::_3;
+ auto Op = hpx::bind(heat_part_action(), hpx::find_here(), _1, _2, _3);
+
+ // Actual time step loop
+ for (std::size_t t = 0; t != nt; ++t)
+ {
+ space const& current = U[t % 2];
+ space& next = U[(t + 1) % 2];
+
+ for (std::size_t i = 0; i != np; ++i)
+ {
+ next[i] = dataflow(hpx::launch::async, Op, current[idx(i, -1, np)],
+ current[i], current[idx(i, +1, np)]);
+ }
+ }
+
+ // Return the solution at time-step 'nt'.
+ return U[nt % 2];
+}
+
+///////////////////////////////////////////////////////////////////////////////
+int hpx_main(hpx::program_options::variables_map& vm)
+{
+ std::uint64_t np = vm["np"].as(); // Number of partitions.
+ std::uint64_t nx =
+ vm["nx"].as(); // Number of grid points.
+ std::uint64_t nt = vm["nt"].as(); // Number of steps.
+
+ if (vm.count("no-header"))
+ header = false;
+
+ // Create the stepper object
+ stepper step;
+
+ // Measure execution time.
+ std::uint64_t t = hpx::chrono::high_resolution_clock::now();
+
+ // Execute nt time steps on nx grid points and print the final solution.
+ stepper::space solution = step.do_work(np, nx, nt);
+ for (std::size_t i = 0; i != np; ++i)
+ solution[i].get_data().wait();
+
+ std::uint64_t elapsed = hpx::chrono::high_resolution_clock::now() - t;
+
+ // Print the final solution
+ if (vm.count("results"))
+ {
+ for (std::size_t i = 0; i != np; ++i)
+ {
+ std::cout << "U[" << i << "] = " << solution[i].get_data().get()
+ << std::endl;
+ }
+ }
+
+ std::uint64_t const num_worker_threads = hpx::get_num_worker_threads();
+ hpx::future locs = hpx::get_num_localities();
+ print_time_results(
+ locs.get(), num_worker_threads, elapsed, nx, np, nt, header);
+
+ return hpx::finalize();
+}
+
+int main(int argc, char* argv[])
+{
+ using namespace hpx::program_options;
+
+ options_description desc_commandline;
+ desc_commandline.add_options()(
+ "results", "print generated results (default: false)")("nx",
+ value()->default_value(10),
+ "Local x dimension (of each partition)")("nt",
+ value()->default_value(45),
+ "Number of time steps")("np", value()->default_value(10),
+ "Number of partitions")("k", value(&k)->default_value(0.5),
+ "Heat transfer coefficient (default: 0.5)")("dt",
+ value(&dt)->default_value(1.0),
+ "Timestep unit (default: 1.0[s])")(
+ "dx", value(&dx)->default_value(1.0), "Local x dimension")(
+ "no-header", "do not print out the csv header row");
+
+ // Initialize and run HPX
+ hpx::init_params init_args;
+ init_args.desc_cmdline = desc_commandline;
+
+ return hpx::init(argc, argv, init_args);
+}
+#endif
diff --git a/branches/master/singlehtml/_downloads/7b08f088c4a0239d9ff79cffe9cab53c/component_in_executable.cpp b/branches/master/singlehtml/_downloads/7b08f088c4a0239d9ff79cffe9cab53c/component_in_executable.cpp
new file mode 100644
index 00000000000..2b73e2ebafc
--- /dev/null
+++ b/branches/master/singlehtml/_downloads/7b08f088c4a0239d9ff79cffe9cab53c/component_in_executable.cpp
@@ -0,0 +1,74 @@
+////////////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2012 Bryce Adelstein-Lelbach
+//
+// SPDX-License-Identifier: BSL-1.0
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+///////////////////////////////////////////////////////////////////////////////
+
+#include
+#if !defined(HPX_COMPUTE_DEVICE_CODE)
+#include
+#include
+#include
+#include
+
+#include
+
+using hpx::components::client_base;
+using hpx::components::component;
+using hpx::components::component_base;
+
+using hpx::async;
+using hpx::find_here;
+
+using hpx::cout;
+
+struct hello_world_server : component_base
+{
+ void print() const
+ {
+ cout << "hello world\n" << std::flush;
+ }
+
+ HPX_DEFINE_COMPONENT_ACTION(hello_world_server, print, print_action)
+};
+
+typedef component server_type;
+HPX_REGISTER_COMPONENT(server_type, hello_world_server)
+
+typedef hello_world_server::print_action print_action;
+HPX_REGISTER_ACTION_DECLARATION(print_action)
+HPX_REGISTER_ACTION(print_action)
+
+struct hello_world : client_base
+{
+ typedef client_base base_type;
+
+ hello_world() = default;
+ explicit hello_world(hpx::id_type const& id)
+ : base_type(id)
+ {
+ }
+ hello_world(hpx::future&& id)
+ : base_type(std::move(id))
+ {
+ }
+
+ void print()
+ {
+ async(this->get_id()).get();
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ hello_world hw = hpx::new_(find_here());
+
+ hw.print();
+
+ return 0;
+}
+
+#endif
diff --git a/branches/master/singlehtml/_downloads/8718f91881bfac20e1674d008f5651e3/1d_stencil_7.cpp b/branches/master/singlehtml/_downloads/8718f91881bfac20e1674d008f5651e3/1d_stencil_7.cpp
new file mode 100644
index 00000000000..f3c05da7de5
--- /dev/null
+++ b/branches/master/singlehtml/_downloads/8718f91881bfac20e1674d008f5651e3/1d_stencil_7.cpp
@@ -0,0 +1,475 @@
+// Copyright (c) 2014-2022 Hartmut Kaiser
+//
+// SPDX-License-Identifier: BSL-1.0
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// This is the seventh in a series of examples demonstrating the development
+// of a fully distributed solver for a simple 1D heat distribution problem.
+//
+// This example builds on example six.
+
+#include
+#if !defined(HPX_COMPUTE_DEVICE_CODE)
+#include
+#include
+#include
+#include
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "print_time_results.hpp"
+
+///////////////////////////////////////////////////////////////////////////////
+// Command-line variables
+bool header = true; // print csv heading
+double k = 0.5; // heat transfer coefficient
+double dt = 1.; // time step
+double dx = 1.; // grid spacing
+
+inline std::size_t idx(std::size_t i, int dir, std::size_t size)
+{
+ if (i == 0 && dir == -1)
+ return size - 1;
+ if (i == size - 1 && dir == +1)
+ return 0;
+
+ HPX_ASSERT((i + dir) < size);
+
+ return i + dir;
+}
+
+inline std::size_t locidx(std::size_t i, std::size_t np, std::size_t nl)
+{
+ return (i * nl) / np;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+struct partition_data
+{
+private:
+ typedef hpx::serialization::serialize_buffer buffer_type;
+
+public:
+ partition_data()
+ : size_(0)
+ , min_index_(0)
+ {
+ }
+
+ // Create a new (uninitialized) partition of the given size.
+ explicit partition_data(std::size_t size)
+ : data_(new double[size], size, buffer_type::take)
+ , size_(size)
+ , min_index_(0)
+ {
+ }
+
+ // Create a new (initialized) partition of the given size.
+ partition_data(std::size_t size, double initial_value)
+ : data_(new double[size], size, buffer_type::take)
+ , size_(size)
+ , min_index_(0)
+ {
+ double base_value = double(initial_value * size);
+ for (std::size_t i = 0; i != size; ++i)
+ data_[i] = base_value + double(i);
+ }
+
+ // Create a partition which acts as a proxy to a part of the embedded array.
+ // The proxy is assumed to refer to either the left or the right boundary
+ // element.
+ partition_data(partition_data const& base, std::size_t min_index)
+ : data_(base.data_.data() + min_index, 1, buffer_type::reference)
+ , size_(base.size())
+ , min_index_(min_index)
+ {
+ HPX_ASSERT(min_index < base.size());
+ }
+
+ double& operator[](std::size_t idx)
+ {
+ return data_[index(idx)];
+ }
+ double operator[](std::size_t idx) const
+ {
+ return data_[index(idx)];
+ }
+
+ std::size_t size() const
+ {
+ return size_;
+ }
+
+private:
+ std::size_t index(std::size_t idx) const
+ {
+ HPX_ASSERT(idx >= min_index_ && idx < size_);
+ return idx - min_index_;
+ }
+
+private:
+ // Serialization support: even if all of the code below runs on one
+ // locality only, we need to provide an (empty) implementation for the
+ // serialization as all arguments passed to actions have to support this.
+ friend class hpx::serialization::access;
+
+ template
+ void serialize(Archive& ar, const unsigned int)
+ {
+ // clang-format off
+ ar & data_ & size_ & min_index_;
+ // clang-format on
+ }
+
+private:
+ buffer_type data_;
+ std::size_t size_;
+ std::size_t min_index_;
+};
+
+std::ostream& operator<<(std::ostream& os, partition_data const& c)
+{
+ os << "{";
+ for (std::size_t i = 0; i != c.size(); ++i)
+ {
+ if (i != 0)
+ os << ", ";
+ os << c[i];
+ }
+ os << "}";
+ return os;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// This is the server side representation of the data. We expose this as a HPX
+// component which allows for it to be created and accessed remotely through
+// a global address (hpx::id_type).
+struct partition_server : hpx::components::component_base
+{
+ enum partition_type
+ {
+ left_partition,
+ middle_partition,
+ right_partition
+ };
+
+ // construct new instances
+ partition_server() {}
+
+ partition_server(partition_data const& data)
+ : data_(data)
+ {
+ }
+
+ partition_server(std::size_t size, double initial_value)
+ : data_(size, initial_value)
+ {
+ }
+
+ // Access data. The parameter specifies what part of the data should be
+ // accessed. As long as the result is used locally, no data is copied,
+ // however as soon as the result is requested from another locality only
+ // the minimally required amount of data will go over the wire.
+ partition_data get_data(partition_type t) const
+ {
+ switch (t)
+ {
+ case left_partition:
+ return partition_data(data_, data_.size() - 1);
+
+ case middle_partition:
+ break;
+
+ case right_partition:
+ return partition_data(data_, 0);
+
+ default:
+ HPX_ASSERT(false);
+ break;
+ }
+ return data_;
+ }
+
+ // Every member function which has to be invoked remotely needs to be
+ // wrapped into a component action. The macro below defines a new type
+ // 'get_data_action' which represents the (possibly remote) member function
+ // partition::get_data().
+ HPX_DEFINE_COMPONENT_DIRECT_ACTION(
+ partition_server, get_data, get_data_action)
+
+private:
+ partition_data data_;
+};
+
+// The macros below are necessary to generate the code required for exposing
+// our partition type remotely.
+//
+// HPX_REGISTER_COMPONENT() exposes the component creation
+// through hpx::new_<>().
+typedef hpx::components::component partition_server_type;
+HPX_REGISTER_COMPONENT(partition_server_type, partition_server)
+
+// HPX_REGISTER_ACTION() exposes the component member function for remote
+// invocation.
+typedef partition_server::get_data_action get_data_action;
+HPX_REGISTER_ACTION(get_data_action)
+
+///////////////////////////////////////////////////////////////////////////////
+// This is a client side helper class allowing to hide some of the tedious
+// boilerplate.
+struct partition : hpx::components::client_base
+{
+ typedef hpx::components::client_base base_type;
+
+ partition() {}
+
+ // Create new component on locality 'where' and initialize the held data
+ partition(hpx::id_type where, std::size_t size, double initial_value)
+ : base_type(hpx::new_(where, size, initial_value))
+ {
+ }
+
+ // Create a new component on the locality co-located to the id 'where'. The
+ // new instance will be initialized from the given partition_data.
+ partition(hpx::id_type where, partition_data const& data)
+ : base_type(hpx::new_(hpx::colocated(where), data))
+ {
+ }
+
+ // Attach a future representing a (possibly remote) partition.
+ partition(hpx::future&& id)
+ : base_type(std::move(id))
+ {
+ }
+
+ // Unwrap a future (a partition already holds a future to the
+ // id of the referenced object, thus unwrapping accesses this inner future).
+ partition(hpx::future&& c)
+ : base_type(std::move(c))
+ {
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Invoke the (remote) member function which gives us access to the data.
+ // This is a pure helper function hiding the async.
+ hpx::future get_data(
+ partition_server::partition_type t) const
+ {
+ partition_server::get_data_action act;
+ return hpx::async(act, get_id(), t);
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+struct stepper
+{
+ // Our data for one time step
+ typedef std::vector space;
+
+ // Our operator
+ static double heat(double left, double middle, double right)
+ {
+ return middle + (k * dt / (dx * dx)) * (left - 2 * middle + right);
+ }
+
+ //[stepper_7
+ // The partitioned operator, it invokes the heat operator above on all elements
+ // of a partition.
+ static partition heat_part(
+ partition const& left, partition const& middle, partition const& right)
+ {
+ using hpx::dataflow;
+ using hpx::unwrapping;
+
+ hpx::shared_future middle_data =
+ middle.get_data(partition_server::middle_partition);
+
+ hpx::future next_middle = middle_data.then(
+ unwrapping([middle](partition_data const& m) -> partition_data {
+ HPX_UNUSED(middle);
+
+ // All local operations are performed once the middle data of
+ // the previous time step becomes available.
+ std::size_t size = m.size();
+ partition_data next(size);
+ for (std::size_t i = 1; i != size - 1; ++i)
+ next[i] = heat(m[i - 1], m[i], m[i + 1]);
+ return next;
+ }));
+
+ return dataflow(hpx::launch::async,
+ unwrapping([left, middle, right](partition_data next,
+ partition_data const& l, partition_data const& m,
+ partition_data const& r) -> partition {
+ HPX_UNUSED(left);
+ HPX_UNUSED(right);
+
+ // Calculate the missing boundary elements once the
+ // corresponding data has become available.
+ std::size_t size = m.size();
+ next[0] = heat(l[size - 1], m[0], m[1]);
+ next[size - 1] = heat(m[size - 2], m[size - 1], r[0]);
+
+ // The new partition_data will be allocated on the same locality
+ // as 'middle'.
+ return partition(middle.get_id(), std::move(next));
+ }),
+ std::move(next_middle),
+ left.get_data(partition_server::left_partition), middle_data,
+ right.get_data(partition_server::right_partition));
+ }
+ //]
+
+ // do all the work on 'np' partitions, 'nx' data points each, for 'nt'
+ // time steps
+ space do_work(std::size_t np, std::size_t nx, std::size_t nt);
+};
+
+// Global functions can be exposed as actions as well. That allows to invoke
+// those remotely. The macro HPX_PLAIN_ACTION() defines a new action type
+// 'heat_part_action' which wraps the global function heat_part(). It can be
+// used to call that function on a given locality.
+HPX_PLAIN_ACTION(stepper::heat_part, heat_part_action)
+
+///////////////////////////////////////////////////////////////////////////////
+// do all the work on 'np' partitions, 'nx' data points each, for 'nt'
+// time steps
+stepper::space stepper::do_work(std::size_t np, std::size_t nx, std::size_t nt)
+{
+ using hpx::dataflow;
+
+ std::vector localities = hpx::find_all_localities();
+ std::size_t nl = localities.size(); // Number of localities
+
+ // U[t][i] is the state of position i at time t.
+ std::vector U(2);
+ for (space& s : U)
+ s.resize(np);
+
+ // Initial conditions: f(0, i) = i
+ for (std::size_t i = 0; i != np; ++i)
+ U[0][i] = partition(localities[locidx(i, np, nl)], nx, double(i));
+
+ // limit depth of dependency tree
+ std::size_t nd = 3;
+ auto sem = std::make_shared(nd);
+
+ heat_part_action act;
+ for (std::size_t t = 0; t != nt; ++t)
+ {
+ space const& current = U[t % 2];
+ space& next = U[(t + 1) % 2];
+
+ for (std::size_t i = 0; i != np; ++i)
+ {
+ // we execute the action on the locality of the middle partition
+ auto Op = hpx::bind_front(act, localities[locidx(i, np, nl)]);
+ next[i] = dataflow(hpx::launch::async, Op, current[idx(i, -1, np)],
+ current[i], current[idx(i, +1, np)]);
+ }
+
+ if ((t % nd) == 0)
+ {
+ next[0].then([sem, t](partition&&) {
+ // inform semaphore about new lower limit
+ sem->signal(t);
+ });
+ }
+
+ // suspend if the tree has become too deep, the continuation above
+ // will resume this thread once the computation has caught up
+ sem->wait(t);
+ }
+
+ // Return the solution at time-step 'nt'.
+ return U[nt % 2];
+}
+
+///////////////////////////////////////////////////////////////////////////////
+int hpx_main(hpx::program_options::variables_map& vm)
+{
+ std::uint64_t np = vm["np"].as(); // Number of partitions.
+ std::uint64_t nx =
+ vm["nx"].as(); // Number of grid points.
+ std::uint64_t nt = vm["nt"].as(); // Number of steps.
+
+ std::vector localities = hpx::find_all_localities();
+ std::size_t nl = localities.size(); // Number of localities
+
+ if (vm.count("no-header"))
+ header = false;
+
+ if (np < nl)
+ {
+ std::cout << "The number of partitions should not be smaller than "
+ "the number of localities"
+ << std::endl;
+ return hpx::finalize();
+ }
+
+ // Create the stepper object
+ stepper step;
+
+ // Measure execution time.
+ std::uint64_t t = hpx::chrono::high_resolution_clock::now();
+
+ // Execute nt time steps on nx grid points and print the final solution.
+ stepper::space solution = step.do_work(np, nx, nt);
+ for (std::size_t i = 0; i != np; ++i)
+ solution[i].get_data(partition_server::middle_partition).wait();
+
+ std::uint64_t elapsed = hpx::chrono::high_resolution_clock::now() - t;
+
+ // Print the final solution
+ if (vm.count("results"))
+ {
+ for (std::size_t i = 0; i != np; ++i)
+ {
+ std::cout << "U[" << i << "] = "
+ << solution[i]
+ .get_data(partition_server::middle_partition)
+ .get()
+ << std::endl;
+ }
+ }
+ std::uint64_t const num_worker_threads = hpx::get_num_worker_threads();
+ hpx::future locs = hpx::get_num_localities();
+ print_time_results(
+ locs.get(), num_worker_threads, elapsed, nx, np, nt, header);
+
+ return hpx::finalize();
+}
+
+int main(int argc, char* argv[])
+{
+ using namespace hpx::program_options;
+
+ options_description desc_commandline;
+ desc_commandline.add_options()(
+ "results", "print generated results (default: false)")("nx",
+ value()->default_value(10),
+ "Local x dimension (of each partition)")("nt",
+ value()->default_value(45),
+ "Number of time steps")("np", value()->default_value(10),
+ "Number of partitions")("k", value(&k)->default_value(0.5),
+ "Heat transfer coefficient (default: 0.5)")("dt",
+ value(&dt)->default_value(1.0),
+ "Timestep unit (default: 1.0[s])")(
+ "dx", value(&dx)->default_value(1.0), "Local x dimension")(
+ "no-header", "do not print out the csv header row");
+
+ // Initialize and run HPX
+ hpx::init_params init_args;
+ init_args.desc_cmdline = desc_commandline;
+
+ return hpx::init(argc, argv, init_args);
+}
+#endif
diff --git a/branches/master/singlehtml/_downloads/9d22d8dc6c30a217f9d1d12aa2654138/custom_serialization.cpp b/branches/master/singlehtml/_downloads/9d22d8dc6c30a217f9d1d12aa2654138/custom_serialization.cpp
new file mode 100644
index 00000000000..02253df59d3
--- /dev/null
+++ b/branches/master/singlehtml/_downloads/9d22d8dc6c30a217f9d1d12aa2654138/custom_serialization.cpp
@@ -0,0 +1,218 @@
+// Copyright (c) 2022 John Sorial
+//
+// SPDX-License-Identifier: BSL-1.0
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// This example is meant for inclusion in the documentation.
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+//[point_member_serialization
+struct point_member_serialization
+{
+ int x{0};
+ int y{0};
+
+ // Required when defining the serialization function as private
+ // In this case it isn't
+ // Provides serialization access to HPX
+ friend class hpx::serialization::access;
+
+ // Second argument exists solely for compatibility with boost serialize
+ // it is NOT processed by HPX in any way.
+ template
+ void serialize(Archive& ar, const unsigned int)
+ {
+ // clang-format off
+ ar & x & y;
+ // clang-format on
+ }
+};
+
+// Allow bitwise serialization
+HPX_IS_BITWISE_SERIALIZABLE(point_member_serialization)
+//]
+
+//[rectangle_member_serialization
+struct rectangle_member_serialization
+{
+ point_member_serialization top_left;
+ point_member_serialization lower_right;
+
+ template
+ void serialize(Archive& ar, const unsigned int)
+ {
+ // clang-format off
+ ar & top_left & lower_right;
+ // clang-format on
+ }
+};
+//]
+
+//[rectangle_free
+struct rectangle_free
+{
+ point_member_serialization top_left;
+ point_member_serialization lower_right;
+};
+
+template
+void serialize(Archive& ar, rectangle_free& pt, const unsigned int)
+{
+ // clang-format off
+ ar & pt.lower_right & pt.top_left;
+ // clang-format on
+}
+//]
+
+//[point_class
+class point_class
+{
+public:
+ point_class(int x, int y)
+ : x(x)
+ , y(y)
+ {
+ }
+
+ point_class() = default;
+
+ [[nodiscard]] int get_x() const noexcept
+ {
+ return x;
+ }
+
+ [[nodiscard]] int get_y() const noexcept
+ {
+ return y;
+ }
+
+private:
+ int x;
+ int y;
+};
+
+template
+void load(Archive& ar, point_class& pt, const unsigned int)
+{
+ int x, y;
+ ar >> x >> y;
+ pt = point_class(x, y);
+}
+
+template
+void save(Archive& ar, point_class const& pt, const unsigned int)
+{
+ ar << pt.get_x() << pt.get_y();
+}
+
+// This tells HPX that you have spilt your serialize function into
+// load and save
+HPX_SERIALIZATION_SPLIT_FREE(point_class)
+//]
+
+//[SendRectangle
+void send_rectangle_struct(rectangle_free rectangle)
+{
+ hpx::util::format_to(std::cout,
+ "Rectangle(Point(x={1},y={2}),Point(x={3},y={4}))\n",
+ rectangle.top_left.x, rectangle.top_left.y, rectangle.lower_right.x,
+ rectangle.lower_right.y);
+}
+//]
+
+HPX_PLAIN_ACTION(send_rectangle_struct)
+
+//[planet_weight_calculator
+class planet_weight_calculator
+{
+public:
+ explicit planet_weight_calculator(double g)
+ : g(g)
+ {
+ }
+
+ template
+ friend void save_construct_data(
+ Archive&, planet_weight_calculator const*, unsigned int);
+
+ [[nodiscard]] double get_g() const
+ {
+ return g;
+ }
+
+private:
+ // Provides serialization access to HPX
+ friend class hpx::serialization::access;
+ template
+ void serialize(Archive&, const unsigned int)
+ {
+ // Serialization will be done in the save_construct_data
+ // Still needs to be defined
+ }
+
+ double g;
+};
+//]
+
+//[save_construct_data
+template