Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Kirill Terekhov
INMOST
Commits
831bfd7c
Commit
831bfd7c
authored
Aug 05, 2014
by
Alexander Danilov
Browse files
Merge branch 'master' of inmost-github
parents
f3e4e583
5452e1ea
Changes
45
Hide whitespace changes
Inline
Side-by-side
CMakeLists.txt
View file @
831bfd7c
...
@@ -31,7 +31,7 @@ set(HEADER inmost.h
...
@@ -31,7 +31,7 @@ set(HEADER inmost.h
container.hpp
container.hpp
io.hpp
io.hpp
solver_ilu2.hpp
solver_ilu2.hpp
#
solver_ddpqiluc2.hpp
solver_ddpqiluc2.hpp
solver_bcgsl.hpp
solver_bcgsl.hpp
solver_prototypes.hpp
)
solver_prototypes.hpp
)
...
@@ -56,7 +56,7 @@ option(USE_PARTITIONER_PARMETIS "Use ParMetis partitioner" OFF)
...
@@ -56,7 +56,7 @@ option(USE_PARTITIONER_PARMETIS "Use ParMetis partitioner" OFF)
option
(
USE_PARTITIONER_ZOLTAN
"Use Zoltan partitioner"
OFF
)
option
(
USE_PARTITIONER_ZOLTAN
"Use Zoltan partitioner"
OFF
)
option
(
USE_SOLVER_PETSC
"Use PETSc solver"
OFF
)
option
(
USE_SOLVER_PETSC
"Use PETSc solver"
OFF
)
option
(
USE_AUTODIFF_OPENCL
"Use OpenCL for automatic differentiation (under work)"
OFF
)
option
(
USE_AUTODIFF_OPENCL
"Use OpenCL for automatic differentiation (under work)"
OFF
)
option
(
USE_AUTODIFF_ASMJIT
"Use AsmJit for automatic differentiation"
O
N
)
option
(
USE_AUTODIFF_ASMJIT
"Use AsmJit for automatic differentiation"
O
FF
)
option
(
USE_AUTODIFF_EXPRESSION_TEMPLATES
"Use c++ expression templates for automatic differentiation"
OFF
)
option
(
USE_AUTODIFF_EXPRESSION_TEMPLATES
"Use c++ expression templates for automatic differentiation"
OFF
)
set
(
CMAKE_MODULE_PATH
${
CMAKE_MODULE_PATH
}
"
${
CMAKE_SOURCE_DIR
}
/cmake_find/"
)
set
(
CMAKE_MODULE_PATH
${
CMAKE_MODULE_PATH
}
"
${
CMAKE_SOURCE_DIR
}
/cmake_find/"
)
...
...
autodiff.cpp
View file @
831bfd7c
...
@@ -13,14 +13,216 @@
...
@@ -13,14 +13,216 @@
namespace
INMOST
namespace
INMOST
{
{
#if defined(NEW_VERSION)
//! returns offset from the end of precomputed z
void
Automatizator
::
DerivativeFill
(
expr
&
var
,
INMOST_DATA_ENUM_TYPE
element
,
INMOST_DATA_ENUM_TYPE
parent
,
Solver
::
Row
&
entries
,
INMOST_DATA_REAL_TYPE
multval
,
void
*
user_data
)
{
INMOST_DATA_ENUM_TYPE
voffset
=
var
.
values_offset
(
element
),
doffset
=
var
.
derivatives_offset
(
element
);
INMOST_DATA_ENUM_TYPE
k
=
var
.
data
.
size
()
-
1
;
Storage
*
e
=
var
.
current_stencil
[
element
].
first
;
INMOST_DATA_REAL_TYPE
lval
,
rval
,
ret
;
var
.
values
[
doffset
+
k
]
=
multval
;
expr
::
expr_data
*
arr
=
&
var
.
data
[
0
],
*
it
;
//for (expr::data_type::reverse_iterator it = var.data.rbegin(); it != var.data.rend(); ++it)
do
{
it
=
arr
+
k
;
switch
(
it
->
op
)
{
case
AD_EXT
:
assert
(
parent
!=
ENUMUNDEF
);
it
->
left
.
e
->
values
[
it
->
left
.
e
->
derivatives_offset
(
parent
)
+
it
->
right
.
i
]
+=
var
.
values
[
doffset
+
k
];
break
;
case
AD_COND
:
{
expr
&
next
=
var
.
values
[
voffset
+
it
->
left
.
i
]
>
0.0
?
*
it
->
right
.
q
->
left
.
e
:
*
it
->
right
.
q
->
right
.
e
;
DerivativeFill
(
next
,
0
,
element
,
entries
,
var
.
values
[
doffset
+
k
],
user_data
);
}
break
;
case
AD_PLUS
:
var
.
values
[
doffset
+
it
->
left
.
i
]
+=
var
.
values
[
doffset
+
k
];
var
.
values
[
doffset
+
it
->
right
.
i
]
+=
var
.
values
[
doffset
+
k
];
break
;
case
AD_MINUS
:
var
.
values
[
doffset
+
it
->
left
.
i
]
+=
var
.
values
[
doffset
+
k
];
var
.
values
[
doffset
+
it
->
right
.
i
]
-=
var
.
values
[
doffset
+
k
];
break
;
case
AD_MULT
:
rval
=
var
.
values
[
voffset
+
it
->
right
.
i
];
lval
=
var
.
values
[
voffset
+
it
->
left
.
i
];
var
.
values
[
doffset
+
it
->
left
.
i
]
+=
var
.
values
[
doffset
+
k
]
*
rval
;
var
.
values
[
doffset
+
it
->
right
.
i
]
+=
var
.
values
[
doffset
+
k
]
*
lval
;
break
;
case
AD_DIV
:
rval
=
var
.
values
[
voffset
+
it
->
right
.
i
];
lval
=
var
.
values
[
voffset
+
it
->
left
.
i
];
var
.
values
[
doffset
+
it
->
left
.
i
]
+=
var
.
values
[
doffset
+
k
]
/
rval
;
var
.
values
[
doffset
+
it
->
right
.
i
]
-=
var
.
values
[
doffset
+
k
]
*
lval
/
(
rval
*
rval
);
break
;
case
AD_POW
:
ret
=
var
.
values
[
voffset
+
k
];
rval
=
var
.
values
[
voffset
+
it
->
right
.
i
];
lval
=
var
.
values
[
voffset
+
it
->
left
.
i
];
var
.
values
[
doffset
+
it
->
right
.
i
]
+=
var
.
values
[
doffset
+
k
]
*
::
log
(
lval
);
var
.
values
[
doffset
+
it
->
left
.
i
]
+=
var
.
values
[
doffset
+
k
]
*
ret
*
rval
/
lval
;
break
;
case
AD_SQRT
:
ret
=
var
.
values
[
voffset
+
k
];
var
.
values
[
doffset
+
it
->
left
.
i
]
+=
0.5
*
var
.
values
[
doffset
+
k
]
/
ret
;
break
;
case
AD_ABS
:
lval
=
var
.
values
[
voffset
+
it
->
left
.
i
];
var
.
values
[
doffset
+
it
->
left
.
i
]
+=
var
.
values
[
doffset
+
k
]
*
(
lval
>
0.0
?
1.0
:
-
1.0
);
break
;
case
AD_EXP
:
ret
=
var
.
values
[
voffset
+
k
];
var
.
values
[
doffset
+
it
->
left
.
i
]
+=
var
.
values
[
doffset
+
k
]
*
ret
;
break
;
case
AD_LOG
:
lval
=
var
.
values
[
voffset
+
it
->
left
.
i
];
var
.
values
[
doffset
+
it
->
left
.
i
]
+=
var
.
values
[
doffset
+
k
]
/
lval
;
break
;
case
AD_SIN
:
lval
=
var
.
values
[
voffset
+
it
->
left
.
i
];
var
.
values
[
doffset
+
it
->
left
.
i
]
+=
var
.
values
[
doffset
+
k
]
*
::
cos
(
lval
);
break
;
case
AD_COS
:
lval
=
var
.
values
[
voffset
+
it
->
left
.
i
];
var
.
values
[
doffset
+
it
->
left
.
i
]
-=
var
.
values
[
doffset
+
k
]
*
::
sin
(
lval
);
break
;
case
AD_COND_MARK
:
break
;
case
AD_COND_TYPE
:
break
;
case
AD_CONST
:
break
;
case
AD_MES
:
break
;
case
AD_VAL
:
{
expr
&
next
=
*
it
->
right
.
e
;
next
.
current_stencil
.
resize
(
1
);
next
.
current_stencil
[
0
]
=
stencil_pair
(
e
,
1.0
);
next
.
resize_for_stencil
();
var
.
values
[
doffset
+
it
->
left
.
i
]
+=
var
.
values
[
doffset
+
k
]
*
EvaluateSub
(
next
,
0
,
element
,
user_data
);
break
;
}
default:
if
(
it
->
op
>=
AD_FUNC
)
{}
else
if
(
it
->
op
>=
AD_TABLE
)
{
lval
=
var
.
values
[
voffset
+
it
->
left
.
i
];
var
.
values
[
doffset
+
it
->
left
.
i
]
+=
var
.
values
[
doffset
+
k
]
*
reg_tables
[
it
->
op
]
->
get_derivative
(
lval
);
}
else
if
(
it
->
op
>=
AD_STNCL
)
{
for
(
INMOST_DATA_ENUM_TYPE
j
=
0
;
j
<
it
->
left
.
e
->
current_stencil
.
size
();
++
j
)
if
(
it
->
left
.
e
->
current_stencil
[
j
].
first
!=
NULL
)
{
DerivativeFill
(
*
it
->
left
.
e
,
j
,
ENUMUNDEF
,
entries
,
var
.
values
[
doffset
+
k
]
*
it
->
left
.
e
->
current_stencil
[
j
].
second
,
user_data
);
}
}
else
if
(
it
->
op
>=
AD_CTAG
)
{}
else
if
(
it
->
op
>=
AD_TAG
)
{
if
(
isDynamicValid
(
e
,
it
->
op
))
{
entries
[
GetDynamicIndex
(
e
,
it
->
op
,
it
->
left
.
i
)]
+=
var
.
values
[
doffset
+
k
];
}
}
else
assert
(
false
);
}
}
while
(
k
--
!=
0
);
}
INMOST_DATA_REAL_TYPE
Automatizator
::
EvaluateSub
(
expr
&
var
,
INMOST_DATA_ENUM_TYPE
element
,
INMOST_DATA_ENUM_TYPE
parent
,
void
*
user_data
)
{
INMOST_DATA_ENUM_TYPE
k
=
0
,
offset
=
var
.
values_offset
(
element
);
Storage
*
e
=
var
.
current_stencil
[
element
].
first
;
expr
::
expr_data
*
arr
=
&
var
.
data
[
0
],
*
it
;
//for (expr::data_type::iterator it = var.data.begin(); it != var.data.end(); ++it)
do
{
it
=
arr
+
k
;
switch
(
it
->
op
)
{
case
AD_EXT
:
assert
(
parent
!=
ENUMUNDEF
);
var
.
values
[
offset
+
k
]
=
it
->
left
.
e
->
values
[
it
->
left
.
e
->
values_offset
(
parent
)
+
it
->
right
.
i
];
break
;
case
AD_COND
:
{
expr
&
next
=
var
.
values
[
offset
+
it
->
left
.
i
]
>
0.0
?
*
it
->
right
.
q
->
left
.
e
:
*
it
->
right
.
q
->
right
.
e
;
next
.
current_stencil
.
resize
(
1
);
next
.
current_stencil
[
0
]
=
stencil_pair
(
e
,
1.0
);
next
.
resize_for_stencil
();
var
.
values
[
offset
+
k
]
=
EvaluateSub
(
next
,
0
,
element
,
user_data
);
}
break
;
case
AD_PLUS
:
var
.
values
[
offset
+
k
]
=
var
.
values
[
offset
+
it
->
left
.
i
]
+
var
.
values
[
offset
+
it
->
right
.
i
];
break
;
case
AD_MINUS
:
var
.
values
[
offset
+
k
]
=
var
.
values
[
offset
+
it
->
left
.
i
]
-
var
.
values
[
offset
+
it
->
right
.
i
];
break
;
case
AD_MULT
:
var
.
values
[
offset
+
k
]
=
var
.
values
[
offset
+
it
->
left
.
i
]
*
var
.
values
[
offset
+
it
->
right
.
i
];
break
;
case
AD_DIV
:
var
.
values
[
offset
+
k
]
=
var
.
values
[
offset
+
it
->
left
.
i
]
/
var
.
values
[
offset
+
it
->
right
.
i
];
break
;
case
AD_POW
:
var
.
values
[
offset
+
k
]
=
::
pow
(
var
.
values
[
offset
+
it
->
left
.
i
],
var
.
values
[
offset
+
it
->
right
.
i
]);
break
;
case
AD_SQRT
:
var
.
values
[
offset
+
k
]
=
::
sqrt
(
var
.
values
[
offset
+
it
->
left
.
i
]);
break
;
case
AD_ABS
:
var
.
values
[
offset
+
k
]
=
::
fabs
(
var
.
values
[
offset
+
it
->
left
.
i
]);
break
;
case
AD_EXP
:
var
.
values
[
offset
+
k
]
=
::
exp
(
var
.
values
[
offset
+
it
->
left
.
i
]);
break
;
case
AD_LOG
:
var
.
values
[
offset
+
k
]
=
::
log
(
var
.
values
[
offset
+
it
->
left
.
i
]);
break
;
case
AD_SIN
:
var
.
values
[
offset
+
k
]
=
::
sin
(
var
.
values
[
offset
+
it
->
left
.
i
]);
break
;
case
AD_COS
:
var
.
values
[
offset
+
k
]
=
::
cos
(
var
.
values
[
offset
+
it
->
left
.
i
]);
break
;
case
AD_CONST
:
var
.
values
[
offset
+
k
]
=
it
->
left
.
r
;
break
;
case
AD_COND_TYPE
:
var
.
values
[
offset
+
k
]
=
((
e
->
GetElementType
()
&
it
->
left
.
i
)
?
1.0
:
-
1.0
);
break
;
case
AD_COND_MARK
:
var
.
values
[
offset
+
k
]
=
e
->
GetMarker
(
it
->
left
.
i
)
?
1.0
:
-
1.0
;
break
;
case
AD_MES
:
assert
(
!
(
e
->
GetElementType
()
&
(
ESET
|
MESH
)));
m
->
GetGeometricData
(
static_cast
<
Element
*>
(
e
),
MEASURE
,
&
var
.
values
[
offset
+
k
]);
break
;
case
AD_VAL
:
var
.
values
[
offset
+
k
]
=
var
.
values
[
offset
+
it
->
left
.
i
];
break
;
default:
if
(
it
->
op
>=
AD_FUNC
)
var
.
values
[
offset
+
k
]
=
reg_funcs
[
it
->
op
].
func
(
e
,
user_data
);
else
if
(
it
->
op
>=
AD_TABLE
)
var
.
values
[
offset
+
k
]
=
reg_tables
[
it
->
op
]
->
get_value
(
var
.
values
[
offset
+
it
->
left
.
i
]);
else
if
(
it
->
op
>=
AD_STNCL
)
{
it
->
left
.
e
->
current_stencil
.
clear
();
GetStencil
(
it
->
op
,
e
,
user_data
,
it
->
left
.
e
->
current_stencil
);
it
->
left
.
e
->
resize_for_stencil
();
var
.
values
[
offset
+
k
]
=
0.0
;
for
(
INMOST_DATA_ENUM_TYPE
j
=
0
;
j
<
it
->
left
.
e
->
current_stencil
.
size
();
++
j
)
if
(
it
->
left
.
e
->
current_stencil
[
j
].
first
!=
NULL
)
var
.
values
[
offset
+
k
]
+=
EvaluateSub
(
*
it
->
left
.
e
,
j
,
ENUMUNDEF
,
user_data
)
*
it
->
left
.
e
->
current_stencil
[
j
].
second
;
}
else
if
(
it
->
op
>=
AD_CTAG
)
var
.
values
[
offset
+
k
]
=
GetStaticValue
(
e
,
it
->
op
,
it
->
left
.
i
);
else
if
(
it
->
op
>=
AD_TAG
)
var
.
values
[
offset
+
k
]
=
GetDynamicValue
(
e
,
it
->
op
,
it
->
left
.
i
);
else
assert
(
false
);
}
//k++;
}
while
(
++
k
!=
var
.
data
.
size
());
return
var
.
values
[
offset
+
var
.
data
.
size
()
-
1
];
}
INMOST_DATA_REAL_TYPE
Automatizator
::
Evaluate
(
expr
&
var
,
Storage
*
e
,
void
*
user_data
)
{
var
.
current_stencil
.
resize
(
1
);
var
.
current_stencil
[
0
]
=
stencil_pair
(
e
,
1.0
);
var
.
resize_for_stencil
();
return
EvaluateSub
(
var
,
0
,
ENUMUNDEF
,
user_data
);
}
INMOST_DATA_REAL_TYPE
Automatizator
::
Derivative
(
expr
&
var
,
Storage
*
e
,
Solver
::
Row
&
out
,
Storage
::
real
multiply
,
void
*
user_data
)
{
INMOST_DATA_REAL_TYPE
ret
;
var
.
current_stencil
.
resize
(
1
);
var
.
current_stencil
[
0
]
=
stencil_pair
(
e
,
1.0
);
var
.
resize_for_stencil
();
ret
=
EvaluateSub
(
var
,
0
,
ENUMUNDEF
,
user_data
);
DerivativeFill
(
var
,
0
,
ENUMUNDEF
,
out
,
multiply
,
user_data
);
return
ret
*
multiply
;
}
#else
INMOST_DATA_REAL_TYPE
Automatizator
::
DerivativePrecompute
(
const
expr
&
var
,
Storage
*
e
,
precomp_values_t
&
values
,
void
*
user_data
)
INMOST_DATA_REAL_TYPE
Automatizator
::
DerivativePrecompute
(
const
expr
&
var
,
Storage
*
e
,
precomp_values_t
&
values
,
void
*
user_data
)
{
{
/*
assert
(
var
.
op
!=
AD_NONE
);
assert
(
var
.
op
!=
AD_NONE
);
INMOST_DATA_REAL_TYPE
lval
,
rval
,
ret
=
0.0
;
INMOST_DATA_REAL_TYPE
lval
,
rval
,
ret
=
0.0
;
switch
(
var
.
op
)
switch
(
var
.
op
)
{
{
case
AD_COND_TYPE
:
lval
=
(
e
->
GetElementType
()
&
reinterpret_cast
<
ElementType
>
(
var
.
left
))
?
1.0
:
-
1.0
;
return
lval
;
case
AD_COND_MARK
:
lval
=
e
->
GetMarker
(
reinterpret_cast
<
MIDType
>
(
var
.
left
))
?
1.0
:
-
1.0
;
return
lval
;
case
AD_COND
:
case
AD_COND
:
lval
=
Evaluate
(
*
var
.
left
,
e
,
user_data
);
lval
=
Evaluate
(
*
var
.
left
,
e
,
user_data
);
rval
=
DerivativePrecompute
(
*
(
lval
>
0.0
?
var
.
right
->
left
:
var
.
right
->
right
),
e
,
values
,
user_data
);
rval
=
DerivativePrecompute
(
*
(
lval
>
0.0
?
var
.
right
->
left
:
var
.
right
->
right
),
e
,
values
,
user_data
);
...
@@ -54,6 +256,11 @@ namespace INMOST
...
@@ -54,6 +256,11 @@ namespace INMOST
ret
=
::
pow
(
lval
,
rval
);
ret
=
::
pow
(
lval
,
rval
);
values
.
push_back
(
ret
);
values
.
push_back
(
ret
);
return
ret
*
var
.
coef
;
return
ret
*
var
.
coef
;
case
AD_SQRT
:
lval
=
DerivativePrecompute
(
*
var
.
left
,
e
,
values
,
user_data
);
ret
=
::
sqrt
(
lval
);
values
.
push_back
(
ret
);
return
ret
*
var
.
coef
;
case
AD_INV
:
case
AD_INV
:
lval
=
DerivativePrecompute
(
*
var
.
left
,
e
,
values
,
user_data
);
lval
=
DerivativePrecompute
(
*
var
.
left
,
e
,
values
,
user_data
);
values
.
push_back
(
lval
);
values
.
push_back
(
lval
);
...
@@ -85,6 +292,11 @@ namespace INMOST
...
@@ -85,6 +292,11 @@ namespace INMOST
assert
(
!
(
e
->
GetElementType
()
&
(
ESET
|
MESH
)));
assert
(
!
(
e
->
GetElementType
()
&
(
ESET
|
MESH
)));
m
->
GetGeometricData
(
static_cast
<
Element
*>
(
e
),
MEASURE
,
&
ret
);
m
->
GetGeometricData
(
static_cast
<
Element
*>
(
e
),
MEASURE
,
&
ret
);
return
ret
*
var
.
coef
;
return
ret
*
var
.
coef
;
case
AD_VAL
:
lval
=
DerivativePrecompute
(
*
var
.
left
,
e
,
values
,
user_data
);
rval
=
Evaluate
(
*
var
.
left
,
e
,
user_data
);
values
.
push_back
(
rval
);
return
lval
*
var
.
coef
;
}
}
if
(
var
.
op
>=
AD_FUNC
)
if
(
var
.
op
>=
AD_FUNC
)
{
{
...
@@ -100,14 +312,14 @@ namespace INMOST
...
@@ -100,14 +312,14 @@ namespace INMOST
}
}
else
if
(
var
.
op
>=
AD_STNCL
)
else
if
(
var
.
op
>=
AD_STNCL
)
{
{
stencil_kind_domain st = reg_stencils[var.op];
stencil_kind_domain
&
st
=
reg_stencils
[
var
.
op
];
assert
(
st
.
domainmask
==
0
||
e
->
GetMarker
(
st
.
domainmask
));
assert
(
st
.
domainmask
==
0
||
e
->
GetMarker
(
st
.
domainmask
));
if
(
st
.
kind
==
0
)
if
(
st
.
kind
==
0
)
{
{
Storage
::
reference_array
elems
=
e
->
ReferenceArray
(
static_cast
<
stencil_tag
*>
(
st
.
link
)
->
elements
);
Storage
::
reference_array
elems
=
e
->
ReferenceArray
(
static_cast
<
stencil_tag
*>
(
st
.
link
)
->
elements
);
Storage
::
real_array
coefs
=
e
->
RealArray
(
static_cast
<
stencil_tag
*>
(
st
.
link
)
->
coefs
);
Storage
::
real_array
coefs
=
e
->
RealArray
(
static_cast
<
stencil_tag
*>
(
st
.
link
)
->
coefs
);
assert
(
elems
.
size
()
==
coefs
.
size
());
assert
(
elems
.
size
()
==
coefs
.
size
());
for (INMOST_DATA_ENUM_TYPE k = 0; k < elems.size(); ++k)
for
(
INMOST_DATA_ENUM_TYPE
k
=
0
;
k
<
elems
.
size
();
++
k
)
if
(
elems
[
k
]
!=
NULL
)
{
{
lval
=
DerivativePrecompute
(
*
var
.
left
,
elems
[
k
],
values
,
user_data
);
lval
=
DerivativePrecompute
(
*
var
.
left
,
elems
[
k
],
values
,
user_data
);
ret
+=
lval
*
coefs
[
k
];
ret
+=
lval
*
coefs
[
k
];
...
@@ -117,7 +329,7 @@ namespace INMOST
...
@@ -117,7 +329,7 @@ namespace INMOST
{
{
stencil_pairs
get_st
;
stencil_pairs
get_st
;
reinterpret_cast
<
stencil_callback
>
(
st
.
link
)(
e
,
get_st
,
user_data
);
reinterpret_cast
<
stencil_callback
>
(
st
.
link
)(
e
,
get_st
,
user_data
);
for (INMOST_DATA_ENUM_TYPE k = 0; k < get_st.size(); ++k)
for
(
INMOST_DATA_ENUM_TYPE
k
=
0
;
k
<
get_st
.
size
();
++
k
)
if
(
get_st
[
k
].
first
!=
NULL
)
{
{
lval
=
DerivativePrecompute
(
*
var
.
left
,
get_st
[
k
].
first
,
values
,
user_data
);
lval
=
DerivativePrecompute
(
*
var
.
left
,
get_st
[
k
].
first
,
values
,
user_data
);
ret
+=
lval
*
get_st
[
k
].
second
;
ret
+=
lval
*
get_st
[
k
].
second
;
...
@@ -138,17 +350,18 @@ namespace INMOST
...
@@ -138,17 +350,18 @@ namespace INMOST
return
ret
*
var
.
coef
;
return
ret
*
var
.
coef
;
}
}
assert
(
false
);
assert
(
false
);
*/
return
0.0
;
return
0.0
;
}
}
//! returns offset from the end of precomputed values
//! returns offset from the end of precomputed values
void
Automatizator
::
DerivativeFill
(
const
expr
&
var
,
Storage
*
e
,
Solver
::
Row
&
entries
,
precomp_values_t
&
values
,
INMOST_DATA_REAL_TYPE
multval
,
void
*
user_data
)
void
Automatizator
::
DerivativeFill
(
const
expr
&
var
,
Storage
*
e
,
Solver
::
Row
&
entries
,
precomp_values_t
&
values
,
INMOST_DATA_REAL_TYPE
multval
,
void
*
user_data
)
{
{
/*
assert
(
var
.
op
!=
AD_NONE
);
assert
(
var
.
op
!=
AD_NONE
);
INMOST_DATA_REAL_TYPE
lval
,
rval
,
ret
;
INMOST_DATA_REAL_TYPE
lval
,
rval
,
ret
;
switch
(
var
.
op
)
switch
(
var
.
op
)
{
{
case
AD_COND_MARK
:
case
AD_COND_TYPE
:
return
;
case
AD_COND
:
case
AD_COND
:
lval
=
values
.
back
();
values
.
pop_back
();
lval
=
values
.
back
();
values
.
pop_back
();
DerivativeFill
(
*
(
lval
>
0.0
?
var
.
right
->
left
:
var
.
right
->
right
),
e
,
entries
,
values
,
multval
*
var
.
coef
,
user_data
);
DerivativeFill
(
*
(
lval
>
0.0
?
var
.
right
->
left
:
var
.
right
->
right
),
e
,
entries
,
values
,
multval
*
var
.
coef
,
user_data
);
...
@@ -180,6 +393,10 @@ namespace INMOST
...
@@ -180,6 +393,10 @@ namespace INMOST
DerivativeFill
(
*
var
.
right
,
e
,
entries
,
values
,
multval
*
ret
*
::
log
(
lval
)
*
var
.
coef
,
user_data
);
DerivativeFill
(
*
var
.
right
,
e
,
entries
,
values
,
multval
*
ret
*
::
log
(
lval
)
*
var
.
coef
,
user_data
);
DerivativeFill
(
*
var
.
left
,
e
,
entries
,
values
,
multval
*
ret
*
rval
/
lval
*
var
.
coef
,
user_data
);
DerivativeFill
(
*
var
.
left
,
e
,
entries
,
values
,
multval
*
ret
*
rval
/
lval
*
var
.
coef
,
user_data
);
return
;
return
;
case
AD_SQRT
:
ret
=
values
.
back
();
values
.
pop_back
();
DerivativeFill
(
*
var
.
left
,
e
,
entries
,
values
,
0.5
*
multval
/
ret
*
var
.
coef
,
user_data
);
return
;
case
AD_INV
:
case
AD_INV
:
lval
=
values
.
back
();
values
.
pop_back
();
lval
=
values
.
back
();
values
.
pop_back
();
DerivativeFill
(
*
var
.
left
,
e
,
entries
,
values
,
-
multval
/
(
lval
*
lval
)
*
var
.
coef
,
user_data
);
DerivativeFill
(
*
var
.
left
,
e
,
entries
,
values
,
-
multval
/
(
lval
*
lval
)
*
var
.
coef
,
user_data
);
...
@@ -206,6 +423,10 @@ namespace INMOST
...
@@ -206,6 +423,10 @@ namespace INMOST
return
;
return
;
case
AD_CONST
:
return
;
case
AD_CONST
:
return
;
case
AD_MES
:
return
;
case
AD_MES
:
return
;
case
AD_VAL
:
rval
=
values
.
back
();
values
.
pop_back
();
DerivativeFill
(
*
var
.
left
,
e
,
entries
,
values
,
multval
*
var
.
coef
*
rval
,
user_data
);
return
;
}
}
if
(
var
.
op
>=
AD_FUNC
)
if
(
var
.
op
>=
AD_FUNC
)
{
{
...
@@ -219,21 +440,21 @@ namespace INMOST
...
@@ -219,21 +440,21 @@ namespace INMOST
}
}
else
if
(
var
.
op
>=
AD_STNCL
)
else
if
(
var
.
op
>=
AD_STNCL
)
{
{
stencil_kind_domain st = reg_stencils[var.op];
stencil_kind_domain
&
st
=
reg_stencils
[
var
.
op
];
assert
(
st
.
domainmask
==
0
||
e
->
GetMarker
(
st
.
domainmask
));
assert
(
st
.
domainmask
==
0
||
e
->
GetMarker
(
st
.
domainmask
));
if
(
st
.
kind
==
0
)
if
(
st
.
kind
==
0
)
{
{
Storage
::
reference_array
elems
=
e
->
ReferenceArray
(
static_cast
<
stencil_tag
*>
(
st
.
link
)
->
elements
);
Storage
::
reference_array
elems
=
e
->
ReferenceArray
(
static_cast
<
stencil_tag
*>
(
st
.
link
)
->
elements
);
Storage
::
real_array
coefs
=
e
->
RealArray
(
static_cast
<
stencil_tag
*>
(
st
.
link
)
->
coefs
);
Storage
::
real_array
coefs
=
e
->
RealArray
(
static_cast
<
stencil_tag
*>
(
st
.
link
)
->
coefs
);
assert
(
elems
.
size
()
==
coefs
.
size
());
assert
(
elems
.
size
()
==
coefs
.
size
());
for (INMOST_DATA_ENUM_TYPE k = elems.size(); k > 0; --k)
for
(
INMOST_DATA_ENUM_TYPE
k
=
elems
.
size
();
k
>
0
;
--
k
)
if
(
elems
[
k
-
1
]
!=
NULL
)
DerivativeFill
(
*
var
.
left
,
elems
[
k
-
1
],
entries
,
values
,
var
.
coef
*
coefs
[
k
-
1
]
*
multval
,
user_data
);
DerivativeFill
(
*
var
.
left
,
elems
[
k
-
1
],
entries
,
values
,
var
.
coef
*
coefs
[
k
-
1
]
*
multval
,
user_data
);
}
}
else
if
(
st
.
kind
==
1
)
else
if
(
st
.
kind
==
1
)
{
{
stencil_pairs
get_st
;
stencil_pairs
get_st
;
reinterpret_cast
<
stencil_callback
>
(
st
.
link
)(
e
,
get_st
,
user_data
);
reinterpret_cast
<
stencil_callback
>
(
st
.
link
)(
e
,
get_st
,
user_data
);
for (INMOST_DATA_ENUM_TYPE k = get_st.size(); k > 0; --k)
for
(
INMOST_DATA_ENUM_TYPE
k
=
get_st
.
size
();
k
>
0
;
--
k
)
if
(
get_st
[
k
-
1
].
first
!=
NULL
)
DerivativeFill
(
*
var
.
left
,
get_st
[
k
-
1
].
first
,
entries
,
values
,
var
.
coef
*
get_st
[
k
-
1
].
second
*
multval
,
user_data
);
DerivativeFill
(
*
var
.
left
,
get_st
[
k
-
1
].
first
,
entries
,
values
,
var
.
coef
*
get_st
[
k
-
1
].
second
*
multval
,
user_data
);
}
}
return
;
return
;
...
@@ -244,74 +465,76 @@ namespace INMOST
...
@@ -244,74 +465,76 @@ namespace INMOST
if
(
isDynamicValid
(
e
,
var
.
op
))
if
(
isDynamicValid
(
e
,
var
.
op
))
{
{
INMOST_DATA_ENUM_TYPE
ind
=
GetDynamicIndex
(
e
,
var
.
op
,
*
(
INMOST_DATA_ENUM_TYPE
*
)(
&
var
.
left
));
INMOST_DATA_ENUM_TYPE
ind
=
GetDynamicIndex
(
e
,
var
.
op
,
*
(
INMOST_DATA_ENUM_TYPE
*
)(
&
var
.
left
));
std::cout << ind << ", " << multval*var.coef << std::endl;
entries
[
ind
]
+=
multval
*
var
.
coef
;
entries
[
ind
]
+=
multval
*
var
.
coef
;
}
}
return
;
return
;
}
}
assert
(
false
);
assert
(
false
);
*/
return
;
return
;
}
}
INMOST_DATA_REAL_TYPE
Automatizator
::
Evaluate
(
const
expr
&
var
,
Storage
*
e
,
void
*
user_data
)
INMOST_DATA_REAL_TYPE
Automatizator
::
Evaluate
(
const
expr
&
var
,
Storage
*
e
,
void
*
user_data
)
{
{
return
EvaluateSub
(
var
,
e
,
user_data
,
NULL
);
assert
(
var
.
op
!=
AD_NONE
);
}
switch
(
var
.
op
)
INMOST_DATA_REAL_TYPE
Automatizator
::
EvaluateSub
(
const
expr
&
var
,
Storage
*
e
,
void
*
user_data
,
values_container
*
parent_values
)
{
values_container
values
(
var
.
data
.
size
());
INMOST_DATA_ENUM_TYPE
k
=
0
;
for
(
expr
::
data_type
::
const_iterator
it
=
var
.
data
.
begin
();
it
!=
var
.
data
.
end
();
++
it
)
{
{
switch
(
it
->
op
)
case
AD_COND_MARK
:
return
e
->
GetMarker
(
reinterpret_cast
<
MIDType
>
(
var
.
left
))
?
1.0
:
-
1.0
;
case
AD_COND_TYPE
:
return
(
e
->
GetElementType
()
&
reinterpret_cast
<
ElementType
>
(
var
.
left
))
?
1.0
:
-
1.0
;
case
AD_COND
:
return
Evaluate
(
*
(
Evaluate
(
*
var
.
left
,
e
,
user_data
)
>
0.0
?
var
.
right
->
left
:
var
.
right
->
right
),
e
,
user_data
)
*
var
.
coef
;
case
AD_PLUS
:
return
(
Evaluate
(
*
var
.
left
,
e
,
user_data
)
+
Evaluate
(
*
var
.
right
,
e
,
user_data
))
*
var
.
coef
;
case
AD_MINUS
:
return
(
Evaluate
(
*
var
.
left
,
e
,
user_data
)
-
Evaluate
(
*
var
.
right
,
e
,
user_data
))
*
var
.
coef
;
case
AD_MULT
:
return
(
Evaluate
(
*
var
.
left
,
e
,
user_data
)
*
Evaluate
(
*
var
.
right
,
e
,
user_data
))
*
var
.
coef
;
case
AD_DIV
:
return
(
Evaluate
(
*
var
.
left
,
e
,
user_data
)
/
Evaluate
(
*
var
.
right
,
e
,
user_data
))
*
var
.
coef
;
case
AD_INV
:
return
var
.
coef
/
Evaluate
(
*
var
.
left
,
e
,
user_data
);
case
AD_POW
:
return
::
pow
(
Evaluate
(
*
var
.
left
,
e
,
user_data
),
Evaluate
(
*
var
.
right
,
e
,
user_data
))
*
var
.
coef
;
case
AD_SQRT
:
return
::
sqrt
(
Evaluate
(
*
var
.
left
,
e
,
user_data
))
*
var
.
coef
;
case
AD_ABS
:
return
::
fabs
(
Evaluate
(
*
var
.
left
,
e
,
user_data
))
*
var
.
coef
;
case
AD_EXP
:
return
::
exp
(
Evaluate
(
*
var
.
left
,
e
,
user_data
))
*
var
.
coef
;
case
AD_LOG
:
return
::
log
(
Evaluate
(
*
var
.
left
,
e
,
user_data
))
*
var
.
coef
;
case
AD_SIN
:
return
::
sin
(
Evaluate
(
*
var
.
left
,
e
,
user_data
))
*
var
.
coef
;
case
AD_COS
:
return
::
cos
(
Evaluate
(
*
var
.
left
,
e
,
user_data
))
*
var
.
coef
;
case
AD_CONST
:
return
var
.
coef
;
case
AD_MES
:
assert
(
!
(
e
->
GetElementType
()
&
(
ESET
|
MESH
)));
Storage
::
real
ret
;
m
->
GetGeometricData
(
static_cast
<
Element
*>
(
e
),
MEASURE
,
&
ret
);
return
ret
*
var
.
coef
;
case
AD_VAL
:
return
Evaluate
(
*
var
.
left
,
e
,
user_data
)
*
var
.
coef
;
}
if
(
var
.
op
>=
AD_FUNC
)
return
reg_funcs
[
var
.
op
].
func
(
e
,
user_data
);
if
(
var
.
op
>=
AD_TABLE
)
return
reg_tables
[
var
.
op
]
->
get_value
(
Evaluate
(
*
var
.
left
,
e
,
user_data
))
*
var
.
coef
;
if
(
var
.
op
>=
AD_STNCL
)
{
INMOST_DATA_REAL_TYPE
ret
=
0.0
;
stencil_kind_domain
&
st
=
reg_stencils
[
var
.
op
];
assert
(
st
.
domainmask
==
0
||
e
->
GetMarker
(
st
.
domainmask
));
if
(
st
.
kind
==
0
)
{
{
case
AD_EXT
:
values
[
k
]
=
(
*
parent_values
)[
it
->
right
.
i
];
break
;
Storage
::
reference_array
elems
=
e
->
ReferenceArray
(
static_cast
<
stencil_tag
*>
(
st
.
link
)
->
elements
);
case
AD_COND
:
Storage
::
real_array
coefs
=
e
->
RealArray
(
static_cast
<
stencil_tag
*>
(
st
.
link
)
->
coefs
);
if
(
values
[
it
->
left
.
i
]
>
0.0
)
assert
(
elems
.
size
()
==
coefs
.
size
());
values
[
k
]
=
EvaluateSub
(
*
it
->
right
.
q
->
left
.
e
,
e
,
user_data
,
&
values
);
for
(
INMOST_DATA_ENUM_TYPE
k
=
0
;
k
<
elems
.
size
();
++
k
)
if
(
elems
[
k
]
!=
NULL
)
else
ret
+=
var
.
coef
*
Evaluate
(
*
var
.
left
,
elems
[
k
],
user_data
)
*
coefs
[
k
];
values
[
k
]
=
EvaluateSub
(
*
it
->
right
.
q
->
right
.
e
,
e
,
user_data
,
&
values
);
break
;
case
AD_PLUS
:
values
[
k
]
=
values
[
it
->
left
.
i
]
+
values
[
it
->
right
.
i
];
break
;
case
AD_MINUS
:
values
[
k
]
=
values
[
it
->
left
.
i
]
-
values
[
it
->
right
.
i
];
break
;
case
AD_MULT
:
values
[
k
]
=
values
[
it
->
left
.
i
]
*
values
[
it
->
right
.
i
];
break
;
case
AD_DIV
:
values
[
k
]
=
values
[
it
->
left
.
i
]
/
values
[
it
->
right
.
i
];
break
;
case
AD_POW
:
values
[
k
]
=
::
pow
(
values
[
it
->
left
.
i
],
values
[
it
->
right
.
i
]);
break
;
case
AD_ABS
:
values
[
k
]
=
::
fabs
(
values
[
it
->
left
.
i
]);
break
;
case
AD_EXP
:
values
[
k
]
=
::
exp
(
values
[
it
->
left
.
i
]);
break
;
case
AD_LOG
:
values
[
k
]
=
::
log
(
values
[
it
->
left
.
i
]);
break
;
case
AD_SIN
:
values
[
k
]
=
::
sin
(
values
[
it
->
left
.
i
]);
break
;
case
AD_COS
:
values
[
k
]
=
::
cos
(
values
[
it
->
left
.
i
]);
break
;
case
AD_CONST
:
values
[
k
]
=
it
->
left
.
r
;
break
;
case
AD_MES
:
assert
(
!
(
e
->
GetElementType
()
&
(
ESET
|
MESH
)));
m
->
GetGeometricData
(
static_cast
<
Element
*>
(
e
),
MEASURE
,
&
values
[
k
]);
break
;
default:
if
(
it
->
op
>=
AD_FUNC
)
values
[
k
]
=
reg_funcs
[
it
->
op
].
func
(
e
,
user_data
);
else
if
(
it
->
op
>=
AD_TABLE
)
values
[
k
]
=
reg_tables
[
it
->
op
]
->
get_value
(
values
[
it
->
left
.
i
]);
else
if
(
it
->
op
>=
AD_STNCL
)
{
stencil_pairs
get_st
;
GetStencil
(
it
->
op
,
e
,
user_data
,
get_st
);
values
[
k
]
=
0.0
;
for
(
INMOST_DATA_ENUM_TYPE
k
=
0
;
k
<
get_st
.
size
();
++
k
)
values
[
k
]
+=
EvaluateSub
(
*
it
->
left
.
e
,
get_st
[
k
].
first
,
user_data
,
NULL
)
*
get_st
[
k
].
second
;
}
else
if
(
it
->
op
>=
AD_CTAG
)
values
[
k
]
=
GetStaticValue
(
e
,
it
->
op
,
it
->
left
.
i
);
else
if
(
it
->
op
>=
AD_TAG
)
values
[
k
]
=
GetDynamicValue
(
e
,
it
->
op
,
it
->
left
.
i
);
else
assert
(
false
);
}
}
k
++
;
else
if
(
st
.
kind
==
1
)
{
stencil_pairs
get_st
;
reinterpret_cast
<
stencil_callback
>
(
st
.
link
)(
e
,
get_st
,
user_data
);
for
(
INMOST_DATA_ENUM_TYPE
k
=
0
;
k
<
get_st
.
size
();
++
k
)
if
(
get_st
[
k
].
first
!=
NULL
)
ret
+=
var
.
coef
*
Evaluate
(
*
var
.
left
,
get_st
[
k
].
first
,
user_data
)
*
get_st
[
k
].
second
;
}
return
ret
;
}
}
return
values
[
var
.
data
.
size
()
-
1
];
if
(
var
.
op
>=
AD_CTAG
)
return
GetStaticValue
(
e
,
var
.
op
,
*
(
INMOST_DATA_ENUM_TYPE
*
)(
&
var
.
left
))
*
var
.
coef
;
if
(
var
.
op
>=
AD_TAG
)
return
GetDynamicValue
(
e
,
var
.
op
,
*
(
INMOST_DATA_ENUM_TYPE
*
)(
&
var
.
left
))
*
var
.
coef
;
assert
(
false
);
return
0.0
;
}
}
INMOST_DATA_REAL_TYPE
Automatizator
::
Derivative
(
const
expr
&
var
,
Storage
*
e
,
Solver
::
Row
&
out
,
void
*
user_data
)
INMOST_DATA_REAL_TYPE
Automatizator
::
Derivative
(
const
expr
&
var
,
Storage
*
e
,
Solver
::
Row
&
out
,
Storage
::
real
multiply
,
void
*
user_data
)
{
{
INMOST_DATA_REAL_TYPE
ret
;
INMOST_DATA_REAL_TYPE
ret
;
precomp_values_t
values
;
precomp_values_t
values
;
ret
=
DerivativePrecompute
(
var
,
e
,
values
,
user_data
);
ret
=
DerivativePrecompute
(
var
,
e
,
values
,
user_data
);
DerivativeFill
(
var
,
e
,
out
,
values
,
1.0
,
user_data
);
DerivativeFill
(
var
,
e
,
out
,
values
,
multiply
,
user_data
);
return
ret
;
return
ret
*
multiply
;
}
}
#endif