Skip to content
This repository has been archived by the owner on Jun 13, 2024. It is now read-only.

Unified solver API #137

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
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
99 changes: 99 additions & 0 deletions CMake/LoadAlienOptionsConfigGenerator.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
function(generateOptionsConfig target)

set(options INSTALL_GENERATED_FILES)
set(oneValueArgs)
set(multiValueArgs)
cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})

set(OPTIONSCONFIG2CC "${PROJECT_SOURCE_DIR}/tools/python/options/gen_baseoption.py")

set(template_path "${PROJECT_SOURCE_DIR}/tools/python/options/template")

set(cxxopts_path "${PROJECT_SOURCE_DIR}/third_party/cxxopts/include")

set(options_config_path ${CMAKE_BINARY_DIR}/${PROJECT_NAME}/options_config)

if(NOT EXISTS ${options_config_path})
file(MAKE_DIRECTORY ${options_config_path})
endif()

set(options_config_files ${ARGS_UNPARSED_ARGUMENTS})

foreach(config_file ${options_config_files})

get_filename_component(name ${config_file} NAME_WE)

set(file_args --file ${config_file})
set(input_args --input_dir ${CMAKE_CURRENT_LIST_DIR})
set(output_args --output_dir ${options_config_path})
set(template_args --template_dir ${template_path})

target_include_directories(${target} PRIVATE
$<BUILD_INTERFACE:${options_config_path}>
$<BUILD_INTERFACE:${cxxopts_path}>
)

if(IS_ABSOLUTE ${config_file})
set(file ${config_file})
else()
set(file ${CMAKE_CURRENT_LIST_DIR}/${config_file})
endif()

if(NOT EXISTS ${file})
get_source_file_property(is_generated ${file} GENERATED)
if(NOT ${is_generated})
logFatalError("solver config file ${file} doesn't exist")
endif()
endif()

set(COMMENT_MESSAGE)
set(generated_files ${options_config_path}/${name}BaseOptions_config.h
${options_config_path}/${name}BaseOptionsSetter_config.h
${options_config_path}/${name}BaseOptionsEnum_config.h)
set(pycmd "python ${OPTIONSCONFIG2CC} ${file_args} ${input_args} ${output_args} ${template_args}")
set(COMMENT_MESSAGE "Building BaseOptions generated files ${name}BaseOptions_config.h ${name}BaseOptionsSetter_config.h ${name}BaseOptionsEnum_config.h ${pycmd}")

add_custom_command(OUTPUT ${generated_files}
DEPENDS ${file}
COMMAND python ${OPTIONSCONFIG2CC}
ARGS ${file_args}
${input_args}
${output_args}
${template_args}
COMMENT ${COMMENT_MESSAGE}
)

foreach(generated_file ${generated_files})
set_source_files_properties(
${generated_file} PROPERTIES GENERATED ON
)
endforeach()

target_sources(${target} PRIVATE ${generated_files})

set_property(GLOBAL APPEND PROPERTY SOLVERCONFIG_DB ${file})

if(ARGS_INSTALL_GENERATED_FILES)
install(FILES ${generated_files} DESTINATION include/${PROJECT_NAME}/solver_config)
endif()

endforeach()

target_include_directories(${target} PRIVATE
$<BUILD_INTERFACE:${config_path}>
)

endfunction()


function(generateOptionConfigDataBase)

get_property(configs GLOBAL PROPERTY SOLVERCONFIG_DB)

foreach(config ${configs})
set(CONFIG_STR "${CONFIG_STR}${config}\n")
endforeach()

file(WRITE ${PROJECT_BINARY_DIR}/optionconfigdb.txt ${CONFIG_STR})

endfunction()
6 changes: 4 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,9 @@ option(ALIEN_EXAMPLES "Whether or not to compile examples" ON)
option(ALIEN_UNIT_TESTS "Whether or not to enable unit tests" OFF)
option(ALIEN_EXPAND_TESTS "Run unit tests one by one" OFF)

option(ALIEN_USE_HDF5 "Enable HDF5 export" OFF)
option(ALIEN_USE_LIBXML2 "Enable xml export" OFF)
option(ALIEN_USE_HDF5 "Enable HDF5 import export" OFF)
option(ALIEN_USE_LIBXML2 "Enable xml import export" OFF)
option(ALIEN_USE_JSON "Enable json import export" OFF)
option(ALIEN_USE_SYCL "Whether or not to compile SYCL backend" OFF)
option(ALIEN_USE_PERF_TIMER "Whether or not to enable perf timer" OFF)
option(ALIEN_WANT_AVX "Whether or not to enable avx flags" OFF)
Expand All @@ -56,6 +57,7 @@ option(ALIEN_DEFAULT_OPTIONS "Enable best effort to find optional dependencies"

option(ALIEN_GENERATE_DOCUMENTATION "Generate API documentation" OFF)
option(ALIEN_GENERATE_TUTORIAL "Compile examples of Alien" ON)
option(ALIEN_GENERATE_OPTIONSCONFIG "Enable Options config generation" OFF)

option(ALIEN_PLUGIN_HYPRE "Whether or not to compile Hypre backend" OFF)
option(ALIEN_PLUGIN_PETSC "Whether or not to compile PETSc backend" OFF)
Expand Down
178 changes: 178 additions & 0 deletions src/core/alien/utils/XML2Tools.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
/*
* Copyright 2020 IFPEN-CEA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/

#pragma once

#include <fstream>
#include <iostream>
#include <sstream>
#include <vector>

#ifdef ALIEN_USE_LIBXML2
#include <libxml/parser.h>
#endif

#include "arccore/base/String.h"

#include <alien/utils/Precomp.h>

namespace Alien
{
#ifdef ALIEN_USE_LIBXML2
namespace XML2Tools {

class XMLDocument
{
public :
XMLDocument() = default ;
~XMLDocument()
{
if(m_doc!=nullptr)
xmlFreeDoc(m_doc);
}

xmlDocPtr m_doc = nullptr ;
bool isNull() const {
return m_doc == nullptr ;
}
};

struct FileNode
{
FileNode(int _level = 0)
: name("")
, path_name("")
, level(_level)
{}

bool isNull() const {
return x_id == nullptr ;
}

std::string name;
std::string path_name;
int level = 0 ;
xmlNodePtr x_id = nullptr ;
};


XMLDocument openDocument(const std::string& filename)
{
XMLDocument document ;
document.m_doc = xmlParseFile(filename.c_str());
if (document.m_doc == nullptr) {
throw Arccore::FatalErrorException(A_FUNCINFO, Arccore::String::format("Error while parsing XML file : {0} ",filename));
}
return document ;
}

FileNode openFileNode(XMLDocument const& document, const std::string& node_name)
{
if(document.isNull())
throw Arccore::FatalErrorException(A_FUNCINFO, "Null XML document");

FileNode node;
node.x_id = xmlDocGetRootElement(document.m_doc);
if (xmlStrcmp(node.x_id->name, (const xmlChar*)node_name.c_str())) {
throw Arccore::FatalErrorException(A_FUNCINFO, "node not found");
}
return node;
}

FileNode openFileNode(FileNode const& parent, const std::string& name)
{
FileNode node;
node.name = name;
node.path_name = parent.path_name + "/" + name;
node.level = parent.level + 1;
xmlNodePtr cur = parent.x_id->xmlChildrenNode;
while (cur != NULL) {
if ((!xmlStrcmp(cur->name, (const xmlChar*)name.c_str()))) {
node.x_id = cur;
break;
}
cur = cur->next;
}
return node;
}

void closeFileNode(FileNode const& group)
{
xmlFree(group.x_id) ;
}

template <typename ValueT>
bool read(FileNode const& parent_node, const std::string& node_name,
std::vector<ValueT>& buffer)
{
FileNode node;

xmlNodePtr cur = parent_node.x_id->xmlChildrenNode;
while (cur != nullptr) {
if ((!xmlStrcmp(cur->name, (const xmlChar*)node_name.c_str()))) {
node.x_id = cur;
break;
}
cur = cur->next;
}
if(node.isNull())
return false ;

xmlChar* contenu = xmlNodeGetContent(node.x_id);
std::stringstream flux;
flux << (const xmlChar*)contenu;
for (std::size_t i = 0; i < buffer.size(); ++i)
flux >> buffer[i];
xmlFree(contenu);
return true ;
}

template <typename ValueT>
bool read(FileNode const& parent_node, const std::string& node_name, ValueT& val)
{
FileNode node;
xmlNodePtr cur = parent_node.x_id->xmlChildrenNode;
while (cur != nullptr) {
if ((!xmlStrcmp(cur->name, (const xmlChar*)node_name.c_str()))) {
node.x_id = cur;
break;
}
cur = cur->next;
}
if(node.isNull())
return false ;

xmlChar* contenu = xmlNodeGetContent(node.x_id);
//printf("%s\n",contenu);
std::stringstream flux;
flux << (const xmlChar*)contenu;
flux >> val;
xmlFree(contenu);
return true ;
}

void read(FileNode const& node, std::string& buffer)
{
xmlChar* contenu = xmlNodeGetContent(node.x_id);
buffer = std::string((char*)contenu);
xmlFree(contenu);
}

} // end namespace XML2Tools
#endif
} // end namespace Alien
35 changes: 30 additions & 5 deletions src/core/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,14 @@
# SPDX-License-Identifier: Apache-2.0

include(LoadAlienTest)
include(LoadAlienOptionsConfigGenerator)

find_package(MPI REQUIRED)
find_package(GTest REQUIRED)

configure_file(Sample.xml Sample.xml COPYONLY)
configure_file(Sample.json Sample.json COPYONLY)

# tests with GTest

add_executable(core.gtest.seq main.cpp
Expand All @@ -34,19 +38,40 @@ add_executable(core.gtest.mpi main.cpp
TestRedistributor.cc
)

IF(ALIEN_GENERATE_OPTIONSCONFIG)
target_sources(core.gtest.seq PRIVATE TestOptionsConfig.cc)

generateOptionsConfig(core.gtest.seq
Sample.config
INSTALL_GENERATED_FILES
)
endif()

target_link_libraries(core.gtest.seq
PUBLIC GTest::GTest
PUBLIC Alien::alien_core
alien_test_framework
arcconpkg_MPI
)

if (ALIEN_USE_LIBXML2)
find_package(LibXml2 REQUIRED)

target_link_libraries(core.gtest.seq PRIVATE arccon::LibXml2)
endif ()

if(ALIEN_USE_JSON)
find_package(Boost COMPONENTS system)
target_compile_definitions(core.gtest.seq PRIVATE ALIEN_USE_BOOST_PROPERTY_TREE)
target_link_libraries(core.gtest.seq PRIVATE Boost::system)
endif()

target_link_libraries(core.gtest.mpi
PUBLIC GTest::GTest
PUBLIC Alien::alien_core
alien_test_framework
arcconpkg_MPI
)
PUBLIC GTest::GTest
PUBLIC Alien::alien_core
alien_test_framework
arcconpkg_MPI
)

if (ALIEN_EXPAND_TESTS)
gtest_discover_tests(core.gtest.seq TEST_PREFIX "core." TEST_SUFFIX ".seq")
Expand Down
Loading