Skip to content
Commits on Source (27)
......@@ -66,7 +66,7 @@ done
for module in typetree pdelab
do
eval SETUP_dune_${module}_BRANCH=\"support/dune-copasi-latest\"
eval SETUP_dune_${module}_BRANCH=\"support/dune-copasi-v1.1.0\"
eval SETUP_dune_${module}_REPO=\"https://gitlab.dune-project.org/copasi/dune-${module}.git\"
done
......
......@@ -46,7 +46,7 @@ if [[ ! "$OS_TARGET" =~ ^(linux|osx|win32|win64)$ ]]; then
fi
echo "Downloading static libs for OS_TARGET: ${OS_TARGET}"
DEPS_URL="https://github.com/spatial-model-editor/sme_deps_common/releases/latest/download/sme_deps_common_${OS_TARGET}.tgz"
DEPS_URL="https://github.com/spatial-model-editor/sme_deps_common/releases/download/2021.04.15/sme_deps_common_${OS_TARGET}.tgz"
if command -v wget &> /dev/null; then
wget -nv $DEPS_URL | sed 's/^/ /'
elif command -v curl &> /dev/null; then
......
......@@ -15,7 +15,7 @@ stages:
.global_variables: &global_variables
DUNECONTROL: dunecontrol
BASE_IMAGE_VERSION: v1.0.0
BASE_IMAGE_VERSION: v1.1.0
DUNE_COPASI_SD_EXECUTABLE: 'ON'
CPACK_GENERATORS: 'DEB'
CPACK_PACKAGE_DIRECTORY: $CI_PROJECT_DIR/tmp
......
......@@ -27,6 +27,25 @@ Types of changes
-->
## [Unreleased] ([git-diff][Unreleased-diff])
## [1.1.0] ([git-diff][1.1.0-diff]) - 2021-04-29
### Added
- Dune options file receives `CMAKE_OPTIONS` and `MAKE_OPTIONS` !60
- Parameter to use max norm on newton steps !65
- Parameter to accept best solution in linear search on newton steps !65
- Event timestepper !64
- Preprocessor macros containing version information !67
### Changed
- TIFF helper is compiled in the dunecopasi library !62
- Use `NewtonMethod` instead of `Newton` class from PDELab !65
### Fixed
- Executables can be compiled without the library !60
- All dune cmake flags are now transitively passed to dune-copasi targets !60
- System tests on main executables were ignored !66
- Snap to final time now avoids very small timesteps !61
- CMake config file was installed on the wrong path !68
## [1.0.0] ([git-diff][1.0.0-diff]) - 2021-02-11
### Added
- Custom membrane flux !30
- Skip intersection methods in local operators !36
......@@ -35,7 +54,7 @@ Types of changes
- Provide help message when executables are not used correctly !49
- Produce Debian Packages on the CI !49
- Installation is now divided on three components: `Runtime|Library|Development` !49
- Define a recommended dune options file (`dune-copasi.opts`)[dune-copasi.opts] !49
- Define a recommended dune options file [`dune-copasi.opts`](dune-copasi.opts) !49
- Versioned documentation !49
- Dependency on `pkg-config` !52
### Changed
......@@ -117,12 +136,16 @@ Types of changes
- [Semantic Versioning](https://semver.org/spec/v2.0.0.html)
- Solver for reaction-diffusion systems in multiple compartments.
[Unreleased-diff]: https://gitlab.dune-project.org/copasi/dune-copasi/compare/v0.3.0...master
[Unreleased-diff]: https://gitlab.dune-project.org/copasi/dune-copasi/compare/v1.1.0...master
[1.1.0-diff]: https://gitlab.dune-project.org/copasi/dune-copasi/compare/v1.0.0...v1.1.0
[1.0.0-diff]: https://gitlab.dune-project.org/copasi/dune-copasi/compare/v0.3.0...v1.0.0
[0.3.0-diff]: https://gitlab.dune-project.org/copasi/dune-copasi/compare/v0.2.0...v0.3.0
[0.2.0-diff]: https://gitlab.dune-project.org/copasi/dune-copasi/compare/v0.1.0...v0.2.0
[Unreleased]: https://gitlab.dune-project.org/copasi/dune-copasi/-/tree/master
[1.1.0]: https://gitlab.dune-project.org/copasi/dune-copasi/-/releases/v1.1.0
[1.0.0]: https://gitlab.dune-project.org/copasi/dune-copasi/-/releases/v1.0.0
[0.3.0]: https://gitlab.dune-project.org/copasi/dune-copasi/-/releases/v0.3.0
[0.2.0]: https://gitlab.dune-project.org/copasi/dune-copasi/-/releases/v0.2.0
[0.1.0]: https://gitlab.dune-project.org/copasi/dune-copasi/-/releases/v0.1.0
......@@ -46,8 +46,7 @@ dune_project()
add_subdirectory(cmake/modules)
# find specific dune-copasi dependencies
find_package(PkgConfig REQUIRED)
pkg_search_module(muparser REQUIRED IMPORTED_TARGET muparser)
find_package(muparser REQUIRED)
find_package(TIFF REQUIRED)
find_package(Filesystem)
......@@ -84,13 +83,19 @@ endif()
# create a target to gather all dependencies
add_library(dune-copasi-deps INTERFACE)
target_link_libraries(dune-copasi-deps INTERFACE ${DUNE_LIBS} TIFF::TIFF PkgConfig::muparser)
target_compile_definitions(dune-copasi-deps INTERFACE ENABLE_UG=1 UG_USE_NEW_DIMENSION_DEFINES)
target_link_libraries(dune-copasi-deps INTERFACE muparser::muparser ${DUNE_LIBS})
# add missing definition from muparser pkg-config file
if(NOT ${BUILD_SHARED_LIBS})
target_compile_definitions(dune-copasi-deps INTERFACE MUPARSER_STATIC)
endif()
# get properties defined by dune macros
get_property(all_incs GLOBAL PROPERTY ALL_PKG_INCS)
get_property(all_defs GLOBAL PROPERTY ALL_PKG_DEFS)
get_property(all_opts GLOBAL PROPERTY ALL_PKG_OPTS)
get_property(all_libs GLOBAL PROPERTY ALL_PKG_LIBS)
# ...apply them to the dependency target
target_include_directories(dune-copasi-deps INTERFACE ${all_incs})
target_compile_definitions(dune-copasi-deps INTERFACE ${all_defs})
target_compile_options(dune-copasi-deps INTERFACE ${all_opts})
target_link_libraries(dune-copasi-deps INTERFACE ${all_libs})
# Set up filesystem. Where do we get it from?
if(DUNE_USE_FALLBACK_FILESYSTEM)
......@@ -102,14 +107,21 @@ else()
target_link_libraries(dune-copasi-deps INTERFACE std::filesystem)
endif()
########## Create main liabrary ##########
########## Create main targets ##########
# create main library
# create main library target
add_library(dune-copasi)
set_target_properties(dune-copasi PROPERTIES LIBRARY_OUTPUT_NAME dunecopasi)
set_target_properties(dune-copasi PROPERTIES ARCHIVE_OUTPUT_NAME dunecopasi)
target_link_libraries(dune-copasi PUBLIC dune-copasi-deps)
dune_target_enable_all_packages(dune-copasi)
target_link_libraries(dune-copasi PUBLIC dune-copasi-deps PRIVATE TIFF::TIFF)
# create executable targets
if(DUNE_COPASI_SD_EXECUTABLE)
add_executable(singledomain-exec)
endif()
if(DUNE_COPASI_MD_EXECUTABLE)
add_executable(multidomain-exec)
endif()
########## Include other scripts ##########
......@@ -129,9 +141,6 @@ add_subdirectory(doc)
finalize_dune_project(GENERATE_CONFIG_H_CMAKE)
target_compile_definitions(dune-copasi INTERFACE HAVE_DUNE_COPASI_CONFIG_H)
# main library is completely set up, define a read only alias for our main target
add_library(dune-copasi::dune-copasi ALIAS dune-copasi)
# install generated config in build and install directories
file(COPY "${CMAKE_CURRENT_BINARY_DIR}/config.h"
DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/dune/copasi"
......@@ -155,19 +164,21 @@ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/dune/copasi/FC.h"
# taget configuration for downstream projects
install(TARGETS dune-copasi-deps dune-copasi
EXPORT dune-copasi-targets
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
LIBRARY DESTINATION "${DUNE_INSTALL_LIBDIR}"
COMPONENT Libraries
NAMELINK_COMPONENT Development
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
ARCHIVE DESTINATION "${DUNE_INSTALL_LIBDIR}"
COMPONENT Development
)
# export targets to be used with installed tree
install(EXPORT dune-copasi-targets
FILE dune-copasi-targets.cmake
NAMESPACE dune-copasi::
COMPONENT Development
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/dune-copasi"
DESTINATION "${DUNE_INSTALL_LIBDIR}/cmake/dune-copasi"
)
# export targets to be used with build tree
......@@ -176,6 +187,15 @@ export(EXPORT dune-copasi-targets
NAMESPACE dune-copasi::
)
# create read-only targets
add_library(dune-copasi::dune-copasi ALIAS dune-copasi)
if(TARGET singledomain-exec)
add_executable(dune-copasi::singledomain-exec ALIAS singledomain-exec)
endif()
if(TARGET multidomain-exec)
add_executable(dune-copasi::multidomain-exec ALIAS multidomain-exec)
endif()
# include tests as a sub project
include(CTest)
if(BUILD_TESTING)
......
......@@ -2,5 +2,6 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}")
install(FILES
FindFilesystem.cmake
Findmuparser.cmake
COMPONENT Development
DESTINATION ${DUNE_INSTALL_MODULEDIR})
# Find the muparser library
#
# Usage:
# find_package(muparser [REQUIRED] [QUIET] )
#
# It sets the following variables:
# muparser_FOUND ... true if muparser is found on the system
# muparser_LIBRARIES ... full path to muparser library
# muparser_INCLUDES ... muparser include directory
#
# It defines the following targets:
# muparser::muparser ... muparser library to link against
#
find_path(muparser_INCLUDE_DIR muParserDef.h)
find_library(muparser_LIBRARY muparser)
mark_as_advanced(muparser_INCLUDE_DIR muparser_LIBRARY)
file(
STRINGS
"${muparser_INCLUDE_DIR}/muParserDef.h"
muparser_version_str
REGEX "^#define MUP_VERSION _T.*")
string(
REGEX
REPLACE "^#define MUP_VERSION _T..(.*).."
"\\1"
muparser_VERSION_STRING
"${muparser_version_str}")
unset(muparser_version_str)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(
muparser
REQUIRED_VARS muparser_LIBRARY muparser_INCLUDE_DIR
VERSION_VAR muparser_VERSION_STRING)
if(muparser_FOUND
AND NOT
TARGET
muparser::muparser)
add_library(
muparser::muparser
UNKNOWN
IMPORTED)
set_target_properties(
muparser::muparser
PROPERTIES IMPORTED_LOCATION ${muparser_LIBRARY}
INTERFACE_INCLUDE_DIRECTORIES ${muparser_INCLUDE_DIR})
set(muparser_test_path "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/CMakeTmp/muparser_test.cc")
set(muparser_test_source
"#include<muParser.h>
int main() {
mu::Parser p;
p.DefineConst(\"pi\", 3.14);
p.SetExpr(\"pi\");
p.Eval();
}")
file(WRITE "${muparser_test_path}" "${muparser_test_source}")
try_compile(COMPILE_RESULT_DYNAMIC "${CMAKE_CURRENT_BINARY_DIR}"
SOURCES "${muparser_test_path}"
LINK_LIBRARIES muparser::muparser)
if(NOT COMPILE_RESULT_DYNAMIC)
file(WRITE "${muparser_test_path}" "${muparser_test_source}")
try_compile(COMPILE_RESULT_STATIC "${CMAKE_CURRENT_BINARY_DIR}"
SOURCES "${muparser_test_path}"
COMPILE_DEFINITIONS -DMUPARSER_STATIC
LINK_LIBRARIES muparser::muparser)
if(NOT COMPILE_RESULT_STATIC)
message(FATAL_ERROR "A simple muparser test program could not be successfuly compiled")
endif()
set_target_properties(
muparser::muparser
PROPERTIES INTERFACE_COMPILE_DEFINITIONS MUPARSER_STATIC)
endif()
endif()
......@@ -55,8 +55,7 @@ if(NOT dune-copasi_FOUND)
# make sure to find cmake modules for dune-copasi
list(APPEND CMAKE_MODULE_PATH "${dune-copasi_MODULE_PATH}")
find_dependency(PkgConfig REQUIRED)
pkg_search_module(muparser REQUIRED IMPORTED_TARGET muparser)
find_dependency(muparser)
find_dependency(TIFF)
if(@DUNE_USE_FALLBACK_FILESYSTEM@)
find_dependency(ghc_filesystem REQUIRED)
......
......@@ -28,17 +28,18 @@
/* end private */
/* Define to the version of dune-copasi */
#define Udune_copasi_VERSION "@Udune_copasi_VERSION@"
#define DUNE_COPASI_VERSION "@DUNE_COPASI_VERSION@"
/* Define to the major version of dune-copasi */
#define Udune_copasi_VERSION_MAJOR @Udune_copasi_VERSION_MAJOR@
#define DUNE_COPASI_VERSION_MAJOR @DUNE_COPASI_VERSION_MAJOR@
/* Define to the minor version of dune-copasi */
#define Udune_copasi_VERSION_MINOR @Udune_copasi_VERSION_MINOR@
#define DUNE_COPASI_VERSION_MINOR @DUNE_COPASI_VERSION_MINOR@
/* Define to the revision of dune-copasi */
#define Udune_copasi_VERSION_REVISION @Udune_copasi_VERSION_REVISION@
#define DUNE_COPASI_VERSION_REVISION @DUNE_COPASI_VERSION_REVISION@
/* end dune-copasi
Everything below here will be overwritten
......
......@@ -32,5 +32,5 @@ The GUI is able to read and modify non-spatial SBML models into 2D spatial
models and simulate them with `dune-copasi`. A big adventage of this package is
that is tailored specifically for biologists and is availalbe with just a pair
of clicks on the major plataforms.
[Check it out](https://spatial-model-editor.readthedocs.io/en/latest/quickstart/get-started.html)!
[Check it out](https://spatial-model-editor.readthedocs.io/en/stable/quickstart/get-started.html)!
......@@ -23,9 +23,9 @@ spatial *Systems Biology Markup Language* ([SBML](https://en.wikipedia.org/wiki/
models of bio-chemical reactions. Additionally, it can simulate them with `dune-copasi`. A big
adventage of this package is that is tailored for biologists and is availalbe
with just a pair of clicks on the major plataforms. Find more information
[here](https://spatial-model-editor.readthedocs.io/en/latest/quickstart/get-started.html)!
[here](https://spatial-model-editor.readthedocs.io/en/stable/quickstart/get-started.html)!
[![sme](./img/spatial-model-editor.png)](https://spatial-model-editor.readthedocs.io/en/latest/quickstart/get-started.html)
[![sme](./img/spatial-model-editor.png)](https://spatial-model-editor.readthedocs.io/en/stable/quickstart/get-started.html)
### Configuration File
......@@ -99,7 +99,7 @@ nano config.ini
#### Run the program
Here, you may pull and run the latest stable container from our
Here, you may pull and run the container from our
[GitLab registry](https://gitlab.dune-project.org/copasi/dune-copasi/container_registry).
To do so, call the docker container with a configuration
file `config.ini` using one of the following commands on the terminal:
......@@ -117,7 +117,7 @@ file `config.ini` using one of the following commands on the terminal:
```bash
docker run -v $PWD \
registry.dune-project.org/copasi/dune-copasi/dune-copasi:latest\
registry.dune-project.org/copasi/dune-copasi/dune-copasi:v1.1.0\
config.ini
```
......@@ -127,7 +127,7 @@ docker run -v $PWD \
```bash
docker run -v $PWD \
--entrypoint=dune-copasi-sd \
registry.dune-project.org/copasi/dune-copasi/dune-copasi:latest\
registry.dune-project.org/copasi/dune-copasi/dune-copasi:v1.1.0\
config.ini
```
......@@ -155,7 +155,7 @@ with [INI](#configuration-file) usage, installation is as simple as:
<TabItem value="apt">
```bash
curl -fsSL https://gitlab.dune-project.org/copasi/dune-copasi/-/jobs/artifacts/latest/raw/packages/dune-copasi-runtime.deb?job=build:debian_clang -o dune-copasi-runtime.deb
curl -fsSL https://gitlab.dune-project.org/copasi/dune-copasi/-/jobs/artifacts/v1.1.0/raw/packages/dune-copasi-runtime.deb?job=build:debian_clang -o dune-copasi-runtime.deb
apt install ./dune-copasi-runtime.deb
```
......@@ -264,8 +264,8 @@ The following list of software is required to install and use `dune-copasi`:
| [dune-functions](https://gitlab.dune-project.org/staging/dune-functions) | == 2.7 |
| [dune-logging](https://gitlab.dune-project.org/staging/dune-logging) | == 2.7 |
| [dune-multidomaingrid](https://gitlab.dune-project.org/extensions/dune-multidomaingrid) | == 2.7 |
| [COPASI/dune-typetree](https://gitlab.dune-project.org/copasi/dune-typetree) | `support/dune-copasi-latest` |
| [COPASI/dune-pdelab](https://gitlab.dune-project.org/copasi/dune-pdelab) | `support/dune-copasi-latest` |
| [COPASI/dune-typetree](https://gitlab.dune-project.org/copasi/dune-typetree) | `support/dune-copasi-v1.1.0` |
| [COPASI/dune-pdelab](https://gitlab.dune-project.org/copasi/dune-pdelab) | `support/dune-copasi-v1.1.0` |
:::info
Notice that some required dune modules are forks of original reopsitories and
......@@ -369,9 +369,9 @@ git clone -b releases/2.7 https://gitlab.dune-project.org/core/dune-localfunctio
git clone -b releases/2.7 https://gitlab.dune-project.org/staging/dune-functions
git clone -b releases/2.7 https://gitlab.dune-project.org/extensions/dune-multidomaingrid
git clone -b releases/2.7 --recursive https://gitlab.dune-project.org/staging/dune-logging
git clone -b support/dune-copasi-latest https://gitlab.dune-project.org/copasi/dune-typetree
git clone -b support/dune-copasi-latest https://gitlab.dune-project.org/copasi/dune-pdelab
git clone -b latest https://gitlab.dune-project.org/copasi/dune-copasi
git clone -b support/dune-copasi-v1.1.0 https://gitlab.dune-project.org/copasi/dune-typetree
git clone -b support/dune-copasi-v1.1.0 https://gitlab.dune-project.org/copasi/dune-pdelab
git clone -b v1.1.0 https://gitlab.dune-project.org/copasi/dune-copasi
# apply patches
git apply -C dune-common dune-copasi/.ci/dune-common.patch
......@@ -393,7 +393,7 @@ export CMAKE_INSTALL_PREFIX=/opt/dune/
cd ~ && rm -r ~/dune-modules
# include dune binaries into your path
echo export PATH="$CMAKE_INSTALL_PREFIX/bin:$PATH" >> $HOME/.bashrc
echo "export PATH=${CMAKE_INSTALL_PREFIX}/bin:\$PATH" >> $HOME/.bashrc
```
For further information on dune module installation process, please check out
......
......@@ -93,6 +93,7 @@ The possible `rk_id`s can be found at the end of this document.
| Key | Type | Description |
| -----------|-----| -------------- |
| `reduction` | `float` | Threshold for termination, relative to first linear defect
| `use_max_norm` | `bool` | Use the maximum norm as a stopping criterion. This helps loosen the tolerance when solving for stationary solutions of nonlinear time-dependent problems.
| `absolute_limit` | `float` | Threshold for termination, absolute to linear defect
| `min_linear_reduction` | `float` | The linear reduction will be determined as mininum of this and the one needed to achieve second order newton convergence
| `fixed_linear_reduction` | `bool` | Whenever `true`, the linear reduction rate will always be fixed to `min_linear_reduction`
......@@ -107,8 +108,9 @@ The possible `rk_id`s can be found at the end of this document.
| Key | Type | Description |
| -----------|-----| -------------- |
| `strategy` | `string` | `noLineSearch` or `hackbuschReusken` or `hackbuschReuskenAcceptBest`
| `max_iterations` | `integer` | Maximum iterations on Hackbusch-Reusken linear search
| `damping_factor` | `float` | Damping factor for Hackbusch-Reusken linear search
| `max_iterations` | `integer` | Maximum number of line search iterations
| `damping_factor` | `float` | Multiplier to line search parameter after each iteration
| `accept_best` | `bool` | Accept the best line search parameter if there was any improvement, even if the convergence criterion was not
#### `[model.compartment]`
......
......@@ -4,7 +4,7 @@
# - Find the operating system target
# - Set default DUNE_ and CMAKE_ values, if they are not in environment
# - Any env variable starting with CMAKE_ or DUNE_ will added to the cmake flags
# - The resulting values will be prepended to the CMAKE_FLAGS env variable (if any)
# - The resulting CMAKE_FLAGS and MAKE_FLAGS values will be prepended to the CMAKE_OPTIONS and MAKE_OPTIONS env variable (if any)
# - In *nix systems, it will try to find out if installation requires sudo
#
# If run in script mode (e.g. ./dune-copasi.opts), this script will print out
......@@ -14,7 +14,7 @@
export SETUP_DUNE_TESTTOOLS=${SETUP_DUNE_TESTTOOLS:-OFF}
# get install prefix from CMAKE_FLAGS env
for flag in $CMAKE_FLAGS; do
for flag in $CMAKE_OPTIONS; do
[[ ${flag#-D} == CMAKE_INSTALL_PREFIX* ]] && CMAKE_INSTALL_PREFIX=${flag#-DCMAKE_INSTALL_PREFIX}
done
# remove "=" or ":PATH=" prefix
......@@ -67,16 +67,16 @@ export CMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS:-"'-fvisibility=hidden -fpic'"}
export CMAKE_CXX_FLAGS_RELEASE=${CMAKE_CXX_FLAGS_RELEASE:-"'-O3'"}
export CMAKE_CXX_FLAGS_RELWITHDEBINFO=${CMAKE_CXX_FLAGS_RELWITHDEBINFO:-"'-O2 -g3 -DNDEBUG -fno-omit-frame-pointer'"}
export CMAKE_CXX_FLAGS_DEBUG=${CMAKE_CXX_FLAGS_DEBUG:-"'-O0 -g'"}
export CMAKE_DISABLE_FIND_PACKAGE_MPI=${CMAKE_DISABLE_FIND_PACKAGE_MPI:-ON}
export CMAKE_DISABLE_FIND_PACKAGE_MPI=${CMAKE_DISABLE_FIND_PACKAGE_MPI:-OFF}
if [[ "$DUNE_COPASI_USE_STATIC_DEPS" =~ ^(ON|on|ON|TRUE|true|1)$ ]];then
CMAKE_FLAGS+=" -DGMPXX_INCLUDE_DIR:PATH='"${CMAKE_INSTALL_PREFIX}"/include'"
CMAKE_FLAGS+=" -DGMPXX_LIB:FILEPATH='"${CMAKE_INSTALL_PREFIX}"/lib/libgmpxx.a'"
CMAKE_FLAGS+=" -DGMP_LIB:FILEPATH='"${CMAKE_INSTALL_PREFIX}"/lib/libgmp.a'"
CMAKE_FLAGS+=" -Dfmt_ROOT='"${CMAKE_INSTALL_PREFIX}"'"
CMAKE_FLAGS+=" -DCMAKE_DISABLE_FIND_PACKAGE_QuadMath=TRUE"
CMAKE_FLAGS+=" -DF77=true"
CMAKE_FLAGS+=" -DBUILD_SHARED_LIBS=OFF"
CMAKE_OPTIONS+=" -DGMPXX_INCLUDE_DIR:PATH='"${CMAKE_INSTALL_PREFIX}"/include'"
CMAKE_OPTIONS+=" -DGMPXX_LIB:FILEPATH='"${CMAKE_INSTALL_PREFIX}"/lib/libgmpxx.a'"
CMAKE_OPTIONS+=" -DGMP_LIB:FILEPATH='"${CMAKE_INSTALL_PREFIX}"/lib/libgmp.a'"
CMAKE_OPTIONS+=" -Dfmt_ROOT='"${CMAKE_INSTALL_PREFIX}"'"
CMAKE_OPTIONS+=" -DCMAKE_DISABLE_FIND_PACKAGE_QuadMath=TRUE"
CMAKE_OPTIONS+=" -DF77=true"
CMAKE_OPTIONS+=" -DBUILD_SHARED_LIBS=OFF"
DUNE_VENDOR_FMT='OFF'
export DUNE_USE_ONLY_STATIC_LIBS='ON'
fi
......@@ -91,14 +91,13 @@ export DUNE_COPASI_MD_EXECUTABLE=${DUNE_COPASI_MD_EXECUTABLE:-ON}
# default make flags
if [[ "$CMAKE_BUILD_TYPE" == "Debug" ]]; then
MAKE_FLAGS=${MAKE_FLAGS:-"-j1 VERBOSE=1"}
else
MAKE_FLAGS=${MAKE_FLAGS:-"-j1"}
MAKE_FLAGS="VERBOSE=1"
fi
# get environment variables (excluding CMAKE_FLAGS and DUNE_CONTROL_PATH)
# get environment variables (excluding CMAKE_FLAGS, CMAKE_OPTIONS, and DUNE_CONTROL_PATH)
ENV_VARS=$(compgen -e)
ENV_VARS=${ENV_VARS//CMAKE_FLAGS/}
ENV_VARS=${ENV_VARS//CMAKE_OPTIONS/}
ENV_VARS=${ENV_VARS//DUNE_CONTROL_PATH/}
_CMAKE_FLAGS=""
......@@ -113,7 +112,8 @@ for var in $ENV_VARS; do
done
# final flags
CMAKE_FLAGS="$_CMAKE_FLAGS $_DUNE_FLAGS $CMAKE_FLAGS"
CMAKE_FLAGS="$_CMAKE_FLAGS $_DUNE_FLAGS $CMAKE_OPTIONS"
MAKE_FLAGS="$MAKE_OPTIONS $MAKE_FLAGS"
# if called in script mode, print cmake flags and os target
if [[ $(basename $0) == dune-copasi.opts ]] ; then
......
......@@ -4,7 +4,7 @@
#Name of the module
Module: dune-copasi
Version: 0.4.0-git
Version: 1.1.0
Maintainer: santiago.ospina@iwr.uni-heidelberg.de
#depending on
Depends: dune-logging dune-uggrid (>= 2.7) dune-pdelab (>= 2.7) dune-multidomaingrid (>= 2.7)
......
......@@ -6,6 +6,7 @@ install(FILES bit_flags.hh
muparser_data_handler.hh
pdelab_expression_adapter.hh
stepper.hh
tiff_file.hh
tiff_grayscale.hh
COMPONENT Development
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/dune/copasi/common")
......@@ -5,7 +5,7 @@
#include <dune/pdelab/backend/istl.hh>
#include <dune/pdelab/instationary/onestep.hh>
#include <dune/pdelab/newton/newton.hh>
#include <dune/pdelab/solver/newton.hh>
#include <dune/logging.hh>
......@@ -111,10 +111,12 @@ public:
bool snap_to_end_time = true) const
{
const auto& logger = asImpl().logger();
logger.notice("Evolving system: {:.2f}s -> {:.2f}s"_fmt, in.time, end_time);
logger.notice("Evolving system: {:.2e}s -> {:.2e}s"_fmt, in.time, end_time);
out = in;
auto prev_out = in;
while (FloatCmp::le<double>(out.time+dt, end_time)) {
// if snap to end time, stop loop 2 dt before final time, otherwise 1 dt
double stop_dt = snap_to_end_time ? 2. : 1.;
while (FloatCmp::le<Time>(out.time+stop_dt*dt, end_time)) {
std::swap(prev_out, out);
asImpl().do_step(system, prev_out, out, dt);
if (not out) {
......@@ -167,19 +169,19 @@ public:
/**
* @brief Snap the output to a specific time
* @details This method is used to advance very small timesteps with a very
* basic adaptivity algorithm. It differs from evolve in that the steps
* might be done with a more suitable stepper for wide range of timesteps.
* @details This method is used to advance towards a snap_time
* avoiding very small timesteps. It work best if the snap time is a couple
* of timesteps ahead of the suggested dt. It differs from evolve in that the
* steps might be done with a suitable stepper for wider range of timesteps.
*
* @tparam System System that contain suitable operators to advance in time
* @tparam Time Valid time type to operate with
* @param system System that contain suitable operators to advance in time.
* If the step is not possible, the system stays with its initial state
* @param dt Delta time to perform first step. If the step is not
* possible, stepper may modify it to a suitable value
* @param dt Suggested delta time to to reach snap time. It will be
* modified to reach snap time exactly.
* @param snap_time Final time that `out` state must reach
* @param callable A function called with an state at the end of each
* succesful step
* succesful step
*/
template<class System, class State, class Time, class Callable>
void snap_to_time(System& system,
......@@ -212,24 +214,23 @@ protected:
{
auto& logger = stepper.logger();
logger.info(2, "Snapping current time to {:.2f}"_fmt, snap_time);
logger.info(2, "Snapping current time to {:.5e}"_fmt, snap_time);
// enough iterations to explore 4 orders of magnitude
std::size_t max_it = 15, it = 0;
// let's avoid getting into an infinite loop
// If max_it is reached something is wrong
std::size_t max_it = 100, it = 0;
// reduce last timestep adaptively until time is exactly reached
out = in;
auto prev_out = in;
while (FloatCmp::lt<double>(out.time, snap_time)) {
if (max_it == it++) {
DUNE_THROW(RangeError,
"Snapping time exceeded maximum interation count");
return;
}
auto new_dt = std::min(dt, snap_time - out.time);
logger.detail(2, "Snapping step size {:.2f}s -> {:.2f}s"_fmt, dt, new_dt);
while (FloatCmp::lt<Time>(out.time, snap_time)) {
// find number of time steps to fit in the (out.time,snap_time) range
int timesteps_until_end = std::ceil((snap_time - out.time) / dt);
if (timesteps_until_end <= 0)
DUNE_THROW(MathError,
"Timestep doesn't make advances towards snap step");
Time new_dt = (snap_time - out.time) / timesteps_until_end;
logger.detail(2, "Snapping step size {:.5e}s -> {:.5e}s"_fmt, dt, new_dt);
dt = new_dt;
std::swap(prev_out, out);
......@@ -237,13 +238,15 @@ protected:
if (out) {
callable(out);
logger.detail(
2, "Increasing step size: {:.2f}s -> {:.2f}s"_fmt, dt, dt * 1.5);
dt *= 1.5;
} else {
out = prev_out;
if (max_it == it++) {
DUNE_THROW(RangeError,
"Snapping time exceeded maximum interation count");
return;
}
logger.detail(
2, "Reducing step size: {:.2f}s -> {:.2f}s"_fmt, dt, dt * 0.5);
2, "Reducing step size: {:.5e}s -> {:.5e}s"_fmt, dt, dt * 0.5);
dt *= 0.5;
}
}
......@@ -352,7 +355,7 @@ public:
Dune::Logging::Logging::redirectCout(_logger.name(),
Dune::Logging::LogLevel::detail);
_logger.detail("Trying step: {:.2f}s + {:.2f}s -> {:.2f}s"_fmt,
_logger.detail("Trying step: {:.2e}s + {:.2e}s -> {:.2e}s"_fmt,
in.time,
dt,
in.time + dt);
......@@ -369,7 +372,7 @@ public:
solver.apply(in.time, dt, *x_in, *x_out);
solver.result(); // triggers an exception if solver failed
_logger.notice("Time Step: {:.2f}s + {:.2f}s -> {:.2f}s"_fmt,
_logger.notice("Time Step: {:.2e}s + {:.2e}s -> {:.2e}s"_fmt,
in.time,
dt,
in.time + dt);
......@@ -379,6 +382,14 @@ public:
out.coefficients.reset(); // set output to an invalid state
_logger.warn(2, "Step failed (NewtonError)"_fmt);
_logger.trace("{}"_fmt, e.what());
} catch (const Dune::PDELab::TerminateError& e) {
out.coefficients.reset(); // set output to an invalid state
_logger.warn(2, "Step failed (NewtonError::TerminateError)"_fmt);
_logger.trace("{}"_fmt, e.what());
} catch (const Dune::PDELab::LineSearchError& e) {
out.coefficients.reset(); // set output to an invalid state
_logger.warn(2, "Step failed (NewtonError::LineSearchError)"_fmt);
_logger.trace("{}"_fmt, e.what());
} catch (const Dune::MathError& e) {
out.coefficients.reset(); // set output to an invalid state
_logger.warn(2, "Step failed (MathError)"_fmt);
......@@ -401,7 +412,7 @@ private:
using InstationaryGridOperator = typename System::InstationaryGridOperator;
using LinearSolver = Dune::PDELab::ISTLBackend_NOVLP_BCGS_SSORk<InstationaryGridOperator>;
using NonLinearOperator =
PDELab::Newton<InstationaryGridOperator, LinearSolver, Coefficients>;
PDELab::NewtonMethod<InstationaryGridOperator, LinearSolver>;
using OneStepOperator = PDELab::
OneStepMethod<Time, InstationaryGridOperator, NonLinearOperator, Coefficients>;
......@@ -429,52 +440,7 @@ private:
std::make_unique<NonLinearOperator>(grid_operator, *linear_solver);
// Add settings to the newton solver
auto reduction = _solver_parameters.template get<double>("reduction");
non_linear_operator->setReduction(reduction);
auto min_reduction =
_solver_parameters.template get<double>("min_linear_reduction");
non_linear_operator->setMinLinearReduction(min_reduction);
auto fixed_reduction =
_solver_parameters.template get<bool>("fixed_linear_reduction");
non_linear_operator->setFixedLinearReduction(fixed_reduction);
auto max_it = _solver_parameters.template get<unsigned int>("max_iterations");
non_linear_operator->setMaxIterations(max_it);
auto abs_limit = _solver_parameters.template get<double>("absolute_limit");
non_linear_operator->setAbsoluteLimit(abs_limit);
auto reassemble =
_solver_parameters.template get<double>("reassemble_threshold");
non_linear_operator->setReassembleThreshold(reassemble);
auto keep_matrix = _solver_parameters.template get<bool>("keep_matrix");
non_linear_operator->setKeepMatrix(keep_matrix);
auto force_iteration =
_solver_parameters.template get<bool>("force_iteration");
non_linear_operator->setForceIteration(force_iteration);
const auto& ls = _solver_parameters.sub("linear_search", true);
auto ls_strategy = ls.template get<std::string>("strategy");
try {
non_linear_operator->setLineSearchStrategy(ls_strategy);
} catch (const Dune::Exception& e) {
_logger.error("Not valid linear search strategy: {}"_fmt, ls_strategy);
DUNE_THROW(IOError, "Not valid linear search strategy: " << ls_strategy);
}
if (ls_strategy != "noLineSearch")
{
auto ls_max_it = ls.template get<unsigned int>("max_iterations");
non_linear_operator->setLineSearchMaxIterations(ls_max_it);
auto ls_damping = ls.template get<double>("damping_factor");
non_linear_operator->setLineSearchDampingFactor(ls_damping);
}
non_linear_operator->setParameters(_solver_parameters);
_logger.trace("Get one step operator"_fmt);
auto one_step_operator = std::make_unique<OneStepOperator>(
......@@ -505,7 +471,7 @@ private:
* until step is successful or minimum time step is reached. When step is
* successful, delta time is increased up to a maximum value
*
* @tparam SimpleStepper Stepper that does not addapt its delta time on failure
* @tparam SimpleStepper Stepper that does not adapt its delta time on failure
*/
template<class SimpleStepper>
class SimpleAdaptiveStepper
......@@ -568,7 +534,7 @@ public:
_stepper.do_step(system, in, out, dt);
while (not out) {
logger().detail(2,
"Reducing step size: {:.2f}s -> {:.2f}s"_fmt, dt, dt * _decrease_factor);
"Reducing step size: {:.2e}s -> {:.2e}s"_fmt, dt, dt * _decrease_factor);
dt = dt * _decrease_factor;
if (FloatCmp::lt<Time>(dt, _min_step))
DUNE_THROW(MathError,
......@@ -580,10 +546,11 @@ public:
auto new_step = std::min<Time>(_max_step, dt * _increase_factor);
logger().detail(2,
"Increasing step size: {:.2f}s -> {:.2f}s"_fmt, dt, new_step);
"Increasing step size: {:.2e}s -> {:.2e}s"_fmt, dt, new_step);
dt = new_step;
}
/**
* @copydoc BaseStepper::snap_to_time()
* @details This class overloads the default implementation in oder to make
......@@ -598,7 +565,8 @@ public:
const Time& time,
Callable&& callable) const
{
Base::snap_to_time(_stepper, system, in, out, dt, time, callable);
// use snap_to_time on the wrapped stepper
_stepper.snap_to_time(system, in, out, dt, time, callable);
}
//! Return stepper logger
......@@ -610,6 +578,91 @@ private:
const double _decrease_factor, _increase_factor;
};
/**
* @brief Adapt an stepper into an event time stepper
*
* @details For a given predicate, this stepper finds the moment (or event)
* in time when the predicate changes its result. If the predicate
* does not change, it simply applyies the do_step of the underlying
* stepper.
*
* @tparam Stepper Underlying stepper that will advance the system on time
* @tparam Predicate Functor that accepts system states and signals event
* changes
*/
template<class Stepper, class Predicate>
class EventStepper : public BaseStepper<EventStepper<Stepper, Predicate>>
{
using Base = BaseStepper<EventStepper<Stepper, Predicate>>;
public:
using Time = typename Stepper::Time;
EventStepper(Stepper&& stepper,
Predicate&& predicate,
double threshold = 1e-4,
std::size_t max_it = 20)
: _stepper(std::move(stepper))
, _predicate(std::move(predicate))
, _threshold(threshold)
, _max_it(max_it)
{}
/**
* @copydoc BaseStepper::do_step()
*
* @param out Output state where result will be placed. If step is not
* possible, out is guaranteed to be false when casted to bool. If the
* predicate signals an event change, out will hold the change before the
* event
*/
template<class System, class State>
void do_step(const System& system,
const State& in,
State& out,
Time& dt) const
{
std::size_t it = _max_it;
_stepper.do_step(system, in, out, dt);
if (not out)
return;
// let's make an binary search of the approiated time step
Time start = 0.;
Time end = dt;
const bool pre_in = _predicate(in);
bool pre_out = _predicate(std::as_const(out));
State test_out = out;
while ((pre_in != pre_out) and (0 != it--) and
((end - start) / dt > _threshold)) {
Time test = start + (end - start) / 2.;
_stepper.do_step(system, in, test_out, test);
bool pre_out = _predicate(std::as_const(test_out));
if (pre_in == pre_out) {
out = test_out;
start = test;
} else {
end = test;
}
}
}
//! Return stepper logger
const Logging::Logger& logger() const { return _stepper.logger(); }
private:
const Stepper _stepper;
Predicate _predicate;
const double _threshold;
const std::size_t _max_it;
};
/**
* @brief Make a default adaptive simple stepper
*
* @tparam Time type of time
* @param config Configuration file for the time stepping scheme
* @return auto An stepper
*/
template<class Time = double>
auto
make_default_stepper(const ParameterTree& config)
......@@ -625,10 +678,26 @@ make_default_stepper(const ParameterTree& config)
log.trace("Decrease factor: {}"_fmt,decrease_factor);
log.trace("Runge-Kutta method: {}"_fmt,rk_type);
const auto& np = config.sub("newton", true);
// make parameters compatible with dune-copasi 1.0
ParameterTree param;
param["Reduction"] = np["reduction"];
param["UseMaxNorm"] = np.get("use_max_norm", "false");
param["MinLinearReduction"] = np["min_linear_reduction"];
param["FixedLinearReduction"] = np["fixed_linear_reduction"];
param["AbsoluteLimit"] = np["absolute_limit"];
param["ReassembleThreshold"] = np["reassemble_threshold"];
param["KeepMatrix"] = np["keep_matrix"];
param["Terminate.MaxIterations"] = np["max_iterations"];
param["Terminate.ForceIteration"] = np["force_iteration"];
param["LineSearchStrategy"] = np["linear_search.strategy"];
param["LineSearch.MaxIterations"] = np["linear_search.max_iterations"];
param["LineSearch.DampingFactor"] = np["linear_search.damping_factor"];
param["LineSearch.AcceptBest"] = np.get("linear_search.accept_best", "false");
const auto& newton_parameters = config.sub("newton", true);
using RKStepper = Dune::Copasi::RKStepper<double>;
auto rk_stepper = RKStepper{ rk_type, newton_parameters };
auto rk_stepper = RKStepper{ rk_type, param };
using Stepper = Dune::Copasi::SimpleAdaptiveStepper<RKStepper>;
return Stepper{
std::move(rk_stepper), min_step, max_step, decrease_factor, increase_factor
......
#ifndef DUNE_COPASI_TIFF_FILE_HH
#define DUNE_COPASI_TIFF_FILE_HH
#include <dune/common/exceptions.hh>
#include <dune/common/float_cmp.hh>
#include <tiffio.h>
#include <memory>
#include <string>
namespace Dune::Copasi {
/**
* @brief Simple tiff file interface
*/
struct TIFFFile
{
//! opens a tiff file from the file system
TIFFFile(const std::string& filename);
//! Destructor
~TIFFFile();
//! Closes the file
void close();
//! Allocates buffer to scan lines of the file
void* malloc_scanline() const;
//! Deallocates tiff type pointers
void free(void* ptr) const;
//! Reads one line on the buffer for a given row
void read_scanline(void* ptr, std::size_t row) const;
void* _tiff_file;
bool _zero;
short _bits_per_sample;
short _row_size;
short _col_size;
float _x_res, _x_off;
float _y_res, _y_off;
};
} // namespace Dune::Copasi
#endif // DUNE_COPASI_TIFF_FILE_HH
#ifndef DUNE_COPASI_TIFF_GRAYSCALE_HH
#define DUNE_COPASI_TIFF_GRAYSCALE_HH
#include <dune/copasi/common/tiff_file.hh>
#include <dune/common/exceptions.hh>
#include <dune/common/float_cmp.hh>
#include <tiffio.h>
#include <algorithm>
#include <memory>
#include <queue>
......@@ -41,18 +41,15 @@ class TIFFGrayscale
* @param[in] col_size The column size
* @param[in] zero Zero based grayscale?
*/
TIFFGrayscaleRow(TIFF* const tiff_file,
const T& row,
const short& col_size,
const bool& zero)
: _row(row)
, _col_size(col_size)
, _zero(zero)
TIFFGrayscaleRow(const TIFFFile& tiff,
const T& row)
: _tiff(tiff)
, _row(row)
{
T* raw_buffer = (T*)_TIFFmalloc(TIFFScanlineSize(tiff_file));
auto deleter = [](auto& ptr) { _TIFFfree(ptr); };
T* raw_buffer = (T*)_tiff.malloc_scanline();
auto deleter = [&](auto& ptr) { _tiff.free(ptr); };
_tiff_buffer = std::shared_ptr<T>(raw_buffer, deleter);
TIFFReadScanline(tiff_file, _tiff_buffer.get(), _row);
_tiff.read_scanline(_tiff_buffer.get(), _row);
}
/**
......@@ -67,10 +64,10 @@ class TIFFGrayscale
*/
double operator[](const T& col) const
{
assert((short)col < _col_size);
assert((short)col < _tiff._col_size);
const T max = std::numeric_limits<T>::max();
T val = *(_tiff_buffer.get() + col);
val = _zero ? val : max - val;
val = _tiff._zero ? val : max - val;
return (double)val / max;
}
......@@ -79,7 +76,7 @@ class TIFFGrayscale
*
* @return Number of columns in this row
*/
std::size_t size() const { return static_cast<std::size_t>(_col_size); }
std::size_t size() const { return static_cast<std::size_t>(_tiff._col_size); }
/**
* @brief The current row
......@@ -89,10 +86,9 @@ class TIFFGrayscale
std::size_t row() const { return static_cast<std::size_t>(_row); }
private:
const TIFFFile& _tiff;
std::shared_ptr<T> _tiff_buffer;
const T _row;
const short _col_size;
const bool _zero;
};
public:
......@@ -103,46 +99,17 @@ public:
* @param[in] max_cache The maximum row cache.
*/
TIFFGrayscale(const std::string& filename, std::size_t max_cache = 8)
: _tiff_file(TIFFOpen(filename.c_str(), "r"))
: _tiff{filename}
, _max_cache(max_cache)
{
if (not _tiff_file)
DUNE_THROW(IOError, "Error opening TIFF file '" << filename << "'.");
short photometric;
TIFFGetField(_tiff_file, TIFFTAG_PHOTOMETRIC, &photometric);
if ((photometric != PHOTOMETRIC_MINISWHITE) and
(photometric != PHOTOMETRIC_MINISBLACK))
DUNE_THROW(IOError,
"TIFF file '" << filename << "' must be in grayscale.");
_zero = (bool)photometric;
short bits_per_sample;
TIFFGetField(_tiff_file, TIFFTAG_BITSPERSAMPLE, &bits_per_sample);
if (bits_per_sample != 8 * sizeof(T)) {
TIFFClose(_tiff_file);
if (_tiff._bits_per_sample != 8 * sizeof(T)) {
_tiff.close();
DUNE_THROW(IOError,
"TIFF file '" << filename
<< "' contains a non-readable grayscale field.");
}
TIFFGetField(_tiff_file, TIFFTAG_IMAGELENGTH, &_row_size);
TIFFGetField(_tiff_file, TIFFTAG_IMAGEWIDTH, &_col_size);
TIFFGetField(_tiff_file, TIFFTAG_XRESOLUTION, &_x_res);
TIFFGetField(_tiff_file, TIFFTAG_YRESOLUTION, &_y_res);
assert(FloatCmp::gt(_x_res, 0.f));
assert(FloatCmp::gt(_y_res, 0.f));
_x_off = _y_off = 0.;
TIFFGetField(_tiff_file, TIFFTAG_XPOSITION, &_x_off);
TIFFGetField(_tiff_file, TIFFTAG_YPOSITION, &_y_off);
}
/**
* @brief Destroys the object.
*/
~TIFFGrayscale() { TIFFClose(_tiff_file); }
/**
* @brief Array indexer row operator.
* @warning If rows are read concurrently, this object has to be copied
......@@ -153,7 +120,7 @@ public:
*/
const TIFFGrayscaleRow& operator[](T row) const
{
assert((short)row < _row_size);
assert((short)row < _tiff._row_size);
return cache(row);
}
......@@ -174,11 +141,11 @@ public:
template<class DF>
double operator()(const DF& x, const DF& y)
{
int i = static_cast<int>(_x_res * (x - _x_off));
int j = _row_size - static_cast<int>(_y_res * (y - _y_off)) - 1;
int i = static_cast<int>(_tiff._x_res * (x - _tiff._x_off));
int j = _tiff._row_size - static_cast<int>(_tiff._y_res * (y - _tiff._y_off)) - 1;
// clamp invalid pixel indices to nearest valid pixel
i = std::clamp(i, 0, _col_size - 1);
j = std::clamp(j, 0, _row_size - 1);
i = std::clamp(i, 0, _tiff._col_size - 1);
j = std::clamp(j, 0, _tiff._row_size - 1);
return (*this)[j][i];
}
......@@ -194,14 +161,14 @@ public:
*
* @return Number of rows in this file
*/
std::size_t rows() const { return static_cast<std::size_t>(_row_size); }
std::size_t rows() const { return static_cast<std::size_t>(_tiff._row_size); }
/**
* @brief The size of cols for this file
*
* @return Number of cols in this file
*/
std::size_t cols() const { return static_cast<std::size_t>(_col_size); }
std::size_t cols() const { return static_cast<std::size_t>(_tiff._col_size); }
private:
/**
......@@ -220,7 +187,7 @@ private:
if (it != _row_cache.rend())
return *it;
else
_row_cache.emplace_back(_tiff_file, row, _col_size, _zero);
_row_cache.emplace_back(_tiff, row);
if (_row_cache.size() >= 8)
_row_cache.pop_front();
......@@ -229,16 +196,11 @@ private:
}
private:
TIFF* _tiff_file;
TIFFFile _tiff;
mutable std::deque<TIFFGrayscaleRow> _row_cache;
short _row_size;
short _col_size;
float _x_res, _x_off;
float _y_res, _y_off;
bool _zero;
const std::size_t _max_cache;
};
} // namespace Dune::Copasi
#endif // DUNE_COPASI_TIFF_GRAYSCALE_HH
\ No newline at end of file
#endif // DUNE_COPASI_TIFF_GRAYSCALE_HH
# SingleDomain objects
add_library(singledomain-lib
OBJECT
EXCLUDE_FROM_ALL
dune_copasi_sd_fv.cc
dune_copasi_sd_cg.cc
dune_copasi_sd_fv_cg.cc
)
target_link_directories(singledomain-lib PRIVATE $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>)
target_link_libraries(singledomain-lib PRIVATE dune-copasi-deps)
if(DUNE_COPASI_SD_LIBRARY)
set_target_properties(singledomain-lib PROPERTIES EXCLUDE_FROM_ALL OFF)
add_library(singledomain-lib
OBJECT
EXCLUDE_FROM_ALL
dune_copasi_sd_fv.cc
dune_copasi_sd_cg.cc
dune_copasi_sd_fv_cg.cc
)
target_include_directories(singledomain-lib PRIVATE $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>)
target_link_libraries(singledomain-lib PRIVATE dune-copasi-deps)
target_sources(dune-copasi PRIVATE $<TARGET_OBJECTS:singledomain-lib>)
target_compile_definitions(dune-copasi PUBLIC DUNE_COPASI_MD_LIBRARY)
endif()
# MultiDomain objects
add_library(multidomain-lib
OBJECT
EXCLUDE_FROM_ALL
dune_copasi_md_fv.cc
dune_copasi_md_cg.cc
dune_copasi_md_fv_cg.cc
)
target_link_directories(multidomain-lib PRIVATE $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>)
target_link_libraries(multidomain-lib PRIVATE dune-copasi-deps)
if(DUNE_COPASI_MD_LIBRARY)
set_target_properties(multidomain-lib PROPERTIES EXCLUDE_FROM_ALL OFF)
add_library(multidomain-lib
OBJECT
EXCLUDE_FROM_ALL
dune_copasi_md_fv.cc
dune_copasi_md_cg.cc
dune_copasi_md_fv_cg.cc
)
target_include_directories(multidomain-lib PRIVATE $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>)
target_link_libraries(multidomain-lib PRIVATE dune-copasi-deps)
target_sources(dune-copasi PRIVATE $<TARGET_OBJECTS:multidomain-lib>)
target_compile_definitions(dune-copasi PUBLIC DUNE_COPASI_SD_LIBRARY)
endif()
\ No newline at end of file
endif()