Skip to content

Commit

Permalink
More modular integrators and added to ChaiEngine
Browse files Browse the repository at this point in the history
New integrators:
- Heun
- RK3
- NCRK4

Added threading tools to ChaiEngine

Add const qualifier to Sampler's operator()()
  • Loading branch information
stephenberry committed Nov 21, 2019
1 parent 725b137 commit 3c5fdc3
Show file tree
Hide file tree
Showing 6 changed files with 418 additions and 28 deletions.
63 changes: 36 additions & 27 deletions include/ascent/ChaiEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#pragma once

#include "ascent/Ascent.h"
#include "ascent/threading/Pool.h"
#include "chaiscript/chaiscript.hpp"
#include "chaiscript/chaiscript_stdlib.hpp"

Expand Down Expand Up @@ -57,49 +58,57 @@ namespace asc

ChaiEngine()
{
add(chaiscript::vector_conversion<state_t>());
add(chaiscript::vector_conversion<std::vector<std::string>>());
add(chaiscript::bootstrap::standard_library::vector_type<state_t>("state_t"));
using namespace chaiscript;

add(vector_conversion<state_t>());
add(vector_conversion<std::vector<std::string>>());
add(bootstrap::standard_library::vector_type<state_t>("state_t"));

scriptRecorder<asc::value_t>(*this, "Recorder");
add(chaiscript::fun([](RecorderT<asc::value_t>& rec, int& x) { rec.record(x); }), "record");
add(chaiscript::fun([](RecorderT<asc::value_t>& rec, size_t& x) { rec.record(x); }), "record");
add(chaiscript::fun([](RecorderT<asc::value_t>& rec, int& x, const std::string& title) { rec.record(x, title); }), "record");
add(chaiscript::fun([](RecorderT<asc::value_t>& rec, size_t& x, const std::string& title) { rec.record(x, title); }), "record");
add(fun([](RecorderT<asc::value_t>& rec, int& x) { rec.record(x); }), "record");
add(fun([](RecorderT<asc::value_t>& rec, size_t& x) { rec.record(x); }), "record");
add(fun([](RecorderT<asc::value_t>& rec, int& x, const std::string& title) { rec.record(x, title); }), "record");
add(fun([](RecorderT<asc::value_t>& rec, size_t& x, const std::string& title) { rec.record(x, title); }), "record");

// This allows for more generic mixing of various data types, all they need is to be converted to a string prior to being passed into the recorder
// The RecorderString is primarily for data that is going to be output to a file and not operated on during the simulation
scriptRecorder<std::string>(*this, "RecorderString");

add(chaiscript::user_type<asc::Param>(), "Param");
add(chaiscript::constructor<asc::Param(state_t&)>(), "Param");
add(chaiscript::constructor<asc::Param(state_t&, const value_t)>(), "Param");
add(chaiscript::fun([](asc::Param& param, const value_t y) { return param = y; }), "=");
add(chaiscript::fun([](asc::Param& param) { std::cout << param << '\n'; }), "print");
add(chaiscript::fun([](asc::Param& param) { return static_cast<value_t>(param); }), "value");
add(user_type<asc::Param>(), "Param");
add(constructor<asc::Param(state_t&)>(), "Param");
add(constructor<asc::Param(state_t&, const value_t)>(), "Param");
add(fun([](asc::Param& param, const value_t y) { return param = y; }), "=");
add(fun([](asc::Param& param) { std::cout << param << '\n'; }), "print");
add(fun([](asc::Param& param) { return static_cast<value_t>(param); }), "value");

add(chaiscript::user_type<ParamV>(), "ParamV");
add(chaiscript::constructor<ParamV(state_t&, const size_t)>(), "ParamV");
add(chaiscript::fun([](ParamV& lhs, const std::vector<asc::value_t>& rhs) { return lhs = rhs; }), "=");
add(chaiscript::fun([](ParamV& v) { v.zero(); }), "zero");
add(user_type<ParamV>(), "ParamV");
add(constructor<ParamV(state_t&, const size_t)>(), "ParamV");
add(fun([](ParamV& lhs, const std::vector<asc::value_t>& rhs) { return lhs = rhs; }), "=");
add(fun([](ParamV& v) { v.zero(); }), "zero");

add(chaiscript::user_type<Sampler>(), "Sampler");
add(chaiscript::constructor<Sampler(asc::value_t&, asc::value_t&)>(), "Sampler");
add(chaiscript::fun(&Sampler::operator()), "eval");
add(chaiscript::fun(&Sampler::event), "event");
add(chaiscript::fun(&Sampler::reset), "reset");
add(user_type<Sampler>(), "Sampler");
add(constructor<Sampler(asc::value_t&, asc::value_t&)>(), "Sampler");
add(fun(&Sampler::operator()), "eval");
add(fun(&Sampler::event), "event");
add(fun(&Sampler::reset), "reset");

// System
add(chaiscript::user_type<System>(), "System");
add(chaiscript::constructor<System()>(), "System");
add(chaiscript::fun([](System& sys, const asc::state_t& x, asc::state_t& D, const asc::value_t t) { sys(x, D, t); }), "eval");
add(chaiscript::type_conversion<System&, asc::system_t>());
add(chaiscript::fun([](System& sys, const system_t& func) { sys.push_back(func); }), "push_back");
add(user_type<System>(), "System");
add(constructor<System()>(), "System");
add(fun([](System& sys, const asc::state_t& x, asc::state_t& D, const asc::value_t t) { sys(x, D, t); }), "eval");
add(type_conversion<System&, asc::system_t>());
add(fun([](System& sys, const system_t& func) { sys.push_back(func); }), "push_back");

// Integrators
integrator<Euler>("ascEuler");
integrator<RK2>("RK2");
integrator<RK4>("RK4");

// threading
Queue::script(*this, "Queue");
Pool::script(*this, "Pool");
add(fun([] { return std::thread::hardware_concurrency(); }), "hardware_concurrency");
add(fun([](asc::Recorder& rec, const int sig_digits) { rec.precision = sig_digits; }), "precision");
}
ChaiEngine(const ChaiEngine&) = default;
ChaiEngine(ChaiEngine&&) = default;
Expand Down
114 changes: 114 additions & 0 deletions include/ascent/integrators_modular/Heun.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// Copyright (c) 2016-2019 Anyar, Inc.
//
// 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.

#pragma once

#include "ascent/modular/Module.h"
#include "ascent/integrators_modular/ModularIntegrators.h"

// Heun's Method

namespace asc
{
namespace modular
{
template <class value_t>
struct Heunprop : public Propagator<value_t>
{
void operator()(State& state, const value_t dt) override
{
auto& x = *state.x;
auto& xd = *state.xd;
state.memory.resize(2);
auto& x0 = state.memory[0];
auto& xd0 = state.memory[1];

switch (Propagator<value_t>::pass)
{
case 0:
x0 = x;
xd0 = xd; //k1
x = x0 + dt * xd;
break;
case 1:
x = x0 + dt * 0.5 * ( xd0 + xd );
break;
}
}
};

template <class value_t>
struct Heunstepper : public TimeStepper<value_t>
{
value_t t0{};

void operator()(const size_t pass, value_t& t, const value_t dt) override
{
switch (pass)
{
case 0:
t0 = t;
t += dt;
break;
case 1:
t = t0 + dt;
break;
default:
break;
}
}
};

template <typename value_t>
struct Heun
{
Heunprop<value_t> propagator;
Heunstepper<value_t> stepper;

template <typename modules_t>
void operator()(modules_t& modules, value_t& t, const value_t dt)
{
auto& pass = propagator.pass;
pass = 0;

update(modules);
propagate(modules, dt);
stepper(pass, t, dt);
++pass;

update(modules);
propagate(modules, dt);
stepper(pass, t, dt);
}

template <class modules_t>
void update(modules_t& modules)
{
for (auto& module : modules)
{
(*module)();
}
}

template <class modules_t>
void propagate(modules_t& modules, const value_t dt)
{
for (auto& module : modules)
{
module->propagate(propagator, dt);
}
}
};
}
}
137 changes: 137 additions & 0 deletions include/ascent/integrators_modular/NCRK4.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
// Copyright (c) 2016-2019 Anyar, Inc.
//
// 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.

#pragma once

#include "ascent/modular/Module.h"
#include "ascent/integrators_modular/ModularIntegrators.h"

// Non-confluent RK4 method ( "3/8th's Rule" )

namespace asc
{
namespace modular
{
template <class value_t>
struct NCRK4prop : public Propagator<value_t>
{
void operator()(State& state, const value_t dt) override
{
auto& x = *state.x;
auto& xd = *state.xd;
state.memory.resize(5);
auto& x0 = state.memory[0];
auto& xd0 = state.memory[1];
auto& xd1 = state.memory[2];
auto& xd2 = state.memory[3];
auto& xd3 = state.memory[4];

switch (Propagator<value_t>::pass)
{
case 0:
x0 = x;
xd0 = xd; // k1
x = x0 + (1.0/3.0) * dt * xd0;
break;
case 1:
xd1 = xd; // k2
x = x0 + dt * ( (-1.0/3.0) * xd0 + xd1) ;
break;
case 2:
xd2 = xd; // k3
x = x0 + dt * ( xd0 - xd1 + xd2);
break;
case 3:
xd3 = xd; // k4
x = x0 + dt / 8.0 * (xd0 + 3.0 * xd1 + 3.0 * xd2 + xd3);
break;
}
}
};

template <class value_t>
struct NCRK4stepper : public TimeStepper<value_t>
{
value_t t0{};

void operator()(const size_t pass, value_t& t, const value_t dt) override
{
switch (pass)
{
case 0:
t0 = t;
t += 1.0/3.0 * dt;
break;
case 1:
t = t0 + 2.0/3.0 * dt;
break;
case 2:
t = t0 + dt;
break;
default:
break;
}
}
};

template <class value_t>
struct NCRK4
{
NCRK4prop<value_t> propagator;
NCRK4stepper<value_t> stepper;

template <class modules_t>
void operator()(modules_t& modules, value_t& t, const value_t dt)
{
auto& pass = propagator.pass;
pass = 0;

update(modules);
propagate(modules, dt);
stepper(pass, t, dt);
++pass;

update(modules);
propagate(modules, dt);
++pass;

update(modules);
propagate(modules, dt);
stepper(pass, t, dt);
++pass;

update(modules);
propagate(modules, dt);
}

template <class modules_t>
void update(modules_t& modules)
{
for (auto& module : modules)
{
(*module)();
}
}

template <class modules_t>
void propagate(modules_t& modules, const value_t dt)
{
for (auto& module : modules)
{
module->propagate(propagator, dt);
}
}
};
}
}
Loading

0 comments on commit 3c5fdc3

Please sign in to comment.