Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F63555452
compute_python.cc
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
Mon, May 20, 23:36
Size
11 KB
Mime Type
text/x-c++
Expires
Wed, May 22, 23:36 (1 d, 23 h)
Engine
blob
Format
Raw Data
Handle
17787539
Attached To
rLIBMULTISCALE LibMultiScale
compute_python.cc
View Options
/**
* @file compute_python.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
*
* @date Tue Jul 22 14:47:56 2014
*
* @brief This compute allows to use Python to produce computed values as input
* to LM
*
* @section LICENSE
*
* Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* LibMultiScale is free software: you can redistribute it and/or modify it
* under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* LibMultiScale is distributed in the hope that it will be useful, but
* WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with LibMultiScale. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#define TIMER
#include "compute_python.hh"
#include "communicator.hh"
#include "compute_compatibility.hh"
#include "factory_multiscale.hh"
#include "lib_dd.hh"
#include "lib_md.hh"
#include "lm_common.hh"
#include "lm_parser.hh"
#include "units.hh"
#include <Eigen/Dense>
#include <pybind11/eigen.h>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
/* -------------------------------------------------------------------------- */
__BEGIN_LIBMULTISCALE__
namespace
py
=
pybind11
;
template
<
typename
T
>
void
appendGeneralVariables
(
py
::
object
&
kwargs
,
const
std
::
string
&
name
,
T
&
value
)
{
py
::
object
pyvalue
=
py
::
cast
(
value
);
kwargs
.
attr
(
"__setitem__"
)(
name
,
pyvalue
);
}
/* -------------------------------------------------------------------------- */
template
<>
void
appendGeneralVariables
<
IntegrationSchemeStage
>
(
py
::
object
&
kwargs
,
const
std
::
string
&
name
,
IntegrationSchemeStage
&
value
)
{
std
::
stringstream
sstr
;
sstr
<<
value
;
std
::
string
str
=
sstr
.
str
();
appendGeneralVariables
<
std
::
string
>
(
kwargs
,
name
,
str
);
}
/* -------------------------------------------------------------------------- */
template
<
typename
Cont
>
void
appendGeneralArray
(
py
::
object
&
kwargs
,
Cont
&
cont
,
bool
gather_flag
,
CommGroup
&
group
,
bool
gather_root_proc
)
{
const
UInt
Dim
=
cont
.
getDim
();
std
::
vector
<
Real
>
*
vdata_ptr
=
nullptr
;
if
(
gather_flag
)
{
vdata_ptr
=
&
cont
.
gatherAllData
(
gather_root_proc
);
}
else
{
std
::
vector
<
Real
>
&
tmp
=
dynamic_cast
<
ComputeInterface
&>
(
cont
);
vdata_ptr
=
&
tmp
;
}
if
(
gather_flag
)
{
UInt
my_rank
=
group
.
getMyRank
();
if
(
my_rank
!=
gather_root_proc
)
{
// this->setDim(0);
return
;
}
}
LM_ASSERT
(
vdata_ptr
,
"null pointer detected: abort"
);
std
::
vector
<
Real
>
&
vdata
=
*
vdata_ptr
;
UInt
sz
=
vdata
.
size
()
/
Dim
;
Eigen
::
Map
<
Eigen
::
Array
<
Real
,
Eigen
::
Dynamic
,
Eigen
::
Dynamic
,
Eigen
::
RowMajor
>>
python_input
(
&
vdata
[
0
],
sz
,
Dim
);
py
::
object
pyvalue
=
py
::
cast
(
python_input
);
DUMP
(
"adding the compute "
<<
cont
.
getID
(),
DBG_INFO
);
kwargs
.
attr
(
"__setitem__"
)(
cont
.
getID
(),
pyvalue
);
py
::
object
pyNameComputed
;
try
{
pyNameComputed
=
kwargs
.
attr
(
"__getitem__"
)(
"name_computed"
);
}
catch
(
py
::
error_already_set
&
e
)
{
pyNameComputed
=
py
::
dict
();
}
py
::
object
pyThisNameComputed
=
py
::
dict
();
for
(
UInt
i
=
0
;
i
<
cont
.
name_computed
.
size
();
++
i
)
{
py
::
object
index
=
py
::
cast
(
i
);
pyThisNameComputed
.
attr
(
"__setitem__"
)(
cont
.
name_computed
[
i
],
index
);
}
pyNameComputed
.
attr
(
"__setitem__"
)(
cont
.
getID
(),
pyThisNameComputed
);
kwargs
.
attr
(
"__setitem__"
)(
"name_computed"
,
pyNameComputed
);
}
/* -------------------------------------------------------------------------- */
ComputePython
::
ComputePython
(
const
std
::
string
&
name
)
:
LMObject
(
name
)
{
gather_root_proc
=
0
;
gather_flag
=
false
;
pModule
=
std
::
make_unique
<
py
::
object
>
();
pCompute
=
std
::
make_unique
<
py
::
object
>
();
kwargs
=
std
::
make_unique
<
py
::
dict
>
();
};
/* -------------------------------------------------------------------------- */
ComputePython
::~
ComputePython
()
{}
/* -------------------------------------------------------------------------- */
void
ComputePython
::
init
()
{
if
(
!
this
->
isConnected
(
"input1"
))
this
->
removeInput
(
"input1"
);
try
{
*
pModule
=
py
::
module
::
import
(
filename
.
c_str
());
}
catch
(
py
::
error_already_set
&
e
)
{
DUMP
(
std
::
endl
<<
"Python error while loading "
<<
filename
<<
":"
<<
std
::
endl
<<
e
.
what
()
<<
std
::
endl
<<
std
::
endl
,
DBG_MESSAGE
);
LM_FATAL
(
"Failed to load "
<<
filename
);
}
std
::
map
<
std
::
string
,
decltype
(
code_unit_system
.
mvv2e
)
>
units_dict
{
{
"mvv2e"
,
code_unit_system
.
mvv2e
},
{
"f_m2v_t"
,
code_unit_system
.
f_m2v_t
},
{
"ft_m2v"
,
code_unit_system
.
ft_m2v
},
{
"mv_t2f"
,
code_unit_system
.
mv_t2f
},
{
"kT2e"
,
code_unit_system
.
kT2e
},
{
"kT2fd"
,
code_unit_system
.
kT2fd
},
{
"m_tt2f_d"
,
code_unit_system
.
m_tt2f_d
},
{
"e_dd2m_tt"
,
code_unit_system
.
e_dd2m_tt
},
{
"e2fd"
,
code_unit_system
.
e2fd
},
{
"e_m2dd_tt"
,
code_unit_system
.
e_m2dd_tt
},
{
"fd2e"
,
code_unit_system
.
fd2e
}};
pModule
->
attr
(
"__dict__"
).
attr
(
"update"
)(
units_dict
);
try
{
*
pCompute
=
pModule
->
attr
(
"compute"
);
}
catch
(
py
::
error_already_set
&
e
)
{
DUMP
(
std
::
endl
<<
"Python error in "
<<
filename
<<
":"
<<
std
::
endl
<<
e
.
what
()
<<
std
::
endl
<<
std
::
endl
,
DBG_MESSAGE
);
PyErr_Print
();
LM_FATAL
(
"Cannot find entry point: compute()"
);
}
// try {
// pSetNameComputed = pModule.attr("setNameComputed");
// } catch (py::error_already_set &e) {
// pSetNameComputed = py::none();
// DUMP(this->getID() << ": no setNameComputed routine", DBG_WARNING);
// }
kwargs
->
attr
(
"update"
)(
Parser
::
getAlgebraicVariables
());
}
/* -------------------------------------------------------------------------- */
void
ComputePython
::
appendGeneralInfo
(
CommGroup
&
group
)
{
UInt
my_rank
=
group
.
getMyRank
();
for
(
UInt
comp
=
0
;
comp
<
compute_list
.
size
();
++
comp
)
{
LMID
id
=
compute_list
[
comp
];
auto
&
my_compute
=
FilterManager
::
getManager
().
getCastedObject
<
ComputeInterface
>
(
id
);
my_compute
.
build
();
appendGeneralArray
(
*
kwargs
,
my_compute
,
this
->
gather_flag
,
group
,
this
->
gather_root_proc
);
}
if
(
this
->
gather_flag
&&
(
my_rank
!=
gather_root_proc
))
return
;
appendGeneralVariables
(
*
kwargs
,
"step"
,
current_step
);
appendGeneralVariables
(
*
kwargs
,
"current_stage"
,
current_stage
);
appendGeneralVariables
(
*
kwargs
,
"compute_name"
,
this
->
getID
());
appendGeneralVariables
(
*
kwargs
,
"rank"
,
lm_my_proc_id
);
}
/* -------------------------------------------------------------------------- */
template
<
typename
T
>
void
treat_dict
(
T
&
dict
)
{}
void
ComputePython
::
callPythonRoutine
()
{
STARTTIMER
(
this
->
getID
());
LM_TOIMPLEMENT
;
// // py::array_t<Real> pValue = (*pCompute)(***kwargs);
// py::object pValue = (*pCompute)(***kwargs);
// std::map<std::string, py::object> results;
// try{
// results = pValue.cast<std::map<std::string, py::object>>();
// }catch(...){
// py::object res = pValue;
// results["result"] = res;
// }
// using eigen_array = Eigen::Array<double, Eigen::Dynamic, Eigen::Dynamic>;
// std::map<std::string, eigen_array> results_vec;
// for (auto && pair: results){
// auto & key = pair.first;
// auto & vec = pair.second;
// results_vec[key] = vec.cast<eigen_array>();
// }
// UInt dim = result_vec.cols();
// // setNameComputed(pArgs, dim);
// this->name_computed.clear();
// for (UInt i = 0; i < dim; ++i) {
// std::stringstream title;
// title << "python" << i;
// this->name_computed.push_back(title.str());
// }
// for (UInt i = 0; i < result_vec.rows(); ++i) {
// for (UInt j = 0; j < dim; ++j) {
// this->add(result_vec(i, j));
// }
// }
// DUMP("compute python " << this->getID() << " computed " << this->size()
// << " values",
// DBG_INFO);
STOPTIMER
(
this
->
getID
());
}
/* --------------------------------------------------------------------------
*/
void
ComputePython
::
compute_no_arg
()
{
this
->
clear
();
// import_array();
this
->
setCommGroup
(
Communicator
::
getCommunicator
().
getObject
(
"all"
));
CommGroup
&
group
=
this
->
getCommGroup
();
this
->
appendGeneralInfo
(
group
);
this
->
callPythonRoutine
();
}
/* ----------------------------------------------------------------------- */
void
ComputePython
::
compute_with_arg
(
ComputeInterface
&
cont
)
{
this
->
clear
();
this
->
copyContainerInfo
(
cont
);
// import_array();
CommGroup
&
group
=
this
->
getCommGroup
();
appendGeneralArray
(
*
kwargs
,
cont
,
this
->
gather_flag
,
group
,
this
->
gather_root_proc
);
this
->
appendGeneralInfo
(
group
);
this
->
callPythonRoutine
();
}
/* ----------------------------------------------------------------------- */
// void ComputePython::setNameComputed(py::object &pArgs, UInt dim) {
// this->name_computed.clear();
// if (!pSetNameComputed.is_none()) {
// std::list<py::object> pValue =
// pSetNameComputed(pArgs, kwargs).cast<std::list<py::object>>();
// if (pValue.size() != dim)
// LM_FATAL("The number of names provided is not correct " <<
// pValue.size()
// << " != " <<
// dim);
// for (auto &&entry : pValue) {
// std::string name = entry.cast<std::string>();
// DUMP("adding name_computed " << name, DBG_INFO);
// this->name_computed.push_back(std::string(name));
// }
// } else {
// for (UInt i = 0; i < dim; ++i) {
// std::stringstream title;
// title << "python" << i;
// this->name_computed.push_back(title.str());
// }
// }
// }
/* --------------------------------------------------------------------------
*/
/* LMDESC PYTHON
This computes an array of reals based on a python script
*/
/* LMEXAMPLE
COMPUTE disp EXTRACT INPUT md FIELD displacement \\\\
COMPUTE disp2 PYTHON INPUT disp FILENAME script \\\\
with a python script stored in a file script.py with the content such
as:\\\\
import numpy as np\\ \\
def compute(**kwargs):\\
~~vec = np.copy(kwargs["disp"])\\
~~vec *= 2. \\
~~return vec
*/
void
ComputePython
::
declareParams
()
{
ComputeInterface
::
declareParams
();
/* LMKEYWORD FILENAME
Specify the name of the python script to use
*/
this
->
parseKeyword
(
"FILENAME"
,
filename
);
/* LMKEYWORD GATHER_ROOT
Specify the processor where to gather data before inputing to python
script
*/
this
->
parseKeyword
(
"GATHER_ROOT"
,
gather_root_proc
,
0u
);
/* LMKEYWORD GATHER
Specify the processor where to gather data before inputing to python
script
*/
this
->
parseTag
(
"GATHER"
,
gather_flag
,
false
);
/* LMKEYWORD ADD_COMPUTE
Add computes to input to the kwargs of the python script
*/
this
->
parseKeyword
(
"ADD_COMPUTE"
,
compute_list
,
std
::
vector
<
std
::
string
>
{});
}
/* --------------------------------------------------------------------------
*/
void
ComputePython
::
compute_make_call
()
{
DUMP
(
this
->
getID
()
<<
": Compute"
,
DBG_INFO
);
if
(
this
->
isConnected
(
"input1"
))
call_compute
(
*
this
,
[
&
](
auto
&
...
args
)
{
this
->
compute_with_arg
(
args
...);
},
this
->
getInput
(
"input1"
));
else
call_compute
(
*
this
,
[
&
]()
{
this
->
compute_no_arg
();
});
}
__END_LIBMULTISCALE__
Event Timeline
Log In to Comment