Skip to content
Draft
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
10 changes: 9 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,12 @@ build
TAGS

# python stuff
__pycache__
__pycache__
python/src/*.egg-info/

# build artifacts copied into the Python package by CMake
python/src/daisy/*.pyd
python/src/daisy/*.dll

# local machine-specific CMake overrides (paths, Python envs, etc.)
CMakeUserPresets.json
10 changes: 10 additions & 0 deletions .vscode/c_cpp_properties.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"configurations": [
{
"name": "MinGW",
"compileCommands": "${workspaceFolder}/build/release/compile_commands.json",
"intelliSenseMode": "gcc-x64"
}
],
"version": 4
}
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"python-envs.defaultEnvManager": "ms-python.python:system"
}
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ project(
HOMEPAGE_URL https://daisy.ku.dk/
LANGUAGES CXX C
)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
include(cmake/AddCoverageBuildType.cmake)

if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
Expand Down Expand Up @@ -94,6 +95,9 @@ endif()
# Sources are added with target_sources in CMakeLists in the source tree
add_subdirectory(src)

# Add tools for python interface
add_subdirectory(tools)

# Packaging
# lib/ and sample/ contain .dai files that define functionality that should be installed
add_subdirectory(lib)
Expand Down
18 changes: 18 additions & 0 deletions build.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
rem set PATH=C:\msys64\ucrt64\bin;C:\msys64\usr\bin;%PATH%
rem cd C:\werkmap\PHISHIS\coupling_daisy\src\daisy-7.0.7\daisy-7.0.7
rem cmake --preset mingw-gcc-native -B build/release
rem cmake --build build/release

set PATH=C:\msys64\ucrt64\bin;C:\msys64\usr\bin;%PATH%
cd c:\src\daisy

rem configure (paths defined in CMakeUserPresets.json)
cmake --preset mingw-gcc-native-local

rem build the core
cmake --build build/release --target core

rem rebuild only the .pyd target
cmake --build build/release --target daisy_bmi

pause
39 changes: 39 additions & 0 deletions build_exe.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
@echo off
:: build_exe.bat -- Configure (if needed) and build only the daisy-bin executable.
::
:: Requires MSYS2 ucrt64 installed at C:\msys64.
:: Uses the CMake preset "mingw-gcc-native-local" defined in CMakeUserPresets.json.

set CMAKE=C:\msys64\ucrt64\bin\cmake.exe
set SOURCE_DIR=%~dp0
set BUILD_DIR=%~dp0build\release

if not exist "%CMAKE%" (
echo ERROR: cmake not found at %CMAKE%
echo Please install MSYS2 and run: pacman -S mingw-w64-ucrt-x86_64-cmake
exit /b 1
)

:: MSYS2 ucrt64 must be on PATH so cmake can find ninja.exe and g++.exe
set PATH=C:\msys64\ucrt64\bin;%PATH%

:: Configure (or reconfigure) using the local preset.
:: The preset defines both source and build dirs, so just cd to the source root.
echo Configuring...
cd /d "%~dp0"
"%CMAKE%" --preset mingw-gcc-native-local
if %ERRORLEVEL% neq 0 (
echo CONFIGURE FAILED
exit /b %ERRORLEVEL%
)

echo Building daisy-bin...
"%CMAKE%" --build "%BUILD_DIR%" --target daisy-bin -j%NUMBER_OF_PROCESSORS%

if %ERRORLEVEL% neq 0 (
echo BUILD FAILED
exit /b %ERRORLEVEL%
)

echo.
echo Build succeeded: %BUILD_DIR%\daisy-bin.exe
14 changes: 14 additions & 0 deletions include/daisy/column.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,20 @@ class Column : public ModelFramed
virtual double soil_inorganic_nitrogen (double from, // [kg N/ha]
double to) const = 0;
virtual double second_year_utilization () const = 0;

// Python/BMI coupling: groundwater table and soil state arrays.
virtual double get_groundwater_table () const { return 0.0; } // [cm], neg = below surface
virtual void set_groundwater_table (double) {} // [cm]
virtual double get_bottom_flux () const { return 0.0; } // [cm/h], + = downward
virtual std::vector<double> get_flux_array () const { return {}; } // [cm/h], bottom edge of each cell
virtual std::vector<double> get_h_array () const { return {}; } // [cm], pressure head per layer
virtual std::vector<double> get_theta_array () const { return {}; } // [-], volumetric water content
virtual std::vector<double> get_theta_sat_array () const { return {}; } // [-], saturated water content
virtual double get_runoff_rate () const { return 0.0; } // [mm/day]
virtual double get_column_area () const; // [cm²]
virtual std::vector<double> get_layer_tops () const; // [cm], negative downward
virtual std::vector<double> get_layer_bottoms () const; // [cm], negative downward

// Current development stage for the crop named "crop", or
// Crop::DSremove if no such crop is present.
virtual double crop_ds (symbol crop) const = 0;
Expand Down
30 changes: 28 additions & 2 deletions include/daisy/daisy.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,15 @@ class Scope;
class Frame;
class FrameModel;

class Daisy : public Program
#ifdef __unix
#define DAISY_EXPORT /* nothing */
#elif defined (BUILD_DLL)
#define DAISY_EXPORT __declspec(dllexport)
#else
#define DAISY_EXPORT __declspec(dllimport)
#endif

class DAISY_EXPORT Daisy : public Program
{
public:
static const char *const default_description;
Expand All @@ -57,7 +65,23 @@ class Daisy : public Program
void start ();
bool is_running () const;
void stop ();


// Python/BMI coupling: forwarding to first (or pos-th) column.
double get_groundwater_table (unsigned int pos = 0u) const; // [cm]
void set_groundwater_table (double cm, unsigned int pos = 0u);
/** Hours from simulation start to the configured stop time, or -1 if open-ended. */
double stop_duration_hours() const;

double get_bottom_flux (unsigned int pos = 0u) const; // [cm/h]
std::vector<double> get_flux_array (unsigned int pos = 0u) const; // [cm/h]
std::vector<double> get_h_array (unsigned int pos = 0u) const; // [cm]
std::vector<double> get_theta_array (unsigned int pos = 0u) const; // [-]
std::vector<double> get_theta_sat_array (unsigned int pos = 0u) const; // [-]
double get_runoff_rate (unsigned int pos = 0u) const; // [mm/day]
double get_column_area (unsigned int pos = 0u) const; // [cm²]
std::vector<double> get_layer_tops (unsigned int pos = 0u) const; // [cm]
std::vector<double> get_layer_bottoms (unsigned int pos = 0u) const; // [cm]

// UI.
public:
void attach_ui (Run* run, const std::vector<Log*>& logs);
Expand All @@ -66,6 +90,8 @@ class Daisy : public Program
public:
bool run (Treelog&);
void tick (Treelog&);
void summarize (Treelog&) const;
void close_output ();
void output (Log&) const;

// Create and Destroy.
Expand Down
1 change: 1 addition & 0 deletions include/daisy/lower_boundary/groundwater.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class Groundwater : public ModelDerived
// Accessors.
public:
virtual double table () const = 0;
virtual void set_table (double) {} // [cm], default no-op (override in fixed-table models)

// Create and Destroy.
public:
Expand Down
116 changes: 116 additions & 0 deletions include/programs/bmi.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
// daisy_bmi.h -- BMI (Basic Model Interface) wrapper for Daisy
//
// Implements the BMI 2.0 standard so that Daisy can be driven by
// any BMI-aware framework.
//
// Reference: https://bmi.readthedocs.io/en/stable/

#ifndef BMI_H
#define BMI_H

#include <string>
#include <vector>
#include "programs/daisy_bmi.h"

class Daisy; // forward declaration for protected daisy() accessor

/**
* @class BMI
* @brief BMI 2.0 wrapper around DaisyBMI
*
* Variable names follow a "<category>_<quantity>" convention.
*
* Input variables (set_value):
* "groundwater__depth" [cm] - groundwater table depth
* "irrigation__rate" [mm/day]
* "land_surface__air_temperature" [degC] (if exposed by Daisy)
*
* Output variables (get_value):
* "soil_water__recharge_rate" [mm/day]
* "land_surface__evapotranspiration_rate" [mm/day]
* "groundwater__depth" [cm]
* "soil_water__transpiration_rate" [mm/day]
* "soil_water__evaporation_rate" [mm/day]
* "soil_water__drainage_rate" [mm/day]
* "soil_water__runoff_rate" [mm/day]
* "vegetation__leaf_area_index" [-]
* "vegetation__root_depth" [cm]
* "vegetation__aboveground_biomass" [g/m2]
* "soil_water__content" [m3/m3] (first layer)
*/
class BMI
{
public:
// ===== BMI LIFECYCLE =====

/** Initialize model from a .dai config file. */
void initialize(const std::string& config_file);

/** Advance model by one timestep (dt = get_time_step()). */
void update();

/** Advance model to a specific time (in days since start). */
void update_until(double time);

/** Finalize and release all resources. */
void finalize();

// ===== BMI INFORMATION =====

std::string get_component_name() const;
std::vector<std::string> get_input_var_names() const;
std::vector<std::string> get_output_var_names() const;

// ===== BMI TIME =====

double get_start_time() const; // always 0.0
double get_end_time() const; // NaN = open-ended
double get_current_time() const; // days since simulation start
double get_time_step() const; // in days (e.g. 1/24 = hourly)
std::string get_time_units() const; // "d"

// ===== BMI VARIABLE INFO =====

std::string get_var_type(const std::string& name) const; // "double"
std::string get_var_units(const std::string& name) const;
int get_var_itemsize(const std::string& name) const; // sizeof(double)
int get_var_nbytes(const std::string& name) const; // 1 * sizeof(double)
std::string get_var_location(const std::string& name) const; // "none" (scalar)
int get_var_grid(const std::string& name) const; // 0 (single-cell)

// ===== BMI GRID INFO (single-cell, scalar grid) =====

int get_grid_rank(int grid) const; // 0
int get_grid_size(int grid) const; // 1
std::string get_grid_type(int grid) const; // "scalar"

// ===== BMI GET/SET =====

/** Get scalar output value by variable name into dest[0]. */
void get_value(const std::string& name, double* dest) const;

/** Set scalar input value by variable name from src[0]. */
void set_value(const std::string& name, const double* src);

// ===== CONSTRUCTOR / DESTRUCTOR =====
BMI();
~BMI();

private:
DaisyBMI ctrl_;
double start_time_days_; // always 0
double current_time_days_; // updated each update()
double dt_days_; // timestep size in days

static const std::vector<std::string> INPUT_VARS;
static const std::vector<std::string> OUTPUT_VARS;

double get_output_value(const std::string& name) const;

protected:
/** Direct access to the Daisy simulation object for use by DaisyAPI
* extension methods. Same Daisy& that DaisyBMI uses internally. */
Daisy& daisy ();
};

#endif // DAISY_BMI_H
Loading