Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F74908909
app_core.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Tue, Jul 30, 08:22
Size
12 KB
Mime Type
text/x-c
Expires
Thu, Aug 1, 08:22 (2 d)
Engine
blob
Format
Raw Data
Handle
19451369
Attached To
rSPECMICP SpecMiCP / ReactMiCP
app_core.cpp
View Options
/* =============================================================================
Copyright (c) 2014-2017 F. Georget <fabieng@princeton.edu> Princeton University
Copyright (c) 2017-2018 F. Georget <fabien.georget@epfl.ch> EPFL
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
============================================================================= */
#include "app_core.hpp"
#include "specmicp_common/physics/units.hpp"
#include "specmicp_common/log.hpp"
#include "specmicp_common/compat.hpp"
#include "specmicp_common/openmp_support.hpp"
#include "specmicp_common/cli/parser.hpp"
#include "specmicp_common/filesystem.hpp"
#include "specmicp_database/data_container.hpp"
#include "specmicp_database/io/configuration.hpp"
#include "specmicp_common/io/config_yaml_sections.h"
#include "specmicp_common/io/configuration.hpp"
#include "specmicp_common/physics/io/configuration.hpp"
#include "specmicp_common/physics/io/units.hpp"
#include "dfpm/io/configuration.hpp"
#include "reactmicp/io/configuration.hpp"
#include "reactmicp/solver/reactive_transport_solver.hpp"
#include "reactmicp/solver/reactive_transport_solver_structs.hpp"
#include "specmicp_common/plugins/plugin_modules_names.h"
#include "specmicp_common/plugins/module_base.hpp"
#include "specmicp_common/plugins/plugin_manager.hpp"
#include <iostream>
// ==================== //
// Main App //
// ==================== //
MainApp
::
MainApp
()
{}
MainApp
::~
MainApp
()
=
default
;
int
MainApp
::
run
(
SystemApp
&
system_app
,
int
argc
,
char
*
argv
[])
{
system_app
.
print_welcome
();
init_logger
(
&
std
::
cout
,
logger
::
Warning
);
CliOptions
cli_opts
=
CliOptions
::
parse_cli
(
argc
,
argv
);
if
(
cli_opts
.
done
)
{
return
EXIT_SUCCESS
;
}
// db dirs contain the directories when the database is searched
std
::
vector
<
std
::
string
>
db_dirs
=
cli_opts
.
get_db_dirs
();
// Configuration File
// ------------------
system_app
.
init_input_file
(
cli_opts
.
input_filepath
);
system_app
.
init_simul_info
(
cli_opts
.
working_dir
);
system_app
.
init_alliofiles
(
cli_opts
);
if
(
cli_opts
.
clean_outputs
)
{
if
(
cli_opts
.
only_pretend
)
{
return
EXIT_SUCCESS
;
// Do not panic, just for fun
}
system_app
.
clean_output_files
();
return
EXIT_SUCCESS
;
// just cleaning, nothing more to run
}
system_app
.
init_conf_logger
();
system_app
.
init_logger
();
system_app
.
init_plugin_manager
();
// openmp initialization
// ---------------------
utils
::
initialize_parallel
();
// Simulation Data and Staggers
// ----------------------------
system_app
.
init_simul_data
(
db_dirs
);
// Staggers
// -------
system_app
.
init_staggers
();
// Check the variables
// -------------------
system_app
.
check_init_data
();
// Solver
// ------
system_app
.
init_solver
();
system_app
.
init_runner
();
system_app
.
init_output
(
cli_opts
.
working_dir
);
if
(
not
cli_opts
.
only_pretend
)
{
system_app
.
run
();
}
return
EXIT_SUCCESS
;
}
// ==================== //
// CLI options //
// ==================== //
CliOptions
CliOptions
::
parse_cli
(
int
argc
,
char
*
argv
[])
{
CliOptions
opts
;
// CLI options
cli
::
CommandLineParser
parser
;
parser
.
add_option
(
'i'
,
"input"
,
cli
::
ValueType
::
string
,
"input_file (yaml format)"
);
parser
.
add_option
(
'd'
,
"database_dir"
,
std
::
string
(
""
),
"directory where database are stored"
);
parser
.
add_option
(
'w'
,
"workdir"
,
utils
::
get_current_directory
(),
"working directory"
);
parser
.
add_option
(
'o'
,
"overwrite"
,
false
,
"If true, allow overwrite of previous simulation"
);
parser
.
add_option
(
'c'
,
"clean"
,
false
,
"Clean previous output files"
);
parser
.
add_option
(
'p'
,
"pretend"
,
false
,
"Dry-run, do not run simulation"
);
parser
.
set_help_message
(
"ReactMiCP Unsaturated System"
);
const
auto
ret_parse
=
parser
.
parse
(
argc
,
argv
);
if
(
ret_parse
>
0
)
{
opts
.
done
=
true
;
}
opts
.
input_filepath
=
parser
.
get_option
<
cli
::
ValueType
::
string
>
(
"input"
);
opts
.
database_dir
=
parser
.
get_option
<
cli
::
ValueType
::
string
>
(
"database_dir"
);
opts
.
working_dir
=
parser
.
get_option
<
cli
::
ValueType
::
string
>
(
"workdir"
);
opts
.
allow_overwrite
=
parser
.
get_option
<
cli
::
ValueType
::
boolean
>
(
"overwrite"
);
opts
.
clean_outputs
=
parser
.
get_option
<
cli
::
ValueType
::
boolean
>
(
"clean"
);
opts
.
only_pretend
=
parser
.
get_option
<
cli
::
ValueType
::
boolean
>
(
"pretend"
);
return
opts
;
}
std
::
vector
<
std
::
string
>
CliOptions
::
get_db_dirs
()
const
{
std
::
vector
<
std
::
string
>
db_dirs
;
if
(
not
database_dir
.
empty
())
{
db_dirs
.
push_back
(
database_dir
);}
db_dirs
.
push_back
(
utils
::
get_current_directory
());
io
::
add_db_dirs_from_env
(
db_dirs
);
if
(
not
working_dir
.
empty
())
{
db_dirs
.
push_back
(
working_dir
);}
return
db_dirs
;
}
// ==================== //
// SystemApp //
// ==================== //
void
SystemApp
::
init_input_file
(
const
std
::
string
&
input_filepath
)
{
m_config
=
io
::
YAMLConfigFile
::
make
(
input_filepath
);
}
void
SystemApp
::
init_simul_info
(
const
std
::
string
&
working_dir
)
{
m_simul_info
=
make_unique
<
solver
::
SimulationInformation
>
(
""
,
0
);
*
m_simul_info
=
io
::
configure_simulation_information
(
m_config
->
get_section
(
SPC_CF_S_SIMULINFO
));
m_simul_info
->
working_dir
=
working_dir
;
}
void
SystemApp
::
init_alliofiles
(
const
CliOptions
&
cli_opts
)
{
io
::
AllIOFilesMode
flag
=
io
::
AllIOFilesMode
::
ErrorIfExist
;
if
(
cli_opts
.
allow_overwrite
)
{
flag
=
io
::
AllIOFilesMode
::
Write
;
}
else
if
(
cli_opts
.
clean_outputs
){
flag
=
io
::
AllIOFilesMode
::
Read
;
}
auto
io_file_path
=
m_simul_info
->
complete_filepath
(
"io"
,
"yml"
);
m_all_io_files
=
make_unique
<
io
::
AllIOFiles
>
(
io_file_path
,
flag
);
m_all_io_files
->
add_configuration_file
(
io
::
input_file
(
IO_INPUT
,
cli_opts
.
input_filepath
));
}
void
SystemApp
::
init_conf_logger
()
{
if
(
m_config
->
has_section
(
SPC_CF_S_CONF_LOGS
))
{
m_out_conf_logger
=
io
::
configure_conf_log
(
m_config
->
get_section
(
SPC_CF_S_CONF_LOGS
),
m_all_io_files
.
get
()
// log file registered here
);
}
SPC_CONF_LOG
<<
"Running "
<<
this
->
driver_identification
();
}
void
SystemApp
::
init_logger
()
{
if
(
m_config
->
has_section
(
SPC_CF_S_LOGS
))
{
m_out_logger
=
io
::
configure_log
(
m_config
->
get_section
(
SPC_CF_S_LOGS
),
m_all_io_files
.
get
()
// log file registered here
);
}
}
void
SystemApp
::
init_solver
()
{
m_solver
=
make_unique
<
solver
::
ReactiveTransportSolver
>
(
m_staggers
.
transport
,
m_staggers
.
chemistry
,
m_staggers
.
upscaling
);
io
::
configure_reactmicp_options
(
m_solver
->
get_options
(),
m_config
->
get_section
(
SPC_CF_S_REACTMICP
)
);
SPC_CONF_LOG
<<
"
\n\n
++ ReactMiCP ++
\n
"
<<
SPC_CONF_LOG_SECTION
<<
"
\n
ReactMiCP options
\n
"
<<
SPC_CONF_LOG_HLINE
;
std
::
ostringstream
msg
;
io
::
print_reactmicp_options
(
msg
,
m_solver
->
get_options
());
SPC_CONF_LOG
<<
msg
.
str
();
}
void
SystemApp
::
init_runner
()
{
m_runner
=
make_unique
<
solver
::
ReactiveTransportRunner
>
(
*
m_solver
,
1.0
,
10.0
,
// dummy value, set later
*
m_simul_info
);
io
::
configure_reactmicp_timestepper
(
m_runner
->
get_timestepper_options
(),
m_config
->
get_section
(
SPC_CF_S_TIMESTEPPER
)
);
}
void
SystemApp
::
run
()
{
// run info
auto
run_section
=
m_config
->
get_section
(
SPC_CF_S_RUN
);
auto
run_until
=
run_section
.
get_required_attribute
<
scalar_t
>
(
SPC_CF_S_RUN_A_RUNUNTIL
);
// At this point we assume it's safe to destroy the config
// to get information about unread keys
m_config
.
reset
(
nullptr
);
m_runner
->
run_until
(
run_until
,
get_variables
());
}
void
SystemApp
::
clean_output_files
()
{
m_all_io_files
->
clean_output_files
();
m_all_io_files
.
reset
(
nullptr
);
}
void
SystemApp
::
init_plugin_manager_base
(
std
::
vector
<
std
::
string
>
plugin_modules
)
{
SPC_CONF_LOG
<<
SPC_CONF_LOG_SECTION
<<
"
\n
Initialize plugin manager
\n
"
<<
SPC_CONF_LOG_HLINE
;
plugins
::
PluginManager
&
plugin_manager
=
plugins
::
get_plugin_manager
();
for
(
auto
&
module:
plugin_modules
)
{
SPC_CONF_LOG
<<
"Registering module "
+
module
;
plugin_manager
.
register_module
(
module
,
make_unique
<
plugins
::
ModuleBase
>
());
}
if
(
m_config
->
has_section
(
SPC_CF_S_PLUGINS
))
{
io
::
configure_plugin_manager
(
m_config
->
get_section
(
SPC_CF_S_PLUGINS
));
}
auto
dirs
=
plugin_manager
.
get_plugin_directories
();
if
(
not
dirs
.
empty
())
{
SPC_CONF_LOG
<<
"plugin path : "
;
for
(
auto
dir:
dirs
)
{
SPC_CONF_LOG
<<
" - "
<<
dir
;
}
}
SPC_CONF_LOG
<<
SPC_CONF_LOG_HLINE
;
}
units
::
UnitsSet
SystemApp
::
get_units_from_config
()
{
units
::
UnitsSet
t_units
;
if
(
m_config
->
has_section
(
SPC_CF_S_UNITS
))
{
t_units
=
io
::
configure_units
(
m_config
->
get_section
(
SPC_CF_S_UNITS
));
}
SPC_CONF_LOG
<<
SPC_CONF_LOG_HLINE
<<
"
\n
Units :"
<<
"
\n
- length : "
<<
io
::
to_string
(
t_units
.
length
)
<<
"
\n
- mass : "
<<
io
::
to_string
(
t_units
.
mass
)
<<
"
\n
- quantity : "
<<
io
::
to_string
(
t_units
.
quantity
)
<<
"
\n
"
<<
SPC_CONF_LOG_HLINE
;
return
t_units
;
}
database
::
RawDatabasePtr
SystemApp
::
get_database_from_config
(
const
std
::
vector
<
std
::
string
>
&
db_dirs
)
{
auto
&
config
=
get_config
();
SPC_CONF_LOG
<<
"Database initialization
\n
"
;
RawDatabasePtr
raw_data
=
io
::
configure_database
(
config
.
get_section
(
SPC_CF_S_DATABASE
),
db_dirs
);
auto
&
metadata
=
raw_data
->
metadata
;
m_all_io_files
->
add_database
(
io
::
input_file
(
IO_FILE_INIT_DB
,
metadata
.
path
,
metadata
.
name
+
" - "
+
metadata
.
version
));
SPC_CONF_LOG
<<
SPC_CONF_LOG_HLINE
;
if
(
not
raw_data
->
is_valid
())
{
CRITICAL
<<
"Invalid database from the configuration."
;
throw
std
::
runtime_error
(
"Database parsed from the configuration has"
" been detected to be invalid. Abort."
);
}
return
raw_data
;
}
mesh
::
Mesh1DPtr
SystemApp
::
get_mesh_from_config
()
{
SPC_CONF_LOG
<<
"Mesh initialization
\n
"
<<
SPC_CONF_LOG_SECTION
;
auto
mesh1d
=
io
::
configure_mesh
(
m_config
->
get_section
(
SPC_CF_S_MESH
));
SPC_CONF_LOG
<<
SPC_CONF_LOG_HLINE
;
return
mesh1d
;
}
std
::
string
get_plugin_name
(
io
::
YAMLConfigHandle
&
conf
)
{
std
::
string
plugin_name
=
conf
.
get_required_attribute
<
std
::
string
>
(
SPC_CF_A_PLUGIN_NAME
);
SPC_CONF_LOG
<<
"Use plugin "
<<
plugin_name
;
plugins
::
PluginManager
&
plugin_manager
=
plugins
::
get_plugin_manager
();
auto
extra_plugin_file
=
conf
.
get_optional_attribute
<
std
::
string
>
(
SPC_CF_A_PLUGIN_FILE
,
""
);
if
(
extra_plugin_file
!=
""
)
{
SPC_CONF_LOG
<<
"Load plugin file "
<<
extra_plugin_file
;
auto
retcode
=
plugin_manager
.
load_plugin
(
extra_plugin_file
);
if
(
not
retcode
)
{
CRITICAL
<<
"Failed to load plugin file : "
<<
extra_plugin_file
<<
std
::
endl
;
std
::
runtime_error
(
"Fail to load plugin file : "
+
extra_plugin_file
+
"."
);
}
}
return
plugin_name
;
}
Event Timeline
Log In to Comment