Page MenuHomec4science

No OneTemporary

File Metadata

Created
Sun, Jan 12, 06:50
diff --git a/include/GooseFEM/Iterate.h b/include/GooseFEM/Iterate.h
index f2e97ff..83bce05 100644
--- a/include/GooseFEM/Iterate.h
+++ b/include/GooseFEM/Iterate.h
@@ -1,66 +1,80 @@
/**
Support function for iterations.
\file Iterate.h
\copyright Copyright 2017. Tom de Geus. All rights reserved.
\license This project is released under the GNU Public License (GPLv3).
*/
#ifndef GOOSEFEM_ITERATE_H
#define GOOSEFEM_ITERATE_H
#include "config.h"
namespace GooseFEM {
/**
Support function for iterations in end-user programs.
*/
namespace Iterate {
/**
Class to perform a residual check based on the last "n" iterations.
A typical usage is in dynamic simulations where equilibrium is checked based on a force residual.
Fluctuations could however be responsible for this criterion to be triggered too early.
By checking several time-steps such case can be avoided.
*/
class StopList {
public:
/**
Constructor.
\param n Number of consecutive iterations to consider.
*/
StopList(size_t n = 1);
/**
Reset all residuals to infinity.
*/
void reset();
/**
Reset all residuals to infinity, and change the number of residuals to check.
\param n Number of consecutive iterations to consider.
*/
void reset(size_t n);
/**
Update list of residuals, return `true` if all residuals are below the tolerance.
+ \param res Current residual.
+ \param tol Tolerance below which all last "n" iterations must lie.
+ */
+ bool stop_simple(double res, double tol);
+
+ /**
+ Update list of residuals, return `true` if all residuals are below the tolerance,
+ and all residuals are in a descending order.
+
\param res Current residual.
\param tol Tolerance below which all last "n" iterations must lie.
*/
bool stop(double res, double tol);
+ /**
+ Get the historic residuals.
+ */
+ auto get() const;
+
private:
std::vector<double> m_res; ///< List with residuals.
};
} // namespace Iterate
} // namespace GooseFEM
#include "Iterate.hpp"
#endif
diff --git a/include/GooseFEM/Iterate.hpp b/include/GooseFEM/Iterate.hpp
index 11c9e11..e8c9645 100644
--- a/include/GooseFEM/Iterate.hpp
+++ b/include/GooseFEM/Iterate.hpp
@@ -1,47 +1,59 @@
/**
Implementation of Iterate.h
\file Iterate.hpp
\copyright Copyright 2017. Tom de Geus. All rights reserved.
\license This project is released under the GNU Public License (GPLv3).
*/
#ifndef GOOSEFEM_ITERATE_HPP
#define GOOSEFEM_ITERATE_HPP
#include "Iterate.h"
namespace GooseFEM {
namespace Iterate {
inline StopList::StopList(size_t n)
{
m_res.resize(n);
reset();
}
inline void StopList::reset()
{
std::fill(m_res.begin(), m_res.end(), std::numeric_limits<double>::infinity());
}
inline void StopList::reset(size_t n)
{
m_res.resize(n);
reset();
}
+inline bool StopList::stop_simple(double res, double tol)
+{
+ std::rotate(m_res.begin(), m_res.begin() + 1, m_res.end());
+ m_res.back() = res;
+ return !std::any_of(m_res.cbegin(), m_res.cend(), [=](const auto& i) { return i >= tol; });
+}
+
inline bool StopList::stop(double res, double tol)
{
std::rotate(m_res.begin(), m_res.begin() + 1, m_res.end());
m_res.back() = res;
if (res > tol) {
return false;
}
- return std::is_sorted(m_res.begin(), m_res.end(), std::greater_equal<double>()) && m_res.front() <= tol;
+ return std::is_sorted(m_res.cbegin(), m_res.cend(), std::greater_equal<double>()) && m_res.front() <= tol;
+}
+
+inline auto StopList::get() const
+{
+ return m_res;
}
} // namespace Iterate
} // namespace GooseFEM
#endif
diff --git a/python/Iterate.hpp b/python/Iterate.hpp
index c886c22..a846d2b 100644
--- a/python/Iterate.hpp
+++ b/python/Iterate.hpp
@@ -1,39 +1,52 @@
/**
\file
\copyright Copyright 2017. Tom de Geus. All rights reserved.
\license This project is released under the GNU Public License (GPLv3).
*/
#ifndef PYGOOSEFEM_ITERATE_H
#define PYGOOSEFEM_ITERATE_H
#include <GooseFEM/Iterate.h>
#include <pybind11/pybind11.h>
+#include <pybind11/stl.h>
namespace py = pybind11;
void init_Iterate(py::module& mod)
{
py::class_<GooseFEM::Iterate::StopList> cls(mod, "Iterate");
cls.def(py::init<size_t>(),
"Class to perform a residual check based on the last 'n' iterations."
"See :cpp:class:`GooseFEM::Iterate::StopList`.",
py::arg("n") = 1);
cls.def("reset",
py::overload_cast<>(&GooseFEM::Iterate::StopList::reset),
"Reset."
"See :cpp:func:`GooseFEM::Iterate::StopList::reset`.");
+ cls.def("stop_simple",
+ &GooseFEM::Iterate::StopList::stop_simple,
+ "Update list of residuals, return `true` if all residuals are below the tolerance."
+ "See :cpp:func:`GooseFEM::Iterate::StopList::stop_simple`.",
+ py::arg("res"),
+ py::arg("tol"));
+
cls.def("stop",
&GooseFEM::Iterate::StopList::stop,
- "Update list of residuals, return `true` if all residuals are below the tolerance."
+ "Update list of residuals, return `true` if all residuals are sorted and below the tolerance."
"See :cpp:func:`GooseFEM::Iterate::StopList::stop`.",
py::arg("res"),
py::arg("tol"));
+ cls.def("get",
+ &GooseFEM::Iterate::StopList::get,
+ "Get the list of residuals."
+ "See :cpp:func:`GooseFEM::Iterate::StopList::get`.");
+
cls.def("__repr__", [](const GooseFEM::Iterate::StopList&) { return "<GooseFEM.Iterate.StopList>"; });
}
#endif
diff --git a/test/basic/Iterate.cpp b/test/basic/Iterate.cpp
index db6f797..c746172 100644
--- a/test/basic/Iterate.cpp
+++ b/test/basic/Iterate.cpp
@@ -1,38 +1,63 @@
#include <catch2/catch.hpp>
#include <xtensor/xrandom.hpp>
#include <xtensor/xmath.hpp>
#include <Eigen/Eigen>
#include <GooseFEM/GooseFEM.h>
#define ISCLOSE(a,b) REQUIRE_THAT((a), Catch::WithinAbs((b), 1.e-12));
TEST_CASE("GooseFEM::Iterate", "Iterate.h")
{
+ SECTION("StopList::stop_simple - sorted input")
+ {
+ GooseFEM::Iterate::StopList stop(5);
+
+ std::vector<double> res = {5e+0, 5e+1, 5e-1, 5e-2, 5e-3, 5e-4, 4e-4, 3e-4, 2e-4, 1e-4};
+ std::vector<bool> conv = {false, false, false, false, false, false, false, false, false, true};
+
+ for (size_t i = 0; i < res.size(); ++i) {
+ REQUIRE(stop.stop_simple(res[i], 1e-3) == conv[i]);
+ }
+
+ std::vector<double> m_res = { 0.05 , 0.005 , 0.0005, 0.0004, 0.0005};
+ }
+
+ SECTION("StopList::stop_simple - unsorted input")
+ {
+ GooseFEM::Iterate::StopList a(5);
+ GooseFEM::Iterate::StopList b(5);
+
+ std::vector<double> res = {5e+0, 5e+1, 5e-1, 5e-2, 5e-3, 5e-4, 4e-4, 5e-4, 4e-4, 4e-4};
+ std::vector<bool> conv = {false, false, false, false, false, false, false, false, false, true};
+
+ for (size_t i = 0; i < res.size(); ++i) {
+ REQUIRE(a.stop_simple(res[i], 1e-3) == conv[i]);
+ REQUIRE(b.stop(res[i], 1e-3) == false);
+ }
+ }
- SECTION("StopList - sorted input")
+ SECTION("StopList::stop - sorted input")
{
GooseFEM::Iterate::StopList stop(5);
- // x x x x x v v v v v
std::vector<double> res = {5e+0, 5e+1, 5e-1, 5e-2, 5e-3, 5e-4, 4e-4, 3e-4, 2e-4, 1e-4};
std::vector<bool> conv = {false, false, false, false, false, false, false, false, false, true};
for (size_t i = 0; i < res.size(); ++i) {
REQUIRE(stop.stop(res[i], 1e-3) == conv[i]);
}
}
- SECTION("StopList - unsorted input")
+ SECTION("StopList::stop - unsorted input")
{
GooseFEM::Iterate::StopList stop(5);
- // x x x x x v v v v x v v v v
std::vector<double> res = {5e+0, 5e+1, 5e-1, 5e-2, 5e-3, 5e-4, 4e-4, 3e-4, 2e-4, 3e-4, 2e-4, 1e-4, 9e-5, 8e-5};
std::vector<bool> conv = {false, false, false, false, false, false, false, false, false, false, false, false, false, true};
for (size_t i = 0; i < res.size(); ++i) {
REQUIRE(stop.stop(res[i], 1e-3) == conv[i]);
}
}
}

Event Timeline