Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F90682011
component_libmultiscale_inline_impl.hh
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
Sun, Nov 3, 20:34
Size
14 KB
Mime Type
text/x-c++
Expires
Tue, Nov 5, 20:34 (2 d)
Engine
blob
Format
Raw Data
Handle
22118926
Attached To
rLIBMULTISCALE LibMultiScale
component_libmultiscale_inline_impl.hh
View Options
/**
* @file component_libmultiscale.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
*
* @date Mon Sep 08 23:40:22 2014
*
* @brief This describe the root objects to be combined into valid LM
* components
*
* @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/>.
*
*/
#ifndef __LIBMULTISCALE_COMPONENT_LIBMULTISCALE_INLINE_IMPL_HH__
#define __LIBMULTISCALE_COMPONENT_LIBMULTISCALE_INLINE_IMPL_HH__
/* -------------------------------------------------------------------------- */
#include "auto_arguments.hh"
#include "component_libmultiscale.hh"
#include "container_array.hh"
#include "lm_common.hh"
/* -------------------------------------------------------------------------- */
__BEGIN_LIBMULTISCALE__
/* -------------------------------------------------------------------------- */
class
Component
;
/* -------------------------------------------------------------------------- */
using
dispatch
=
AutoDispatch
::
dispatch
;
template
<
typename
T
,
typename
...
Ts
>
using
enable_if_type
=
AutoDispatch
::
enable_if_type
<
T
,
Ts
...
>
;
/* --------------------------------------------------------------------- */
// OutputContainer
/* --------------------------------------------------------------------- */
inline
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
OutputContainer
&
out
)
{
out
.
get
().
printself
(
os
);
return
os
;
}
OutputContainer
&
OutputContainer
::
operator
=
(
Component
&
v
)
{
AutoDispatch
::
ArgumentAny
::
operator
=
(
v
);
this
->
component
=
&
v
;
return
*
this
;
}
template
<
typename
T
>
inline
OutputContainer
&
OutputContainer
::
operator
=
(
T
&&
v
)
{
AutoDispatch
::
ArgumentAny
::
operator
=
(
std
::
forward
<
T
>
(
v
));
return
*
this
;
}
template
<
typename
type
,
typename
...
T
>
decltype
(
auto
)
OutputContainer
::
alloc
(
T
&&
...
construction_parameters
)
{
try
{
this
->
get
<
type
>
();
}
catch
(
AutoDispatch
::
no_argument
&
e
)
{
(
*
this
)
=
type
(
construction_parameters
...);
}
auto
&
output
=
this
->
get
<
type
>
();
if
(
component
)
output
.
acquireContext
(
*
component
);
return
output
;
}
/* --------------------------------------------------------------------- */
// InputContainer
/* --------------------------------------------------------------------- */
inline
InputContainer
&
InputContainer
::
operator
=
(
OutputContainer
&
v
)
{
output_reference
=
&
v
;
return
*
this
;
}
/* --------------------------------------------------------------------- */
inline
InputContainer
&
InputContainer
::
operator
=
(
OutputContainer
&&
v
)
{
output_reference
=
std
::
forward
<
OutputContainer
>
(
v
);
return
*
this
;
}
/* --------------------------------------------------------------------- */
template
<
typename
T
>
inline
InputContainer
&
InputContainer
::
operator
=
(
T
&&
v
)
{
auto
out
=
std
::
make_shared
<
OutputContainer
>
();
*
out
=
std
::
forward
<
T
>
(
v
);
output_reference
=
out
;
return
*
this
;
}
/* --------------------------------------------------------------------- */
template
<
typename
T
>
decltype
(
auto
)
InputContainer
::
get
()
{
OutputContainer
&
out
=
this
->
get
();
return
out
.
get
<
T
>
();
}
/* --------------------------------------------------------------------- */
template
<
typename
T
>
decltype
(
auto
)
InputContainer
::
get
()
const
{
OutputContainer
&
out
=
this
->
get
();
return
out
.
get
<
T
>
();
}
/* --------------------------------------------------------------------- */
inline
OutputContainer
&
InputContainer
::
get
()
const
{
try
{
auto
*
ptr
=
std
::
any_cast
<
OutputContainer
*>
(
output_reference
);
return
*
ptr
;
}
catch
(
std
::
bad_any_cast
&
e
)
{
}
auto
ptr
=
std
::
any_cast
<
std
::
shared_ptr
<
OutputContainer
>>
(
output_reference
);
return
*
ptr
;
}
/* --------------------------------------------------------------------- */
inline
OutputContainer
&
InputContainer
::
eval
()
const
{
OutputContainer
&
out
=
this
->
get
();
if
(
out
.
component
!=
nullptr
)
{
out
.
component
->
compute
();
}
return
out
;
}
/* --------------------------------------------------------------------- */
inline
UInt
InputContainer
::
evalRelease
()
const
{
OutputContainer
&
out
=
this
->
get
();
return
out
.
evalRelease
();
}
/* --------------------------------------------------------------------- */
inline
UInt
InputContainer
::
getRelease
()
const
{
OutputContainer
&
out
=
this
->
get
();
return
out
.
getRelease
();
}
/* -------------------------------------------------------------------------- */
// Component
/* -------------------------------------------------------------------------- */
inline
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
Component
&
comp
)
{
comp
.
printself
(
os
);
return
os
;
}
/* --------------------------------------------------------------------- */
template
<
typename
T
>
void
Component
::
setCommGroup
(
CommGroup
&
group
)
{
LMObject
::
setCommGroup
(
group
);
for
(
auto
&&
[
key
,
output
]
:
this
->
outputs
)
{
try
{
this
->
getOutputAsArray
<
T
>
(
key
).
setCommGroup
(
group
);
}
catch
(
AutoDispatch
::
no_argument
&
e
)
{
// do nothing: cannot clean unallocated pointer
}
catch
(
AutoDispatch
::
bad_argument_cast
&
e
)
{
// do nothing: it is not an array
}
catch
(
std
::
bad_cast
&
e
)
{
// do nothing: it is not an array
}
}
}
/* --------------------------------------------------------------------- */
inline
Component
::
Component
()
:
calculated_once
(
false
)
{}
/* --------------------------------------------------------------------- */
template
<
typename
ContMap
>
inline
decltype
(
auto
)
Component
::
getContainer
(
const
std
::
string
&
required_name
,
ContMap
&
cont
)
{
std
::
string
container_type
=
"unknown"
;
if
(
std
::
is_same_v
<
ContMap
,
decltype
(
this
->
inputs
)
>
)
container_type
=
"input"
;
if
(
std
::
is_same_v
<
ContMap
,
decltype
(
this
->
outputs
)
>
)
container_type
=
"output"
;
std
::
string
name
=
required_name
;
if
(
name
==
""
)
{
if
(
cont
.
size
()
==
0
)
{
LM_FATAL
(
"There is no input for "
<<
this
->
getID
());
}
else
if
(
cont
.
size
()
!=
1
)
{
std
::
string
mesg
=
this
->
getID
()
+
" "
+
container_type
+
" has several entries: need a name"
;
mesg
+=
"
\n\n
Possible names:
\n\n
"
;
for
(
auto
&&
pair
:
cont
)
{
mesg
+=
"
\t
"
+
pair
.
first
+
"
\n
"
;
}
LM_FATAL
(
mesg
);
}
name
=
cont
.
begin
()
->
first
;
}
else
{
auto
search
=
cont
.
find
(
name
);
if
(
search
==
cont
.
end
())
{
std
::
string
mesg
=
this
->
getID
()
+
":"
+
name
+
": "
+
container_type
+
" not existing"
;
mesg
+=
"
\n\n
Possibilities are:
\n\n
"
;
for
(
auto
&&
pair
:
cont
)
{
mesg
+=
"
\t
"
+
pair
.
first
+
"
\n
"
;
}
LM_FATAL
(
mesg
);
}
}
return
std
::
forward_as_tuple
(
name
,
cont
[
name
]);
}
/* --------------------------------------------------------------------- */
inline
InputContainer
&
Component
::
getInternalInput
(
const
std
::
string
&
requested_input
)
{
auto
&&
[
input
,
arg_cont_input
]
=
getContainer
(
requested_input
,
inputs
);
if
(
not
arg_cont_input
.
has_value
())
throw
UnconnectedInput
{
"For component '"
+
this
->
getID
()
+
"' input '"
+
input
+
"' is not connected"
};
return
arg_cont_input
;
}
/* --------------------------------------------------------------------- */
inline
OutputContainer
&
Component
::
getInput
(
const
std
::
string
&
requested_input
)
{
return
this
->
getInternalInput
(
requested_input
).
eval
();
}
/* --------------------------------------------------------------------- */
template
<
typename
T
>
inline
decltype
(
auto
)
Component
::
getOutput
(
const
std
::
string
&
output_name
)
{
return
getOutput
(
output_name
).
get
<
T
>
();
}
/* --------------------------------------------------------------------- */
inline
OutputContainer
&
Component
::
getOutput
(
const
std
::
string
&
output_name
)
{
auto
&&
[
name
,
output
]
=
getContainer
(
output_name
,
outputs
);
return
output
;
}
/* --------------------------------------------------------------------- */
inline
OutputContainer
&
Component
::
evalOutput
(
const
std
::
string
&
output_name
)
{
this
->
compute
();
return
getOutput
(
output_name
);
}
/* --------------------------------------------------------------------- */
template
<
typename
T
>
inline
decltype
(
auto
)
Component
::
evalOutput
(
const
std
::
string
&
output_name
)
{
this
->
compute
();
return
getOutput
<
T
>
(
output_name
);
}
/* --------------------------------------------------------------------- */
template
<
typename
T
>
inline
decltype
(
auto
)
Component
::
evalArrayOutput
(
const
std
::
string
&
output_name
)
{
return
evalOutput
(
output_name
).
get
<
ContainerArray
<
T
>>
();
}
/* --------------------------------------------------------------------- */
template
<
typename
Cont
,
typename
...
T
>
auto
&
Component
::
allocOutput
(
const
std
::
string
&
output_name
,
T
&&
...
construction_parameters
)
{
using
type
=
typename
Cont
::
ContainerSubset
;
try
{
this
->
getOutput
(
output_name
).
get
<
type
>
();
}
catch
(
AutoDispatch
::
no_argument
&
e
)
{
this
->
getOutput
(
output_name
).
alloc
<
type
>
(
construction_parameters
...);
}
auto
&
output
=
getOutput
(
output_name
).
get
<
type
>
();
return
output
;
}
/* --------------------------------------------------------------------- */
inline
const
auto
&
Component
::
evalOutputs
()
{
this
->
compute
();
return
outputs
;
}
/* --------------------------------------------------------------------- */
inline
const
auto
&
Component
::
getOutputs
()
{
return
outputs
;
}
/* --------------------------------------------------------------------- */
template
<
typename
Names
>
void
Component
::
createArrayOutputs
(
Names
&&
output_names
)
{
for
(
auto
&&
f
:
output_names
)
{
this
->
createArrayOutput
(
f
);
}
}
/* --------------------------------------------------------------------- */
template
<
typename
T
>
void
Component
::
createArrayOutput
(
const
std
::
string
&
name
)
{
this
->
createOutput
(
name
);
this
->
getOutput
(
name
)
=
ContainerArray
<
T
>
(
this
->
getID
()
+
":"
+
name
);
}
/* --------------------------------------------------------------------- */
template
<
typename
T
>
ContainerArray
<
T
>
&
Component
::
getOutputAsArray
(
const
std
::
string
&
output_name
)
{
return
this
->
getOutput
(
output_name
).
get
<
ContainerArray
<
T
>>
();
}
/* --------------------------------------------------------------------- */
inline
void
Component
::
printself
(
std
::
ostream
&
os
)
const
{
for
(
auto
&
pair
:
this
->
inputs
)
{
os
<<
"input "
<<
pair
.
first
<<
":"
;
if
(
pair
.
second
.
has_value
())
os
<<
pair
.
second
.
get
()
<<
"
\n
"
;
else
os
<<
"not yet defined/computed
\n
"
;
}
for
(
auto
&
pair
:
this
->
outputs
)
{
os
<<
"output "
<<
pair
.
first
<<
":"
;
try
{
os
<<
pair
.
second
.
get
()
<<
"
\n
"
;
}
catch
(...)
{
os
<<
"not yet defined/computed
\n
"
;
}
}
}
/* --------------------------------------------------------------------- */
void
Component
::
connect
(
const
std
::
string
&
input
,
Component
&
comp
,
const
std
::
string
&
output
)
{
try
{
this
->
connect
(
input
,
comp
.
getOutput
(
output
));
}
catch
(...)
{
inputs
[
input
]
=
comp
;
}
}
/* --------------------------------------------------------------------- */
template
<
typename
T
>
void
Component
::
connect
(
const
std
::
string
&
input
,
T
&&
arg
)
{
auto
search
=
inputs
.
find
(
input
);
if
(
search
==
inputs
.
end
())
{
DUMP
(
input
+
": input not existing"
,
DBG_MESSAGE
);
if
(
inputs
.
size
()
>
0
)
{
DUMP
(
"Possible inputs are:"
,
DBG_MESSAGE
);
for
(
auto
p
:
inputs
)
{
DUMP
(
"
\t
"
+
p
.
first
+
"
\n
"
,
DBG_MESSAGE
);
}
}
else
{
DUMP
(
"there are no possible inputs"
,
DBG_MESSAGE
);
}
LM_FATAL
(
"abort:"
+
input
+
": input not existing"
);
}
inputs
[
input
]
=
std
::
forward
<
T
>
(
arg
);
}
/* --------------------------------------------------------------------- */
inline
OutputContainer
&
Component
::
createOutput
(
const
std
::
string
&
output
)
{
outputs
[
output
]
=
OutputContainer
(
*
this
,
output
);
return
outputs
[
output
];
}
/* --------------------------------------------------------------------- */
inline
InputContainer
&
Component
::
createInput
(
const
std
::
string
&
input
)
{
inputs
[
input
]
=
InputContainer
();
return
inputs
[
input
];
}
/* --------------------------------------------------------------------- */
inline
void
Component
::
removeInput
(
const
std
::
string
&
input
)
{
inputs
.
erase
(
input
);
}
/* --------------------------------------------------------------------- */
template
<
typename
T
,
typename
...
Ts
>
inline
std
::
enable_if_t
<
std
::
is_same_v
<
std
::
decay_t
<
T
>
,
InputConnection
>>
Component
::
compute
(
T
&&
arg
,
Ts
&&
...
args
)
{
auto
tup_args
=
std
::
forward_as_tuple
(
arg
,
args
...);
apply
([
&
](
auto
&&
arg
)
{
this
->
connect
(
arg
.
name
,
arg
.
val
);
},
tup_args
);
this
->
compute
();
}
/* --------------------------------------------------------------------- */
template
<
typename
T
>
inline
std
::
enable_if_t
<
not
std
::
is_same_v
<
std
::
decay_t
<
T
>
,
InputConnection
>>
Component
::
compute
(
T
&&
arg
)
{
// get the default input
auto
&&
[
input
,
arg_cont_input
]
=
getContainer
(
""
,
inputs
);
arg_cont_input
=
arg
;
this
->
compute
();
}
/* --------------------------------------------------------------------- */
// array output management
/* --------------------------------------------------------------------- */
template
<
typename
F
>
void
Component
::
applyArrayOutput
(
F
&&
f
,
const
std
::
string
&
name
)
{
try
{
auto
&
_output
=
this
->
getOutputAsArray
(
name
);
f
(
_output
);
}
catch
(
AutoDispatch
::
no_argument
&
e
)
{
// do nothing: cannot clean unallocated pointer
}
catch
(
AutoDispatch
::
bad_argument_cast
&
e
)
{
// do nothing: it is not an array
}
catch
(
std
::
bad_cast
&
e
)
{
// do nothing: it is not an array
}
}
/* --------------------------------------------------------------------- */
void
Component
::
clear
()
{
for
(
auto
&&
[
name
,
out
]
:
this
->
outputs
)
{
this
->
applyArrayOutput
([](
auto
&
output
)
->
void
{
output
.
clear
();
},
name
);
}
}
/* --------------------------------------------------------------------- */
UInt
Component
::
size
(
const
std
::
string
&
name
)
{
try
{
auto
&
_output
=
this
->
getOutput
<
ContainerInterface
>
(
name
);
return
_output
.
size
();
}
catch
(
AutoDispatch
::
no_argument
&
e
)
{
// do nothing: cannot clean unallocated pointer
}
catch
(
AutoDispatch
::
bad_argument_cast
&
e
)
{
// do nothing: it is not an array
}
catch
(
std
::
bad_cast
&
e
)
{
// do nothing: it is not an array
}
return
0
;
}
/* --------------------------------------------------------------------- */
__END_LIBMULTISCALE__
#endif
/* __LIBMULTISCALE_COMPONENT_LIBMULTISCALE_INLINE_IMPL_HH__ */
Event Timeline
Log In to Comment