Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions config.cmake.in
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ if(@PCMS_ENABLE_OMEGA_H@)
endif()

include("${CMAKE_CURRENT_LIST_DIR}/pcms_utility-targets.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/pcms_transient-targets.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/pcms_discretization-targets.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/pcms_localization-targets.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/pcms_field-targets.cmake")
Expand Down
3 changes: 2 additions & 1 deletion src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ configure_file(pcms/configuration.h.in pcms/configuration.h)
list(APPEND PCMS_HEADERS ${CMAKE_CURRENT_BINARY_DIR}/pcms/version.h ${CMAKE_CURRENT_BINARY_DIR}/pcms/configuration.h)

add_subdirectory(pcms/utility)
add_subdirectory(pcms/transient)
add_subdirectory(pcms/discretization)
add_subdirectory(pcms/localization)
add_subdirectory(pcms/field)
Expand Down Expand Up @@ -87,7 +88,7 @@ install(
)

add_library(pcms_pcms INTERFACE)
target_link_libraries(pcms_pcms INTERFACE pcms::core)
target_link_libraries(pcms_pcms INTERFACE pcms::core pcms::transient)
set_target_properties(pcms_pcms PROPERTIES EXPORT_NAME pcms)
if (PCMS_ENABLE_Python)
# Disable LTO/IPO before adding Python subdirectory to avoid fatbinData conflicts
Expand Down
33 changes: 33 additions & 0 deletions src/pcms/transient/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
set(PCMS_TRANSIENT_HEADERS timestepper.hpp)
set(PCMS_TRANSIENT_SOURCES timestepper.cpp)

add_library(pcms_transient ${PCMS_TRANSIENT_SOURCES})
set_target_properties(pcms_transient PROPERTIES EXPORT_NAME transient)
add_library(pcms::transient ALIAS pcms_transient)

target_sources(
pcms_transient
PUBLIC FILE_SET transient
TYPE HEADERS
BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/..
FILES ${PCMS_TRANSIENT_HEADERS})
target_compile_features(pcms_transient PUBLIC cxx_std_20)
target_link_libraries(pcms_transient PUBLIC pcms::utility)
target_include_directories(
pcms_transient
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../..>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)

install(
TARGETS pcms_transient
EXPORT pcms_transient-targets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/pcms/transient
FILE_SET transient DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/pcms)

install(
EXPORT pcms_transient-targets
NAMESPACE pcms::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/pcms)
18 changes: 18 additions & 0 deletions src/pcms/transient/timestepper.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#include "pcms/transient/timestepper.hpp"

namespace pcms::transient
{

FixedTimestepper::FixedTimestepper(Real dt) : dt_(dt) {}

Real FixedTimestepper::InitialStep() const
{
return dt_;
}

std::pair<bool, Real> FixedTimestepper::Update(Real, Real)
{
return {true, dt_};
}

} // namespace pcms::transient
43 changes: 43 additions & 0 deletions src/pcms/transient/timestepper.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#ifndef PCMS_TRANSIENT_TIMESTEPPER_HPP
#define PCMS_TRANSIENT_TIMESTEPPER_HPP

#include "pcms/utility/types.h"
#include <utility>

namespace pcms::transient
{

// Decides whether to accept a completed time window and selects the next step.
class Timestepper
{
public:
// Return the positive step size used for the first coupling window.
[[nodiscard]] virtual Real InitialStep() const = 0;

// Given the current time step that was actually completed and its normalized
// error, return whether to accept it and the positive step size to try next.
virtual std::pair<bool, Real> Update(Real dt, Real err) = 0;

virtual ~Timestepper() = default;
};

// Always accepts and keeps a constant time step.
class FixedTimestepper : public Timestepper
{
public:
// Store the positive step size used for every window.
explicit FixedTimestepper(Real dt);

// Return the configured fixed step.
Real InitialStep() const override;

// Keep the configured fixed time step.
std::pair<bool, Real> Update(Real dt, Real err) override;

private:
Real dt_;
};

} // namespace pcms::transient

#endif // PCMS_TRANSIENT_TIMESTEPPER_HPP
5 changes: 5 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,10 @@ find_package(Catch2 3)
if(Catch2_FOUND)
message(
STATUS "Found Catch2: ${Catch2_DIR} (found version ${Catch2_VERSION})")
add_executable(test_transient_timestepper test_transient_timestepper.cpp)
target_link_libraries(test_transient_timestepper
PRIVATE Catch2::Catch2WithMain pcms::transient)

set(PCMS_UNIT_TEST_SOURCES unit_test_main.cpp test_coordinate_transform.cpp
test_coordinate.cpp test_bounding_box.cpp)
if(PCMS_ENABLE_XGC)
Expand Down Expand Up @@ -474,6 +478,7 @@ if(Catch2_FOUND)

include(Catch)
Catch_discover_tests(unit_tests)
Catch_discover_tests(test_transient_timestepper)
else()
message(WARNING "Catch2 not found. Disabling Unit Tests")
endif()
Expand Down
21 changes: 21 additions & 0 deletions test/test_transient_timestepper.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#include <catch2/catch_approx.hpp>
#include <catch2/catch_test_macros.hpp>

#include "pcms/transient/timestepper.hpp"

namespace tr = pcms::transient;

TEST_CASE("FixedTimestepper always accepts its configured step", "[transient]")
{
// 0.25 represents a positive fixed window size.
tr::FixedTimestepper timestepper(0.25);

// The completed step (0.1) and large normalized error (100).
// A fixed controller ignores both.
const auto [accepted, next_step] = timestepper.Update(0.1, 100.0);

// The first window must use the user-configured size.
REQUIRE(timestepper.InitialStep() == Catch::Approx(0.25));
REQUIRE(accepted);
REQUIRE(next_step == Catch::Approx(0.25));
}
Loading