539 lines
18 KiB
Plaintext
539 lines
18 KiB
Plaintext
@q $Id: korder_stoch.hweb 418 2005-08-16 15:10:06Z kamenik $ @>
|
|
@q Copyright 2005, Ondra Kamenik @>
|
|
|
|
@*2 Higher order at stochastic steady. Start of {\tt korder\_stoch.h} file.
|
|
|
|
This file defines a number of classes of which |KOrderStoch| is the
|
|
main purpose. Basically, |KOrderStoch| calculates first and higher
|
|
order Taylor expansion of a policy rule at $\sigma>0$ with explicit
|
|
forward $g^{**}$. More formally, we have to solve a policy rule $g$
|
|
from
|
|
$$E_t\left[f(g^{**}(g^*(y^*_t,u_t,\sigma),u_{t+1},\sigma),g(y^*,u_t,\sigma),y^*,u_t)\right]$$
|
|
As an introduction in {\tt approximation.hweb} argues, $g^{**}$ at
|
|
tine $t+1$ must be given from outside. Let the explicit
|
|
$E_t(g^{**}(y^*,u_{t+1},\sigma)$ be equal to $h(y^*,\sigma)$. Then we
|
|
have to solve
|
|
$$f(h(g^*(y^*,u,\sigma),\sigma),g(y,u,\sigma),y,u),$$
|
|
which is much easier than fully implicit system for $\sigma=0$.
|
|
|
|
Besides the class |KOrderStoch|, we declare here also classes for the
|
|
new containers corresponding to
|
|
$f(h(g^*(y^*,u,\sigma),\sigma),g(y,u,\sigma),y,u)$. Further, we
|
|
declare |IntegDerivs| and |StochForwardDerivs| classes which basically
|
|
calculate $h$ as an extrapolation based on an approximation to $g$ at
|
|
lower $\sigma$.
|
|
|
|
@s IntegDerivs int
|
|
@s StochForwardDerivs int
|
|
@s GContainer int
|
|
@s ZContainer int
|
|
@s GXContainer int
|
|
@s ZXContainer int
|
|
@s MatrixAA int
|
|
@s KOrderStoch int
|
|
@s StackContainer int
|
|
@s _Ttype int
|
|
@s _Ctype int
|
|
@s UnfoldedStackContainer int
|
|
@s FoldedStackContainer int
|
|
|
|
@c
|
|
#include "korder.h"
|
|
#include "faa_di_bruno.h"
|
|
#include "journal.h"
|
|
|
|
|
|
@<|IntegDerivs| class declaration@>;
|
|
@<|StochForwardDerivs| class declaration@>;
|
|
@<|GXContainer| class declaration@>;
|
|
@<|ZXContainer| class declaration@>;
|
|
@<|UnfoldedGXContainer| class declaration@>;
|
|
@<|FoldedGXContainer| class declaration@>;
|
|
@<|UnfoldedZXContainer| class declaration@>;
|
|
@<|FoldedZXContainer| class declaration@>;
|
|
@<|MatrixAA| class declaration@>;
|
|
@<|KOrderStoch| class declaration@>;
|
|
|
|
@ This class is a container, which has a specialized constructor
|
|
integrating the policy rule at given $\sigma$.
|
|
|
|
@<|IntegDerivs| class declaration@>=
|
|
template <int t>
|
|
class IntegDerivs : public ctraits<t>::Tgss {
|
|
public:@;
|
|
@<|IntegDerivs| constructor code@>;
|
|
};
|
|
|
|
@ This constuctor integrates a rule (namely its $g^{**}$ part) with
|
|
respect to $u=\tilde\sigma\eta$, and stores to the object the
|
|
derivatives of this integral $h$ at $(y^*,u,\sigma)=(\tilde
|
|
y^*,0,\tilde\sigma)$. The original container of $g^{**}$, the moments of
|
|
the stochastic shocks |mom| and the $\tilde\sigma$ are input.
|
|
|
|
The code follows the following derivation
|
|
\def\lims{\vbox{\baselineskip=0pt\lineskip=1pt
|
|
\setbox0=\hbox{$\scriptstyle n+k=p$}\hbox to\wd0{\hss$\scriptstyle m=0$\hss}\box0}}
|
|
$$
|
|
\eqalign{h(y,\sigma)&=E_t\left[g(y,u',\sigma)\right]=\cr
|
|
&=\tilde y+\sum_{d=1}{1\over d!}\sum_{i+j+k=d}\pmatrix{d\cr i,j,k}\left[g_{y^iu^j\sigma^k}\right]
|
|
(y^*-\tilde y^*)^i\sigma^j\Sigma^j(\sigma-\tilde\sigma)^k\cr
|
|
&=\tilde y+\sum_{d=1}{1\over d!}\sum_{i+m+n+k=d}\pmatrix{d\cr i,m+n,k}
|
|
\left[g_{y^iu^{m+n}\sigma^k}\right]
|
|
\hat y^{*i}\Sigma^{m+n}\pmatrix{m+n\cr m,n}{\tilde\sigma}^m\hat\sigma^{k+n}\cr
|
|
&=\tilde y+\sum_{d=1}{1\over d!}\sum_{i+m+n+k=d}\pmatrix{d\cr i,m,n,k}
|
|
\left[g_{y^iu^{m+n}\sigma^k}\right]
|
|
\Sigma^{m+n}{\tilde\sigma}^m\hat y^{*i}\hat\sigma^{k+n}\cr
|
|
&=\tilde y+\sum_{d=1}{1\over d!}\sum_{i+p=d}\sum_{\lims}\pmatrix{d\cr i,m,n,k}
|
|
\left[g_{y^iu^{m+n}\sigma^k}\right]
|
|
\Sigma^{m+n}{\tilde\sigma}^m\hat y^{*i}\hat\sigma^{k+n}\cr
|
|
&=\tilde y+\sum_{d=1}{1\over d!}\sum_{i+p=d}\pmatrix{d\cr i,p}
|
|
\left[\sum_{\lims}\pmatrix{p\cr n,k}{1\over m!}
|
|
\left[g_{y^iu^{m+n}\sigma^k}\right]
|
|
\Sigma^{m+n}{\tilde\sigma}^m\right]\hat y^{*i}\hat\sigma^{k+n},
|
|
}
|
|
$$
|
|
where $\pmatrix{a\cr b_1,\ldots, b_n}$ is a generalized combination
|
|
number, $p=k+n$, $\hat\sigma=\sigma-\tilde\sigma$, $\hat
|
|
y^*=y^*-\tilde y$, and we dropped writing the multidimensional indexes
|
|
in Einstein summation.
|
|
|
|
This implies that
|
|
$$h_{y^i\sigma^p}=\sum_{\lims}\pmatrix{p\cr n,k}{1\over m!}
|
|
\left[g_{y^iu^{m+n}\sigma^k}\right]
|
|
\Sigma^{m+n}{\tilde\sigma}^m$$
|
|
and this is exactly what the code does.
|
|
|
|
@<|IntegDerivs| constructor code@>=
|
|
IntegDerivs(int r, const IntSequence& nvs, const _Tgss& g, const __Tm& mom,
|
|
double at_sigma)
|
|
: ctraits<t>::Tgss(4)
|
|
{
|
|
int maxd = g.getMaxDim();
|
|
for (int d = 1; d <= maxd; d++) {
|
|
for (int i = 0; i <= d; i++) {
|
|
int p = d-i;
|
|
Symmetry sym(i,0,0,p);
|
|
_Ttensor* ten = new _Ttensor(r, TensorDimens(sym, nvs));
|
|
@<calculate derivative $h_{y^i\sigma^p}$@>;
|
|
insert(ten);
|
|
}
|
|
}
|
|
}
|
|
|
|
@ This code calculates
|
|
$$h_{y^i\sigma^p}=\sum_{\lims}\pmatrix{p\cr n,k}{1\over m!}
|
|
\left[g_{y^iu^{m+n}\sigma^k}\right]
|
|
\Sigma^{m+n}{\tilde\sigma}^m$$
|
|
and stores it in |ten|.
|
|
|
|
@<calculate derivative $h_{y^i\sigma^p}$@>=
|
|
ten->zeros();
|
|
for (int n = 0; n <= p; n++) {
|
|
int k = p-n;
|
|
int povern = Tensor::noverk(p,n);
|
|
int mfac = 1;
|
|
for (int m = 0; i+m+n+k <= maxd; m++, mfac*=m) {
|
|
double mult = (pow(at_sigma,m)*povern)/mfac;
|
|
Symmetry sym_mn(i,m+n,0,k);
|
|
if (m+n == 0 && g.check(sym_mn))
|
|
ten->add(mult, *(g.get(sym_mn)));
|
|
if (m+n > 0 && KOrder::is_even(m+n) && g.check(sym_mn)) {
|
|
_Ttensor gtmp(*(g.get(sym_mn)));
|
|
gtmp.mult(mult);
|
|
gtmp.contractAndAdd(1, *ten, *(mom.get(Symmetry(m+n))));
|
|
}
|
|
}
|
|
}
|
|
|
|
@ This class calculates an extrapolation of expectation of forward
|
|
derivatives. It is a container, all calculations are done in a
|
|
constructor.
|
|
|
|
The class calculates derivatives of $E[g(y*,u,\sigma)]$ at $(\bar
|
|
y^*,\bar\sigma)$. The derivatives are extrapolated based on
|
|
derivatives at $(\tilde y^*,\tilde\sigma)$.
|
|
|
|
@<|StochForwardDerivs| class declaration@>=
|
|
template <int t>
|
|
class StochForwardDerivs : public ctraits<t>::Tgss {
|
|
public:@;
|
|
@<|StochForwardDerivs| constructor code@>;
|
|
};
|
|
|
|
@ This is the constructor which performs the integration and the
|
|
extrapolation. Its parameters are: |g| is the container of derivatives
|
|
at $(\tilde y,\tilde\sigma)$; |m| are the moments of stochastic
|
|
shocks; |ydelta| is a difference of the steady states $\bar y-\tilde
|
|
y$; |sdelta| is a difference between new sigma and old sigma
|
|
$\bar\sigma-\tilde\sigma$, and |at_sigma| is $\tilde\sigma$. There is
|
|
no need of inputing the $\tilde y$.
|
|
|
|
We do the operation in four steps:
|
|
\orderedlist
|
|
\li Integrate $g^{**}$, the derivatives are at $(\tilde y,\tilde\sigma)$
|
|
\li Form the (full symmetric) polynomial from the derivatives stacking
|
|
$\left[\matrix{y^*\cr\sigma}\right]$
|
|
\li Centralize this polynomial about $(\bar y,\bar\sigma)$
|
|
\li Recover general symmetry tensors from the (full symmetric) polynomial
|
|
\endorderedlist
|
|
|
|
@<|StochForwardDerivs| constructor code@>=
|
|
StochForwardDerivs(const PartitionY& ypart, int nu,
|
|
const _Tgss& g, const __Tm& m,
|
|
const Vector& ydelta, double sdelta,
|
|
double at_sigma)
|
|
: ctraits<t>::Tgss(4)
|
|
{
|
|
int maxd = g.getMaxDim();
|
|
int r = ypart.nyss();
|
|
|
|
@<make |g_int| be integral of $g^{**}$ at $(\tilde y,\tilde\sigma)$@>;
|
|
@<make |g_int_sym| be full symmetric polynomial from |g_int|@>;
|
|
@<make |g_int_cent| the centralized polynomial about $(\bar y,\bar\sigma)$@>;
|
|
@<pull out general symmetry tensors from |g_int_cent|@>;
|
|
}
|
|
|
|
@ This simply constructs |IntegDerivs| class. Note that the |nvs| of
|
|
the tensors has zero dimensions for shocks, this is because we need to
|
|
make easily stacks of the form $\left[\matrix{y^*\cr\sigma}\right]$ in
|
|
the next step.
|
|
|
|
@<make |g_int| be integral of $g^{**}$ at $(\tilde y,\tilde\sigma)$@>=
|
|
IntSequence nvs(4);
|
|
nvs[0] = ypart.nys(); nvs[1] = 0; nvs[2] = 0; nvs[3] = 1;
|
|
IntegDerivs<t> g_int(r, nvs, g, m, at_sigma);
|
|
|
|
@ Here we just form a polynomial whose unique variable corresponds to
|
|
$\left[\matrix{y^*\cr\sigma}\right]$ stack.
|
|
|
|
@<make |g_int_sym| be full symmetric polynomial from |g_int|@>=
|
|
_Tpol g_int_sym(r, ypart.nys()+1);
|
|
for (int d = 1; d <= maxd; d++) {
|
|
_Ttensym* ten = new _Ttensym(r, ypart.nys()+1, d);
|
|
ten->zeros();
|
|
for (int i = 0; i <= d; i++) {
|
|
int k = d-i;
|
|
if (g_int.check(Symmetry(i,0,0,k)))
|
|
ten->addSubTensor(*(g_int.get(Symmetry(i,0,0,k))));
|
|
}
|
|
g_int_sym.insert(ten);
|
|
}
|
|
|
|
@ Here we centralize the polynomial to $(\bar y,\bar\sigma)$ knowing
|
|
that the polynomial was centralized about $(\tilde
|
|
y,\tilde\sigma)$. This is done by derivating and evaluating the
|
|
derivated polynomial at $(\bar y-\tilde
|
|
y,\bar\sigma-\tilde\sigma)$. The stack of this vector is |delta| in
|
|
the code.
|
|
|
|
@<make |g_int_cent| the centralized polynomial about $(\bar y,\bar\sigma)$@>=
|
|
Vector delta(ypart.nys()+1);
|
|
Vector dy(delta, 0, ypart.nys());
|
|
ConstVector dy_in(ydelta, ypart.nstat, ypart.nys());
|
|
dy = dy_in;
|
|
delta[ypart.nys()] = sdelta;
|
|
_Tpol g_int_cent(r, ypart.nys()+1);
|
|
for (int d = 1; d <= maxd; d++) {
|
|
g_int_sym.derivative(d-1);
|
|
_Ttensym* der = g_int_sym.evalPartially(d, delta);
|
|
g_int_cent.insert(der);
|
|
}
|
|
|
|
@ Here we only recover the general symmetry derivatives from the full
|
|
symmetric polynomial. Note that the derivative get the true |nvs|.
|
|
|
|
@<pull out general symmetry tensors from |g_int_cent|@>=
|
|
IntSequence ss(4);
|
|
ss[0]=ypart.nys(); ss[1]=0; ss[2]=0; ss[3]=1;
|
|
IntSequence pp(4);
|
|
pp[0]=0; pp[1]=1; pp[2]=2; pp[3]=3;
|
|
IntSequence true_nvs(nvs);
|
|
true_nvs[1]=nu; true_nvs[2]=nu;
|
|
for (int d = 1; d <= maxd; d++) {
|
|
if (g_int_cent.check(Symmetry(d))) {
|
|
for (int i = 0; i <= d; i++) {
|
|
Symmetry sym(i, 0, 0, d-i);
|
|
IntSequence coor(sym, pp);
|
|
_Ttensor* ten = new _Ttensor(*(g_int_cent.get(Symmetry(d))), ss, coor,
|
|
TensorDimens(sym, true_nvs));
|
|
insert(ten);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@ This container corresponds to $h(g^*(y,u,\sigma),\sigma)$. Note that
|
|
in our application, the $\sigma$ as a second argument to $h$ will be
|
|
its fourth variable in symmetry, so we have to do four member stack
|
|
having the second and third stack dummy.
|
|
|
|
@<|GXContainer| class declaration@>=
|
|
template <class _Ttype>
|
|
class GXContainer : public GContainer<_Ttype> {
|
|
public:@;
|
|
typedef StackContainerInterface<_Ttype> _Stype;
|
|
typedef typename StackContainer<_Ttype>::_Ctype _Ctype;
|
|
typedef typename StackContainer<_Ttype>::itype itype;
|
|
GXContainer(const _Ctype* gs, int ngs, int nu)
|
|
: GContainer<_Ttype>(gs, ngs, nu)@+ {}
|
|
@<|GXContainer::getType| code@>;
|
|
};
|
|
|
|
@ This routine corresponds to this stack:
|
|
$$\left[\matrix{g^*(y,u,\sigma)\cr dummy\cr dummy\cr\sigma}\right]$$
|
|
|
|
@<|GXContainer::getType| code@>=
|
|
itype getType(int i, const Symmetry& s) const
|
|
{
|
|
if (i == 0)
|
|
if (s[2] > 0)
|
|
return _Stype::zero;
|
|
else
|
|
return _Stype::matrix;
|
|
if (i == 1)
|
|
return _Stype::zero;
|
|
if (i == 2)
|
|
return _Stype::zero;
|
|
if (i == 3)
|
|
if (s == Symmetry(0,0,0,1))
|
|
return _Stype::unit;
|
|
else
|
|
return _Stype::zero;
|
|
|
|
KORD_RAISE("Wrong stack index in GXContainer::getType");
|
|
}
|
|
|
|
|
|
@ This container corresponds to $f(H(y,u,\sigma),g(y,u,sigma),y,u)$,
|
|
where the $H$ has the size (number of rows) as $g^{**}$. Since it is
|
|
very simmilar to |ZContainer|, we inherit form it and override only
|
|
|getType| method.
|
|
|
|
@<|ZXContainer| class declaration@>=
|
|
template <class _Ttype>
|
|
class ZXContainer : public ZContainer<_Ttype> {
|
|
public:@;
|
|
typedef StackContainerInterface<_Ttype> _Stype;
|
|
typedef typename StackContainer<_Ttype>::_Ctype _Ctype;
|
|
typedef typename StackContainer<_Ttype>::itype itype;
|
|
ZXContainer(const _Ctype* gss, int ngss, const _Ctype* g, int ng, int ny, int nu)
|
|
: ZContainer<_Ttype>(gss, ngss, g, ng, ny, nu) @+{}
|
|
@<|ZXContainer::getType| code@>;
|
|
};
|
|
|
|
@ This |getType| method corresponds to this stack:
|
|
$$\left[\matrix{H(y,u,\sigma)\cr g(y,u,\sigma)\cr y\cr u}\right]$$
|
|
|
|
@<|ZXContainer::getType| code@>=
|
|
itype getType(int i, const Symmetry& s) const
|
|
{
|
|
if (i == 0)
|
|
if (s[2] > 0)
|
|
return _Stype::zero;
|
|
else
|
|
return _Stype::matrix;
|
|
if (i == 1)
|
|
if (s[2] > 0)
|
|
return _Stype::zero;
|
|
else
|
|
return _Stype::matrix;
|
|
if (i == 2)
|
|
if (s == Symmetry(1,0,0,0))
|
|
return _Stype::unit;
|
|
else
|
|
return _Stype::zero;
|
|
if (i == 3)
|
|
if (s == Symmetry(0,1,0,0))
|
|
return _Stype::unit;
|
|
else
|
|
return _Stype::zero;
|
|
|
|
KORD_RAISE("Wrong stack index in ZXContainer::getType");
|
|
}
|
|
|
|
@
|
|
@<|UnfoldedGXContainer| class declaration@>=
|
|
class UnfoldedGXContainer : public GXContainer<UGSTensor>, public UnfoldedStackContainer {
|
|
public:@;
|
|
typedef TensorContainer<UGSTensor> _Ctype;
|
|
UnfoldedGXContainer(const _Ctype* gs, int ngs, int nu)
|
|
: GXContainer<UGSTensor>(gs, ngs, nu)@+ {}
|
|
};
|
|
|
|
@
|
|
@<|FoldedGXContainer| class declaration@>=
|
|
class FoldedGXContainer : public GXContainer<FGSTensor>, public FoldedStackContainer {
|
|
public:@;
|
|
typedef TensorContainer<FGSTensor> _Ctype;
|
|
FoldedGXContainer(const _Ctype* gs, int ngs, int nu)
|
|
: GXContainer<FGSTensor>(gs, ngs, nu)@+ {}
|
|
};
|
|
|
|
@
|
|
@<|UnfoldedZXContainer| class declaration@>=
|
|
class UnfoldedZXContainer : public ZXContainer<UGSTensor>, public UnfoldedStackContainer {
|
|
public:@;
|
|
typedef TensorContainer<UGSTensor> _Ctype;
|
|
UnfoldedZXContainer(const _Ctype* gss, int ngss, const _Ctype* g, int ng, int ny, int nu)
|
|
: ZXContainer<UGSTensor>(gss, ngss, g, ng, ny, nu)@+ {}
|
|
};
|
|
|
|
@
|
|
@<|FoldedZXContainer| class declaration@>=
|
|
class FoldedZXContainer : public ZXContainer<FGSTensor>, public FoldedStackContainer {
|
|
public:@;
|
|
typedef TensorContainer<FGSTensor> _Ctype;
|
|
FoldedZXContainer(const _Ctype* gss, int ngss, const _Ctype* g, int ng, int ny, int nu)
|
|
: ZXContainer<FGSTensor>(gss, ngss, g, ng, ny, nu)@+ {}
|
|
};
|
|
|
|
@ This matrix corresponds to
|
|
$$\left[f_{y}\right]+ \left[0
|
|
\left[f_{y^{**}_+}\right]\cdot\left[h^{**}_{y^*}\right] 0\right]$$
|
|
This is very the same as |MatrixA|, the only difference that the
|
|
|MatrixA| is constructed from whole $h_{y^*}$, not only from
|
|
$h^{**}_{y^*}$, hence the new abstraction.
|
|
|
|
@<|MatrixAA| class declaration@>=
|
|
class MatrixAA : public PLUMatrix {
|
|
public:@;
|
|
MatrixAA(const FSSparseTensor& f, const IntSequence& ss,
|
|
const TwoDMatrix& gyss, const PartitionY& ypart);
|
|
};
|
|
|
|
|
|
@ This class calculates derivatives of $g$ given implicitly by
|
|
$f(h(g^*(y,u,\sigma),\sigma),g(y,u,\sigma),y,u)$, where $h(y,\sigma)$
|
|
is given from outside.
|
|
|
|
Structurally, the class is very similar to |KOrder|, but calculations
|
|
are much easier. The two constructors construct an object from sparse
|
|
derivatives of $f$, and derivatives of $h$. The caller must ensure
|
|
that the both derivatives are done at the same point.
|
|
|
|
The calculation for order $k$ (including $k=1$) is done by a call
|
|
|performStep(k)|. The derivatives can be retrived by |getFoldDers()|
|
|
or |getUnfoldDers()|.
|
|
|
|
@<|KOrderStoch| class declaration@>=
|
|
class KOrderStoch {
|
|
protected:@;
|
|
IntSequence nvs;
|
|
PartitionY ypart;
|
|
Journal& journal;
|
|
UGSContainer _ug;
|
|
FGSContainer _fg;
|
|
UGSContainer _ugs;
|
|
FGSContainer _fgs;
|
|
UGSContainer _uG;
|
|
FGSContainer _fG;
|
|
const UGSContainer* _uh;
|
|
const FGSContainer* _fh;
|
|
UnfoldedZXContainer _uZstack;
|
|
FoldedZXContainer _fZstack;
|
|
UnfoldedGXContainer _uGstack;
|
|
FoldedGXContainer _fGstack;
|
|
const TensorContainer<FSSparseTensor>& f;
|
|
MatrixAA matA;
|
|
public:@;
|
|
KOrderStoch(const PartitionY& ypart, int nu, const TensorContainer<FSSparseTensor>& fcont,
|
|
const FGSContainer& hh, Journal& jr);
|
|
KOrderStoch(const PartitionY& ypart, int nu, const TensorContainer<FSSparseTensor>& fcont,
|
|
const UGSContainer& hh, Journal& jr);
|
|
@<|KOrderStoch::performStep| templated code@>;
|
|
const FGSContainer& getFoldDers() const
|
|
{@+ return _fg;@+}
|
|
const UGSContainer& getUnfoldDers() const
|
|
{@+ return _ug;@+}
|
|
protected:@;
|
|
@<|KOrderStoch::faaDiBrunoZ| templated code@>;
|
|
@<|KOrderStoch::faaDiBrunoG| templated code@>;
|
|
@<|KOrderStoch| convenience access methods@>;
|
|
};
|
|
|
|
@ This calculates a derivative of $f(G(y,u,\sigma),g(y,u,\sigma),y,u)$
|
|
of a given symmetry.
|
|
|
|
@<|KOrderStoch::faaDiBrunoZ| templated code@>=
|
|
template <int t>
|
|
_Ttensor* faaDiBrunoZ(const Symmetry& sym) const
|
|
{
|
|
JournalRecordPair pa(journal);
|
|
pa << "Faa Di Bruno ZX container for " << sym << endrec;
|
|
_Ttensor* res = new _Ttensor(ypart.ny(), TensorDimens(sym, nvs));
|
|
FaaDiBruno bruno(journal);
|
|
bruno.calculate(Zstack<t>(), f, *res);
|
|
return res;
|
|
}
|
|
|
|
@ This calculates a derivative of
|
|
$G(y,u,\sigma)=h(g^*(y,u,\sigma),\sigma)$ of a given symmetry.
|
|
|
|
@<|KOrderStoch::faaDiBrunoG| templated code@>=
|
|
template <int t>
|
|
_Ttensor* faaDiBrunoG(const Symmetry& sym) const
|
|
{
|
|
JournalRecordPair pa(journal);
|
|
pa << "Faa Di Bruno GX container for " << sym << endrec;
|
|
TensorDimens tdims(sym, nvs);
|
|
_Ttensor* res = new _Ttensor(ypart.nyss(), tdims);
|
|
FaaDiBruno bruno(journal);
|
|
bruno.calculate(Gstack<t>(), h<t>(), *res);
|
|
return res;
|
|
}
|
|
|
|
@ This retrives all $g$ derivatives of a given dimension from implicit
|
|
$f(h(g^*(y,u,\sigma),\sigma),g(y,u,\sigma),y,u)$. It suppose that all
|
|
derivatives of smaller dimensions have been retrieved.
|
|
|
|
So, we go through all symmetries $s$, calculate $G_s$ conditional on
|
|
$g_s=0$, insert the derivative to the $G$ container, then calculate
|
|
$F_s$ conditional on $g_s=0$. This is a righthand side. The left hand
|
|
side is $matA\cdot g_s$. The $g_s$ is retrieved as
|
|
$$g_s=-matA^{-1}\cdot RHS.$$ Finally we have to update $G_s$ by
|
|
calling |Gstack<t>().multAndAdd(1, h<t>(), *G_sym)|.
|
|
|
|
@<|KOrderStoch::performStep| templated code@>=
|
|
template <int t>
|
|
void performStep(int order)
|
|
{
|
|
int maxd = g<t>().getMaxDim();
|
|
KORD_RAISE_IF(order-1 != maxd && (order != 1 || maxd != -1),
|
|
"Wrong order for KOrderStoch::performStep");
|
|
SymmetrySet ss(order, 4);
|
|
for (symiterator si(ss); !si.isEnd(); ++si) {
|
|
if ((*si)[2] == 0) {
|
|
JournalRecordPair pa(journal);
|
|
pa << "Recovering symmetry " << *si << endrec;
|
|
|
|
_Ttensor* G_sym = faaDiBrunoG<t>(*si);
|
|
G<t>().insert(G_sym);
|
|
|
|
_Ttensor* g_sym = faaDiBrunoZ<t>(*si);
|
|
g_sym->mult(-1.0);
|
|
matA.multInv(*g_sym);
|
|
g<t>().insert(g_sym);
|
|
gs<t>().insert(new _Ttensor(ypart.nstat, ypart.nys(), *g_sym));
|
|
|
|
Gstack<t>().multAndAdd(1, h<t>(), *G_sym);
|
|
}
|
|
}
|
|
}
|
|
|
|
@
|
|
@<|KOrderStoch| convenience access methods@>=
|
|
template<int t> _Tg& g();
|
|
template<int t> const _Tg& g() const;
|
|
template<int t> _Tgs& gs();
|
|
template<int t> const _Tgs& gs() const;
|
|
template<int t> const _Tgss& h() const;
|
|
template<int t> _TG& G();
|
|
template<int t> const _TG& G() const;
|
|
template<int t> _TZXstack& Zstack();
|
|
template<int t> const _TZXstack& Zstack() const;
|
|
template<int t> _TGXstack& Gstack();
|
|
template<int t> const _TGXstack& Gstack() const;
|
|
|
|
|
|
@ End of {\tt korder\_stoch.h} file.
|