Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F98341539
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Sun, Jan 12, 06:50
Size
8 KB
Mime Type
text/x-diff
Expires
Tue, Jan 14, 06:50 (1 d, 19 h)
Engine
blob
Format
Raw Data
Handle
23564909
Attached To
rGOOSEFEM GooseFEM
View Options
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
Log In to Comment