Skip to content

Commit

Permalink
Merge pull request #23 from SeisSol/lua
Browse files Browse the repository at this point in the history
Add Lua support
  • Loading branch information
krenzland authored Feb 9, 2022
2 parents 90c982a + 27a3131 commit 39c2508
Show file tree
Hide file tree
Showing 9 changed files with 261 additions and 7 deletions.
34 changes: 27 additions & 7 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
project(easi)
cmake_minimum_required(VERSION 3.13)
set(EASI_VERSION_MAJOR 1)
set(EASI_VERSION_MINOR 0)
set(EASI_VERSION_PATCH 1)

set(EASI_VERSION_MINOR 1)
set(EASI_VERSION_PATCH 0)

include(GNUInstallDirs)
include(CMakePackageConfigHelpers)
Expand All @@ -18,6 +17,8 @@ set(IMPALAJIT_BACKEND original CACHE STRING "Which backend to use")
set(IMPALAJIT_BACKEND_OPTIONS original llvm)
set_property(CACHE IMPALAJIT_BACKEND PROPERTY STRINGS ${IMPALAJIT_BACKEND_OPTIONS})

option(LUA "Use Lua" OFF)

function(check_parameter parameter_name value options)

list(FIND options ${value} INDEX)
Expand All @@ -30,7 +31,7 @@ function(check_parameter parameter_name value options)
endfunction()
check_parameter("IMPALAJIT_BACKEND" "${IMPALAJIT_BACKEND}" "${IMPALAJIT_BACKEND_OPTIONS}")

### external packages ###
### external packages ###

find_package(yaml-cpp 0.6 REQUIRED)
find_package(OpenMP)
Expand All @@ -43,6 +44,10 @@ if(IMPALAJIT)
endif()
endif()

if (LUA)
find_package(Lua REQUIRED)
endif()

if(ASAGI)
find_package (PkgConfig REQUIRED)
find_package (HDF5 REQUIRED COMPONENTS C HL)
Expand All @@ -60,6 +65,7 @@ set(EASI_SOURCES
src/component/DomainFilter.cpp
src/component/EvalModel.cpp
src/component/FunctionMap.cpp
src/component/LuaMap.cpp
src/component/LayeredModelBuilder.cpp
src/component/OptimalStress.cpp
src/component/PolynomialMap.cpp
Expand Down Expand Up @@ -94,6 +100,7 @@ target_link_libraries(easi
if(${OpenMP_CXX_FOUND})
target_link_libraries(easi PRIVATE OpenMP::OpenMP_CXX)
endif()

if(ASAGI)
find_package(MPI REQUIRED)
target_link_libraries(easi
Expand All @@ -103,18 +110,25 @@ if(ASAGI)
PkgConfig::NETCDF
)
target_link_libraries(easi
PRIVATE
PUBLIC
MPI::MPI_CXX
)
target_compile_definitions(easi PRIVATE -DEASI_USE_ASAGI)
target_compile_definitions(easi PRIVATE EASI_USE_ASAGI)
endif()

if (IMPALAJIT)
if (IMPALAJIT_BACKEND STREQUAL "llvm")
target_link_libraries(easi PRIVATE llvm::impalajit)
else()
target_link_libraries(easi PRIVATE impalajit::impalajit)
endif()
target_compile_definitions(easi PRIVATE -DEASI_USE_IMPALAJIT)
target_compile_definitions(easi PRIVATE EASI_USE_IMPALAJIT)
endif()

if (LUA)
target_include_directories(easi PRIVATE ${LUA_INCLUDE_DIR})
target_link_libraries(easi PRIVATE ${LUA_LIBRARIES})
target_compile_definitions(easi PRIVATE EASI_USE_LUA)
endif()

target_include_directories(easi
Expand Down Expand Up @@ -215,3 +229,9 @@ if(ASAGI)
easi_add_test(101_asagi_nearest)
endif ()

if (LUA)
easi_add_test(4_lua)
endif()



5 changes: 5 additions & 0 deletions cmake/easiConfig.cmake.in
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
@PACKAGE_INIT@
set(EASI_IMPALAJIT_BACKEND @IMPALAJIT_BACKEND@)
set(EASI_IMPALAJIT @IMPALAJIT@)
set(EASI_LUA @LUA@)
set(EASI_ASAGI @ASAGI@)

include(CMakeFindDependencyMacro)
Expand All @@ -16,6 +17,10 @@ if (EASI_IMPALAJIT)
endif()
endif()

if (EASI_LUA)
find_package(Lua REQUIRED)
endif()

if (EASI_ASAGI)
find_dependency(PkgConfig)
pkg_check_modules(ASAGI REQUIRED IMPORTED_TARGET asagi)
Expand Down
21 changes: 21 additions & 0 deletions examples/4_lua.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
!Any
components:
- !GroupFilter
groups: [6,7,8]
components: !ConstantMap
map:
rho: 2500.0
mu: 0.0
lambda: 1.96e10
- !LuaMap
returns: ["rho", "mu", "lambda"]
function: |
function f (x)
io.write(x[1], " ", x[2], " ", x[3], "\n") -- optional debug output
return {
rho = 1600. + 59.5 * (x[2] ^ (1./3.)),
mu = 0,
lambda = (260. + 30*math.sqrt(x[2]))^2. * (1600. + 59.5 * x[2] ^(1./3.) )
}
end
44 changes: 44 additions & 0 deletions include/easi/component/LuaMap.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#ifndef EASI_LUAMAP_H
#define EASI_LUAMAP_H

#ifdef EASI_USE_LUA
#include <map>
#include <set>
#include <string>
#include <vector>



#include "easi/component/Map.h"
#include "easi/util/FunctionWrapper.h"
#include "easi/util/Matrix.h"

// Forward declaration to avoid including all Lua headers
struct lua_State;

namespace easi {
double getField(lua_State* L, const std::string& key);

class LuaMap : public Map {
public:
void setMap(const std::set<std::string>& in,
const std::set<std::string>& returns,
const std::string& function);

~LuaMap() override;
protected:
virtual Matrix<double> map(Matrix<double>& x) override;

private:
double executeLuaFunction(Matrix<double> x, unsigned coordIdx, unsigned funcIdx);
std::string function;
std::vector<std::string> idxToNameMap;
lua_State* luaState;

};

} // namespace easi

#endif // EASI_USE_LUA

#endif
5 changes: 5 additions & 0 deletions include/easi/parser/YAMLComponentParsers.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "easi/component/DomainFilter.h"
#include "easi/component/EvalModel.h"
#include "easi/component/FunctionMap.h"
#include "easi/component/LuaMap.h"
#include "easi/component/GroupFilter.h"
#include "easi/component/LayeredModelBuilder.h"
#include "easi/component/OptimalStress.h"
Expand Down Expand Up @@ -57,6 +58,10 @@ void parse_AffineMap(AffineMap* component, YAML::Node const& node, std::set<std:
void parse_FunctionMap(FunctionMap* component, YAML::Node const& node,
std::set<std::string> const& in, YAMLAbstractParser* parser);
#endif
#ifdef EASI_USE_LUA
void parse_LuaMap(LuaMap* component, YAML::Node const& node,
std::set<std::string> const& in, YAMLAbstractParser* parser);
#endif
void parse_PolynomialMap(PolynomialMap* component, YAML::Node const& node,
std::set<std::string> const& in, YAMLAbstractParser* parser);
void parse_SCECFile(SCECFile* component, YAML::Node const& node, std::set<std::string> const& in,
Expand Down
3 changes: 3 additions & 0 deletions src/YAMLParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ YAMLParser::YAMLParser(unsigned dimDomain, AsagiReader* externalAsagiReader, cha
registerType("!AffineMap", parse_AffineMap);
#ifdef EASI_USE_IMPALAJIT
registerType("!FunctionMap", parse_FunctionMap);
#endif
#ifdef EASI_USE_LUA
registerType("!LuaMap", parse_LuaMap);
#endif
registerType("!SCECFile", parse_SCECFile);
#ifdef EASI_USE_ASAGI
Expand Down
100 changes: 100 additions & 0 deletions src/component/LuaMap.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#include "easi/component/LuaMap.h"

#ifdef EASI_USE_LUA
extern "C" {
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
}
#include <cassert>
#include <iostream>
#include <ostream>
#include <stdexcept>

namespace easi {

double getField(lua_State* L, const std::string& key) {
lua_pushstring(L, key.data());
lua_gettable(L, -2);
if (!lua_isnumber(L, -1)) {
std::cerr
<< "Tried key "
<< key
<< " but it did not return a number."
<< std::endl;
}
const auto result = lua_tonumber(L, -1);
lua_pop(L, 1);
return result;
}

double LuaMap::executeLuaFunction(Matrix<double> x,
unsigned coordIdx,
unsigned funcIdx) {
if (!luaState) {
std::cout << "Init lua state" << std::endl;
luaState = luaL_newstate();
luaL_openlibs(luaState);
const auto status = luaL_dostring(luaState, function.data());
if (status) {
std::cerr
<< "Couldn't load script: "
<< lua_tostring(luaState, -1);
std::abort();
}
}

// Push function and arguments to stack
lua_getglobal(luaState, "f"); // the function

// Add table as input: x holds coordinates
lua_newtable(luaState);
for (int i = 0; i < 3; ++i) {
lua_pushnumber(luaState, i+1);
lua_pushnumber(luaState, x(coordIdx, i));
lua_rawset(luaState, -3);
}

if (lua_pcall(luaState, 1, 1, 0) != 0) {
std::cerr
<< "Error running function f "
<< lua_tostring(luaState, -1)
<< std::endl;
}
return getField(luaState, idxToNameMap[funcIdx]);
}

Matrix<double> LuaMap::map(Matrix<double>& x) {

assert(x.cols() == dimDomain());

Matrix<double> y(x.rows(), dimCodomain());
for (unsigned i = 0; i < y.rows(); ++i) {
for (unsigned j = 0; j < y.cols(); ++j) {
y(i,j) = executeLuaFunction(x, i, j);
}
}
return y;
}

void LuaMap::setMap(const std::set<std::string>& in,
const std::set<std::string>& out,
const std::string& newFunction) {
setIn(in);
setOut(out);
function = newFunction;
for (const auto& o : out) {
idxToNameMap.push_back(o);
}
}

LuaMap::~LuaMap() {
if (luaState) {
lua_close(luaState);
}
}



} // namespace easi
#endif // EASI_USE_LUA
22 changes: 22 additions & 0 deletions src/parser/YAMLComponentParsers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,28 @@ void parse_FunctionMap(FunctionMap* component, YAML::Node const& node,
}
#endif

#ifdef EASI_USE_LUA
void parse_LuaMap(LuaMap* component, YAML::Node const& node,
std::set<std::string> const& in, YAMLAbstractParser* parser) {
checkType(node, "returns", {YAML::NodeType::Scalar, YAML::NodeType::Sequence});

std::set<std::string> returns;
if (node["returns"].IsScalar()) {
returns.insert(node["returns"].as<std::string>());
} else {
const auto returnSeq = node["returns"].as<std::vector<std::string>>();
returns.insert(returnSeq.begin(), returnSeq.end());
}

checkType(node, "function", {YAML::NodeType::Scalar});

const auto function = node["function"].as<std::string>();

component->setMap(in, returns, function);
parse_Map(component, node, in, parser);
}
#endif

void parse_PolynomialMap(PolynomialMap* component, YAML::Node const& node,
std::set<std::string> const& in, YAMLAbstractParser* parser) {
checkType(node, "map", {YAML::NodeType::Map});
Expand Down
34 changes: 34 additions & 0 deletions tests/4_lua.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include "easitest.h"
#include <cmath>

double rho(double y) { return 1600. + 59.5 * pow(y, 1. / 3.); }
double lambda(double y) { return pow(260. + 30 * sqrt(y), 2.) * (1600. + 59.5 * pow(y, 1. / 3.)); }

int main(int argc, char** argv) {
assert(argc == 2);

easi::Query query = createQuery<3>({{7, {0.0, 0.0, 0.0}},
{5, {0.0, 10.0, 0.0}},
{4, {0.0, 20.0, 0.0}},
{3, {0.0, 25.0, 0.0}}});

auto material = elasticModel(argv[1], query);

assert(equal(material[0].rho, 2500.0));
assert(equal(material[0].mu, 0.0));
assert(equal(material[0].lambda, 1.96e10));

assert(equal(material[1].rho, rho(10.0)));
assert(equal(material[1].mu, 0.0));
assert(equal(material[1].lambda, lambda(10.0)));

assert(equal(material[2].rho, rho(20.0)));
assert(equal(material[2].mu, 0.0));
assert(equal(material[2].lambda, lambda(20.0)));

assert(equal(material[3].rho, rho(25.0)));
assert(equal(material[3].mu, 0.0));
assert(equal(material[3].lambda, lambda(25.0)));

return 0;
}

0 comments on commit 39c2508

Please sign in to comment.