FiberVISH 0.2
Fish - The Fiber Bundle API for the Vish Visualization Shell
InterpolatedVectorDerivative.cpp

Demonstration of the interpolated derivative of a vector field.

Demonstration of the interpolated derivative of a vector field.

#include <vector/CubicIpol.hpp>
#include <vector/LinearIpol.hpp>
#include <vector/MultiArray.hpp>
#include <vector/Interpolate.hpp>
#include <eagle/Vector.hpp>
#include <eagle/Matrix.hpp>
#include <eagle/QuadraticMatrix.hpp>
#include <time.h>
using namespace std;
using namespace Eagle;
using namespace Fiber;
// Demonstration on how to compute the partial derivative of
// the nth component of a multi-valued (e.g. vector or tensor)
// field by the mth coordinate function.
static int DemonstrateTensorDerivative()
{
// symbolic names for coordinates
enum { x=0, y=1, z=2 };
// untyped tensorial object
// typed tensorial object:
// Symmetric tensor
// General tensor of rank two.
// The data storage of the tensor field is an automatic variable.
// This tensor field, consisting of 1000 points, is defined over
// a three-dimensional base manifold with 10 vertices in each dimension.
MultiArray<3, Tensor> G(TensorStorage, MIndex(10,10,10) );
// Initialize all elements through the MultiArray interface
InitValue(0,0) = InitValue(1,1) = InitValue(2,2) = 1;
InitValue(0,1) = InitValue(1,2) = InitValue(2,0) = 0;
G.set( InitValue );
// Define some point of interesting.
I = 5,6,7;
// modify the data values there
G[ I ] (2,2) = 2;
// Determine the vectorial index of the tensorial component
int Component = Tensor::mem_index(2,2);
// Define field referring to the third component of the tensor field.
// Note that we need to view the tensorial data as vector here, thus
// requiring the vec() call.
Iterator<double> GnmPtr( G.count()*Tensor::SIZE, G.ptr(), Component);
cout << G[I];
// Define a multidimensional array on the view pointer.
// Note that the view pointer could also be constructed as local argument.
Gnm_t Gnm( GnmPtr, G.Size() );
{
// Interpolate<3, double, LinearIpol<double> , double, NoDelimiter<double>, x>
for(double fr=0; fr<2; fr+=0.1)
{
point = 5.1, 6.2, 7 + fr;
cout << "Cubic interpolated derived tensor component Gmn,k " << point << " " << Gnm_k.eval() << endl
;
}
}
// Starting point
q = 5.1, 6.8, 5.03;
// Velocity
v = 0.01,0.02,.2;
clock_t start, finish;
start = clock();
for(int is = 0; is<40000; is++)
{
//
// Computation of coordinate acceleration from metric tensor at specific point.
//
// path parameter increment
double ds = 0.001;
#ifndef EXPLICIT_CHRISTOFFEL_OPERATIONS
//FixedArray<3, FixedArray<3, FixedArray<3, double> > > g_ij_k;
#if 0
dG.eval( g_ij_k );
#elif 0
//const char C[4] = "xyz";
{for(int j=0; j<3; j++)
for(int i=j; i<3; i++)
{
int Component = Tensor::mem_index(i,j);
Gnm_t Gnm( &G.storage().vec(), Component, G.Size() );
#if 1
D(Gnm, q);
D.eval( g_ij_k(i,j) );
#else
#if 1
#else
#endif
#if 0
g_ij_k[i][j][0] = Gij_0.eval();
g_ij_k[i][j][1] = Gij_1.eval();
g_ij_k[i][j][2] = Gij_2.eval();
#else
g_ij_k(i,j)[0] = Gij_0.eval();
g_ij_k(i,j)[1] = Gij_1.eval();
g_ij_k(i,j)[2] = Gij_2.eval();
#endif
// if (!is)
// {
// cout << "g_"<< C[i] << C[j] << ",x=" << g_ij_k[i][j][0] << " ";
// cout << "g_"<< C[i] << C[j] << ",y=" << g_ij_k[i][j][1] << " ";
// cout << "g_"<< C[i] << C[j] << ",z=" << g_ij_k[i][j][2] << " ";
// }
#endif
}
}
#endif
//FixedArray<3, FixedArray<3, FixedArray<3, double> > > G_ijk;
// Gij_k = gik,j + gjk,i - gij,k
{for(int j=0; j<3; j++)
for(int i=j; i<3; i++)
for(int k=0; k<3; k++)
{
// G_ijk[i][j][k] = g_ij_k[i][k][j] + g_ij_k[j][k][i] - g_ij_k[i][j][k];
G_ijk(i,j)[k] = g_ij_k(i,k)[j] + g_ij_k(j,k)[i] - g_ij_k(i,j)[k];
}
}
const Tensor&Glocal = Gfield.eval();
// Compute coordinate co-acceleration via Lower Christoffels
//
// dv_k = G_{ij_k} v^i v^j
//
{for(int k=0; k<3; k++)
{
dv[k] = 0;
for(int j=0; j<3; j++)
{
double G_ijk_vi = 0;
for(int i=0; i<3; i++)
{
G_ijk_vi += G_ijk(i,j)[k] * v[i];
}
G_ijk_vi *= v[j];
dv[k] += G_ijk_vi;
}
}
}
Glocal_q.GaussDecompose(PV);
// coordinate acceleration, \ddot q
Glocal_q.GaussSolve(PV, dv, a );
cout << " Coordinate Acceleration:" << a << endl;
#else // EXPLICIT_CHRISTOFFEL_OPERATIONS
Chris.getAcceleration(a, v);
#endif
// v == dq/ds
// a == dv/ds;
#pragma message "this next operator should work - CHECK!"
//q += v*ds;
v += a*ds;
if (is %1000 == 0)
cout << "v="<<v<<"\t q="<<q<<endl;
}
finish = clock();
printf( "Geodesic computation: %2.1f seconds\n", (double)(finish - start) / CLOCKS_PER_SEC );
cout << "Final: v="<<v<<"\t q="<<q<<endl;
cout << "EXPECT v=(0.00628477,0.088151,0.180334) q=(5.3987,9.70163,12.4076)" << endl;
/*
----- P4 1.6GHz, Cubic Christoffel Ipol, Intel C++, Optimize:
Geodesic computation: 5.7 seconds
Final: v=(0.00628477,0.088151,0.180334) q=(5.3987,9.70163,12.4076)
----> Employing symmetry on Christoffel:
Geodesic computation: 4.0 seconds
Final: v=(0.00628477,0.088151,0.180334) q=(5.3987,9.70163,12.4076)
----- P4 1.6GHz, Linear Christoffel Ipol, Intel C++, Optimize:
Geodesic computation: 1.8 seconds
Final: v=(0.00160945,0.00741571,0.0737203) q=(5.38425,7.92392,10.8191)
----- P4 1.6GHz, Cubic Christoffel Ipol, Intel C++, Debug:
Geodesic computation: 56.5 seconds
Final: v=(0.00628477,0.088151,0.180334) q=(5.3987,9.70163,12.4076)
*/
return 1;
}
// Demonstration the computation of geodesics in a numerical tensor field
// and the numerical precision via back-integration to the starting point.
static int DemonstrateGeodesics()
{
// symbolic names for coordinates
enum { x=0, y=1, z=2 };
// typed tensorial object:
// The data storage of the tensor field is an automatic variable.
// This tensor field, consisting of 1000 points, is defined over
// a three-dimensional base manifold with 10 vertices in each dimension.
MultiArray<3, Tensor> G(TensorStorage, MIndex(10,10,10) );
// Initialize all elements through the MultiArray interface
InitValue(0,0) = InitValue(1,1) = InitValue(2,2) = 1;
InitValue(0,1) = InitValue(1,2) = InitValue(2,0) = 0;
G.set( InitValue );
// Modify the data values at some point of interest
G[ MIndex(5,6,7) ] (2,2) = 2;
// Starting point
q = 5.1, 6.8, 5.03;
q0 = q;
// Velocity
v = 0.01,0.02,.2;
v0 = v;
#if 0
// EXCERPT:
#if 1
{
typedef Tensor metric_type;
typedef Tensor* MetricStorage_t;
typedef CubicIpol<metric_type> MetricInterpol;
typedef double CoordinateType;
// metric_type m = G[0];
metric_type m = MetricField[0];
// metric_type m = ND.limit( MetricField[0] );
// metric_type m = MetricField.myDelimiter.limit( MetricField[0] );
//MetricInterpol::interpolate( MetricField, p[2], G.Size[2], MetricField.myDelimiter );
//IpolDerivative<metric_type, MetricInterpol, false>::interpolate(MetricField, p[2], G.Size[2], MetricField.myDelimiter );
// metric_type g = MetricField.eval();
}
#else
clock_t start, finish;
start = clock();
{for(int is = 0; is<40000; is++)
{
// path parameter increment
double ds = 0.001;
// coordinate acceleration, \ddot q
Chris.getCoordinateAcceleration(a, v);
// Euler step
q += v*ds;
v += a*ds;
if (is %1000 == 0)
cout << "v="<<v<<"\t q="<<q<<endl;
}}
finish = clock();
printf( "Geodesic computation: %2.1f seconds\n", (double)(finish - start) / CLOCKS_PER_SEC );
{for(int is = 0; is<40000; is++)
{
// path parameter increment
double ds = -0.001;
// coordinate acceleration, \ddot q
Chris.getCoordinateAcceleration(a, v);
// Euler step
q += v*ds;
v += a*ds;
if (is %1000 == 0)
cout << "v="<<v<<"\t q="<<q<<endl;
}}
cout << "q=" << q << "\t q0=" << q0 << " Diff: " << q-q0 << endl;
cout << "v=" << v << "\t v0=" << v0 << " Diff: " << v-v0 << endl;
double Qerror = norm2(q-q0);
cout << "Qerror =" << Qerror << endl;
assert( Qerror < 1E-8 );
#endif
#endif
return 1;
}
int dVInterpolCheck()
{
int r=0;
// r+=DemonstrateTensorDerivative();
// r+=DemonstrateGeodesics();
return r;
}
basic_ostream< _CharT, _Traits > & endl(basic_ostream< _CharT, _Traits > &__os)
ostream cout
Vectorized vector.
Definition VVector.hpp:288
An iterator with an optional DataCreator, which is just a class to intercept creation of data along a...
Definition CreativeIterator.hpp:34
double norm2(const PhysicalSpace::bivector &v)
Given a fragmented field of curvilinear coordinates, (3D array of coordinates), build a uniform Grid ...
Definition FAQ.dox:2
STL namespace.