Beispiel #1
0
tmp
<
    GeometricField
    <
        typename outerProduct<vector,Type>::type, fvPatchField, volMesh
    >
>
grad
(
    const tmp<GeometricField<Type, fvsPatchField, surfaceMesh> >& tssf
)
{
    typedef typename outerProduct<vector, Type>::type GradType;
    tmp<GeometricField<GradType, fvPatchField, volMesh> > Grad
    (
        fvc::grad(tssf())
    );
    tssf.clear();
    return Grad;
}
Beispiel #2
0
//*****************************************************************************
//
//
// *
//=============================================================================
float SJCNoise::
Eval(const float x, const float y, const float z)
//=============================================================================
{
  int	  ix = (int)floor(x);
  float   dx = x - ix;
  int	  iy = (int)floor(y);
  float   dy = y - iy;
  int	  iz = (int)floor(z);
  float   dz = z - iz;
  
  ix &= ( PERM_SIZE - 1 );
  iy &= ( PERM_SIZE - 1 );
  iz &= ( PERM_SIZE - 1 );
  
  float   w000 = Grad(ix, iy, iz, dx, dy, dz);
  float   w010 = Grad(ix, iy+1, iz, dx, dy-1.0f, dz);
  float   w100 = Grad(ix+1, iy, iz, dx-1.0f, dy, dz);
  float   w110 = Grad(ix+1, iy+1, iz, dx-1.0f, dy-1.0f, dz);
  float   w001 = Grad(ix, iy, iz+1, dx, dy, dz-1.0f);
  float   w011 = Grad(ix, iy+1, iz+1, dx, dy-1.0f, dz-1.0f);
  float   w101 = Grad(ix+1, iy, iz+1, dx-1.0f, dy, dz-1.0f);
  float   w111 = Grad(ix+1, iy+1, iz+1, dx-1.0f, dy-1.0f, dz-1.0f);
  
  float   ux = NoiseWeight(dx);
  float   uy = NoiseWeight(dy);
  float   uz = NoiseWeight(dz);
  
  float   x00 = ( 1 - ux ) * w000 + ux * w100;
  float   x10 = ( 1 - ux ) * w010 + ux * w110;
  float   x01 = ( 1 - ux ) * w001 + ux * w101;
  float   x11 = ( 1 - ux ) * w011 + ux * w111;
  float   y0 = ( 1 - uy ) * x00 + uy * x10;
  float   y1 = ( 1 - uy ) * x01 + uy * x11;
  return ( 1 - uz ) * y0 + uz * y1;
}
Beispiel #3
0
PreconditionerAS<space_type,coef_space_type>::PreconditionerAS( std::string t,
                                                                space_ptrtype Xh,
                                                                coef_space_ptrtype Mh,
                                                                BoundaryConditions bcFlags,
                                                                std::string const& p,
                                                                sparse_matrix_ptrtype Pm,
                                                                double k )
    :
        M_type( AS ),
        M_Xh( Xh ),
        M_Vh(Xh->template functionSpace<0>() ),
        M_Qh(Xh->template functionSpace<1>() ),
        M_Mh( Mh ),
        M_Vh_indices( M_Vh->nLocalDofWithGhost() ),
        M_Qh_indices( M_Qh->nLocalDofWithGhost() ),
        M_Qh3_indices( Dim ),
        A(backend()->newVector(M_Vh)),
        B(backend()->newVector(M_Vh)),
        C(backend()->newVector(M_Vh)),
        M_r(backend()->newVector(M_Vh)),
        M_r_t(backend()->newVector(M_Vh)),
        M_uout(backend()->newVector(M_Vh)),
        M_diagPm(backend()->newVector(M_Vh)),
        //M_t(backend()->newVector(M_Vh)),
        U( M_Vh, "U" ),
        M_mu(M_Mh, "mu"),
        M_er(M_Mh, "er"),
        M_bcFlags( bcFlags ),
        M_prefix( p ),
        M_k(k),
        M_g(1.-k*k)
{
    tic();
    LOG(INFO) << "[PreconditionerAS] setup starts";
    this->setMatrix( Pm ); // Needed only if worldComm > 1

    // QH3 : Lagrange vectorial space type
    M_Qh3 = lag_v_space_type::New(Xh->mesh());

    M_qh3_elt = M_Qh3->element();
    M_qh_elt = M_Qh->element();
    M_vh_elt = M_Vh->element();

    // Block 11.1
    M_s = backend()->newVector(M_Qh3);
    M_y = backend()->newVector(M_Qh3);

    // Block 11.2
    M_z = backend()->newVector(M_Qh);
    M_t = backend()->newVector(M_Qh);

    // Create the interpolation and keep only the matrix
    auto pi_curl = I(_domainSpace=M_Qh3, _imageSpace=M_Vh);
    auto Igrad   = Grad( _domainSpace=M_Qh, _imageSpace=M_Vh);

    M_P = pi_curl.matPtr();
    M_C = Igrad.matPtr();

    M_Pt = backend()->newMatrix(M_Qh3,M_Vh);
    M_Ct = backend()->newMatrix(M_Qh3,M_Vh);

    M_P->transpose(M_Pt,MATRIX_TRANSPOSE_UNASSEMBLED);
    M_C->transpose(M_Ct,MATRIX_TRANSPOSE_UNASSEMBLED);

    LOG(INFO) << "size of M_C = " << M_C->size1() << ", " << M_C->size2() << std::endl;
    LOG(INFO) << "size of M_P = " << M_P->size1() << ", " << M_P->size2() << std::endl;

    // Create vector of indices to create subvectors/matrices
    std::iota( M_Vh_indices.begin(), M_Vh_indices.end(), 0 ); // Vh indices in Xh
    std::iota( M_Qh_indices.begin(), M_Qh_indices.end(), M_Vh->nLocalDofWithGhost() ); // Qh indices in Xh

    // "Components" of Qh3
    auto Qh3_dof_begin = M_Qh3->dof()->dofPointBegin();
    auto Qh3_dof_end = M_Qh3->dof()->dofPointEnd();

    int dof_comp, dof_idx;
    for( auto it = Qh3_dof_begin; it!= Qh3_dof_end; it++ )
    {
        dof_comp = it->template get<2>(); //Component
        dof_idx = it->template get<1>(); //Global index
        M_Qh3_indices[dof_comp].push_back( dof_idx );
    }

    // Subvectors for M_y (per component)
    M_y1 = M_y->createSubVector(M_Qh3_indices[0], true);
    M_y2 = M_y->createSubVector(M_Qh3_indices[1], true);
#if FEELPP_DIM == 3
    M_y3 = M_y->createSubVector(M_Qh3_indices[2], true);
#endif
    
    // Subvectors for M_s (per component)
    M_s1 = M_y->createSubVector(M_Qh3_indices[0], true);
    M_s2 = M_y->createSubVector(M_Qh3_indices[1], true);
#if FEELPP_DIM == 3
    M_s3 = M_y->createSubVector(M_Qh3_indices[2], true);
#endif

    this->setType ( t );
    toc( "[PreconditionerAS] setup done ", FLAGS_v > 0 );
}
Beispiel #4
0
void Problem::CheckGradHessian(const Variable *xin) const
{
	UseGrad = true;
	UseHess = true;
	integer length;
	double normxi;
	double t, fx, fy;
	double *X, *Y;
	Vector *etax;
	Variable *x = xin->ConstructEmpty();
	xin->CopyTo(x);
	if (Domain->GetIsIntrinsic())
		etax = Domain->GetEMPTYINTR()->ConstructEmpty();
	else
		etax = Domain->GetEMPTYEXTR()->ConstructEmpty();
	etax->RandUnform();
	Vector *xi = etax->ConstructEmpty();
	Vector *gfx = etax->ConstructEmpty();
	Vector *Hv = etax->ConstructEmpty();
	Variable *y = x->ConstructEmpty();
	fx = f(x);
	Grad(x, gfx);
	gfx->CopyTo(etax);//--
	//double *etaxTV = etax->ObtainWriteEntireData();///---
	//integer nnn = etax->Getlength();
	//for (integer i = 0; i < nnn; i++)//--
	//{
	//	etaxTV[i] = sin(static_cast<double> (i) / (etax->Getlength() - 1) / 2);
	//}
	//for (integer i = 0; i < 5; i++)//---
	//	etaxTV[nnn - 1 - i] = 0;//--

	//etax->Print("etax:");//--
	Domain->Projection(x, etax, xi);
	normxi = sqrt(Domain->Metric(x, xi, xi));
	Domain->ScaleTimesVector(x, 100.0 / normxi, xi, xi); // initial length of xi is 100
	//xi->Print("xi:");//---
	// the length of xi variances from 100 to 100*2^(-35) approx 6e-9
	t = 1;
	length = 35;
	X = new double [length * 2];
	Y = X + length;
	for (integer i = 0; i < length; i++)
	{
		Domain->Retraction(x, xi, y);
		fy = f(y);
		HessianEta(x, xi, Hv);
		Y[i] = log(fabs(fy - fx - Domain->Metric(x, gfx, xi) - 0.5 * Domain->Metric(x, xi, Hv)));
		X[i] = 0.5 * log(Domain->Metric(x, xi, xi));
		Rprintf("i:%d,|eta|:%.3e,(fy-fx)/<gfx,eta>:%.3e,(fy-fx-<gfx,eta>)/<0.5 eta, Hessian eta>:%.3e\n", i, 
			sqrt(Domain->Metric(x, xi, xi)), (fy-fx)/Domain->Metric(x, gfx, xi), 
			(fy - fx - Domain->Metric(x, gfx, xi)) / (0.5 * Domain->Metric(x, xi, Hv)));
		Domain->ScaleTimesVector(x, 0.5, xi, xi);
	}

	Rcpp::Rcout << "CHECK GRADIENT:" << std::endl;
	Rcpp::Rcout << "\tSuppose the point is not a critical point." << std::endl;
	Rcpp::Rcout << "\tIf there exists an interval of |eta| such that (fy - fx) / <gfx, eta>" << std::endl;
	Rcpp::Rcout << "\tapproximates ONE, then the gradient is probably correct!" << std::endl;

	Rcpp::Rcout << "CHECK THE ACTION OF THE HESSIAN (PRESUME GRADIENT IS CORRECT):" << std::endl;
	Rcpp::Rcout << "\tSuppose the retraction is second order or the point is a critical point." << std::endl;
	Rcpp::Rcout << "\tIf there exists an interval of |eta| such that (fy-fx-<gfx,eta>)/<0.5 eta, Hessian eta>" << std::endl;
	Rcpp::Rcout << "\tapproximates ONE, then the action of Hessian is probably correct." << std::endl;

	////TEST IDEA2: 
	//for (integer i = 1; i < length - 1; i++)
	//	Rprintf("log(|eta|):%.3e, slope:%.3e\n", X[i], (Y[i + 1] - Y[i - 1]) / (X[i + 1] - X[i - 1]));
	//Rcpp::Rcout << "CHECK GRADIENT:" << std::endl;
	//Rcpp::Rcout << "\tIf there exists an interval of |eta| such that the slopes " << std::endl;
	//Rcpp::Rcout << "\tapproximate TWO, then the gradient is probably correct!" << std::endl;

	//Rcpp::Rcout << "CHECK THE ACTION OF THE HESSIAN (PRESUME GRADIENT IS CORRECT AND" << std::endl;
	//Rcpp::Rcout << "THE COST FUNCTION IS NOT ONLY QUADRATIC):" << std::endl;
	//Rcpp::Rcout << "\tIf there exists an interval of |eta| such that the slopes" << std::endl;
	//Rcpp::Rcout << "\tapproximate THREE, then the action of Hessian is probably correct." << std::endl;

	//x->Print("1, x:", false);//---
	delete xi;
	//x->Print("2, x:", false);//---
	//gfx->Print("2, gfx:", false);//---
	delete gfx;
	//x->Print("3, x:", false);//---
	delete y;
	//x->Print("4, x:", false);//---
	delete Hv;
	//x->Print("5, x:", false);//---
	delete[] X;
	delete etax;
	//x->Print("x:", false);//---
	delete x;
};
CFlightVisualiser::CFlightVisualiser(QWidget *parent) :
    CFlightVisualiser(parent, Point3D(100, 100, 100), Point2D(100, 250), Point3D(500, 500, 500),  Vector3D(Grad(0), Grad(0)))
{

}
Beispiel #6
0
namespace XLEMath
{
    class Grad
    {
    public:
        float x, y, z, w;

        Grad(float ix, float iy, float iz)
            { x = ix; y = iy; z = iz; }

        Grad(float ix, float iy, float iz, float iw)
            { x = ix; y = iy; z = iz; w = iw; }
    };

    Grad grad3[] = 
    {
        Grad(1,1,0), Grad(-1,1,0), Grad(1,-1,0), Grad(-1,-1,0),
        Grad(1,0,1), Grad(-1,0,1), Grad(1,0,-1), Grad(-1,0,-1),
        Grad(0,1,1), Grad(0,-1,1), Grad(0,1,-1), Grad(0,-1,-1)
    };

    Grad grad4[]= 
    {
        Grad(0,1,1,1), Grad(0,1,1,-1), Grad(0,1,-1,1), Grad(0,1,-1,-1),
        Grad(0,-1,1,1), Grad(0,-1,1,-1), Grad(0,-1,-1,1), Grad(0,-1,-1,-1),
        Grad(1,0,1,1), Grad(1,0,1,-1), Grad(1,0,-1,1), Grad(1,0,-1,-1),
        Grad(-1,0,1,1), Grad(-1,0,1,-1), Grad(-1,0,-1,1), Grad(-1,0,-1,-1),
        Grad(1,1,0,1), Grad(1,1,0,-1), Grad(1,-1,0,1), Grad(1,-1,0,-1),
        Grad(-1,1,0,1), Grad(-1,1,0,-1), Grad(-1,-1,0,1), Grad(-1,-1,0,-1),
        Grad(1,1,1,0), Grad(1,1,-1,0), Grad(1,-1,1,0), Grad(1,-1,-1,0),
        Grad(-1,1,1,0), Grad(-1,1,-1,0), Grad(-1,-1,1,0), Grad(-1,-1,-1,0)
    };

    short p[] = {
        151,160,137,91,90,15,
        131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
        190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
        88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
        77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
        102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
        135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
        5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
        223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
        129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
        251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
        49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
        138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180};

    // To remove the need for index wrapping, float the permutation table length
    static short perm[512];
    static short permMod12[512];
    static bool permDoneInit = false;

    static void InitPerm()
    {
        if (permDoneInit) return;
        permDoneInit = true;

        for(int i=0; i<512; i++)
        {
            perm[i]=p[i & 255];
            permMod12[i] = (short)(perm[i] % 12);
        }
    }

        // Skewing and unskewing factors for 2, 3, and 4 dimensions
    static float F2 = 0.5f*(XlSqrt(3.0f)-1.0f);
    static float G2 = (3.0f-XlSqrt(3.0f))/6.0f;
    static float F3 = 1.0f/3.0f;
    static float G3 = 1.0f/6.0f;
    static float F4 = (XlSqrt(5.0f)-1.0f)/4.0f;
    static float G4 = (5.0f-XlSqrt(5.0f))/20.0f;

    static int fastfloor(float x) {
            // this method was built for Java... Maybe it's not the best option for C++?
        int xi = (int)x;
        return x<xi ? xi-1 : xi;
    }

    static float dot(Grad g, float x, float y) { return g.x*x + g.y*y; }
    static float dot(Grad g, float x, float y, float z) { return g.x*x + g.y*y + g.z*z; }
    static float dot(Grad g, float x, float y, float z, float w) { return g.x*x + g.y*y + g.z*z + g.w*w; }

    // 2D simplex noise
    float SimplexNoise(Float2 input)
    {
        float xin = input[0], yin = input[1];
        InitPerm();

        float n0, n1, n2; // Noise contributions from the three corners
        // Skew the input space to determine which simplex cell we're in
        float s = (xin+yin)*F2; // Hairy factor for 2D
        int i = fastfloor(xin+s);
        int j = fastfloor(yin+s);

        float t = (i+j)*G2;
        float X0 = i-t; // Unskew the cell origin back to (x,y) space
        float Y0 = j-t;
        float x0 = xin-X0; // The x,y distances from the cell origin
        float y0 = yin-Y0;
        // For the 2D case, the simplex shape is an equilateral triangle.
        // Determine which simplex we are in.
        int i1, j1; // Offsets for second (middle) corner of simplex in (i,j) coords
        if(x0>y0)   { i1=1; j1=0; } // lower triangle, XY order: (0,0)->(1,0)->(1,1)
        else        { i1=0; j1=1; }      // upper triangle, YX order: (0,0)->(0,1)->(1,1)

        // A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and
        // a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where
        // c = (3-sqrt(3))/6
        float x1 = x0 - i1 + G2; // Offsets for middle corner in (x,y) unskewed coords
        float y1 = y0 - j1 + G2;
        float x2 = x0 - 1.f + 2.f * G2; // Offsets for last corner in (x,y) unskewed coords
        float y2 = y0 - 1.f + 2.f * G2;

        // Work out the hashed gradient indices of the three simplex corners
        int ii = i & 255;
        int jj = j & 255;
        int gi0 = permMod12[ii+perm[jj]];
        int gi1 = permMod12[ii+i1+perm[jj+j1]];
        int gi2 = permMod12[ii+1+perm[jj+1]];

        // Calculate the contribution from the three corners
        float t0 = 0.5f - x0*x0-y0*y0;
        if(t0<0) n0 = 0.f;
        else {
          t0 *= t0;
          n0 = t0 * t0 * dot(grad3[gi0], x0, y0);  // (x,y) of grad3 used for 2D gradient
        }
        float t1 = 0.5f - x1*x1-y1*y1;
        if(t1<0) n1 = 0.f;
        else {
          t1 *= t1;
          n1 = t1 * t1 * dot(grad3[gi1], x1, y1);
        }
        float t2 = 0.5f - x2*x2-y2*y2;
        if(t2<0) n2 = 0.f;
        else {
          t2 *= t2;
          n2 = t2 * t2 * dot(grad3[gi2], x2, y2);
        }
        // Add contributions from each corner to get the final noise value.
        // The result is scaled to return values in the interval [-1,1].
        return 70.f * (n0 + n1 + n2);
    }


  // 3D simplex noise
    float SimplexNoise(Float3 input)
    {
        float xin = input[0], yin = input[1], zin = input[2];
        InitPerm();

        float n0, n1, n2, n3; // Noise contributions from the four corners
        // Skew the input space to determine which simplex cell we're in
        float s = (xin+yin+zin)*F3; // Very nice and simple skew factor for 3D
        int i = fastfloor(xin+s);
        int j = fastfloor(yin+s);
        int k = fastfloor(zin+s);

        float t = (i+j+k)*G3;
        float X0 = i-t; // Unskew the cell origin back to (x,y,z) space
        float Y0 = j-t;
        float Z0 = k-t;
        float x0 = xin-X0; // The x,y,z distances from the cell origin
        float y0 = yin-Y0;
        float z0 = zin-Z0;

        // For the 3D case, the simplex shape is a slightly irregular tetrahedron.
        // Determine which simplex we are in.
        int i1, j1, k1; // Offsets for second corner of simplex in (i,j,k) coords
        int i2, j2, k2; // Offsets for third corner of simplex in (i,j,k) coords
        if(x0>=y0) {
            if(y0>=z0) { i1=1; j1=0; k1=0; i2=1; j2=1; k2=0; } // X Y Z order
            else if(x0>=z0) { i1=1; j1=0; k1=0; i2=1; j2=0; k2=1; } // X Z Y order
            else { i1=0; j1=0; k1=1; i2=1; j2=0; k2=1; } // Z X Y order
        } else { // x0<y0
            if(y0<z0) { i1=0; j1=0; k1=1; i2=0; j2=1; k2=1; } // Z Y X order
            else if(x0<z0) { i1=0; j1=1; k1=0; i2=0; j2=1; k2=1; } // Y Z X order
            else { i1=0; j1=1; k1=0; i2=1; j2=1; k2=0; } // Y X Z order
        }

            // A step of (1,0,0) in (i,j,k) means a step of (1-c,-c,-c) in (x,y,z),
            // a step of (0,1,0) in (i,j,k) means a step of (-c,1-c,-c) in (x,y,z), and
            // a step of (0,0,1) in (i,j,k) means a step of (-c,-c,1-c) in (x,y,z), where
            // c = 1/6.
        float x1 = x0 - i1 + G3; // Offsets for second corner in (x,y,z) coords
        float y1 = y0 - j1 + G3;
        float z1 = z0 - k1 + G3;
        float x2 = x0 - i2 + 2.f*G3; // Offsets for third corner in (x,y,z) coords
        float y2 = y0 - j2 + 2.f*G3;
        float z2 = z0 - k2 + 2.f*G3;
        float x3 = x0 - 1.f + 3.f*G3; // Offsets for last corner in (x,y,z) coords
        float y3 = y0 - 1.f + 3.f*G3;
        float z3 = z0 - 1.f + 3.f*G3;

        // Work out the hashed gradient indices of the four simplex corners
        int ii = i & 255;
        int jj = j & 255;
        int kk = k & 255;
        int gi0 = permMod12[ii+perm[jj+perm[kk]]];
        int gi1 = permMod12[ii+i1+perm[jj+j1+perm[kk+k1]]];
        int gi2 = permMod12[ii+i2+perm[jj+j2+perm[kk+k2]]];
        int gi3 = permMod12[ii+1+perm[jj+1+perm[kk+1]]];

        // Calculate the contribution from the four corners
        float t0 = 0.6f - x0*x0 - y0*y0 - z0*z0;
        if(t0<0) n0 = 0.f;
        else {
            t0 *= t0;
            n0 = t0 * t0 * dot(grad3[gi0], x0, y0, z0);
        }

        float t1 = 0.6f - x1*x1 - y1*y1 - z1*z1;
        if(t1<0) n1 = 0.f;
        else {
            t1 *= t1;
            n1 = t1 * t1 * dot(grad3[gi1], x1, y1, z1);
        }

        float t2 = 0.6f - x2*x2 - y2*y2 - z2*z2;
        if(t2<0) n2 = 0.f;
        else {
            t2 *= t2;
            n2 = t2 * t2 * dot(grad3[gi2], x2, y2, z2);
        }

        float t3 = 0.6f - x3*x3 - y3*y3 - z3*z3;
        if(t3<0) n3 = 0.f;
        else {
            t3 *= t3;
            n3 = t3 * t3 * dot(grad3[gi3], x3, y3, z3);
        }

        // Add contributions from each corner to get the final noise value.
        // The result is scaled to stay just inside [-1,1]
        return 32.f*(n0 + n1 + n2 + n3);
    }


#if 1
  // 4D simplex noise, better simplex rank ordering method 2012-03-09
  float SimplexNoise(Float4 input) 
  {
      float x = input[0], y = input[1], z = input[2], w = input[3];

      InitPerm();

    float n0, n1, n2, n3, n4; // Noise contributions from the five corners
    // Skew the (x,y,z,w) space to determine which cell of 24 simplices we're in
    float s = (x + y + z + w) * F4; // Factor for 4D skewing
    int i = fastfloor(x + s);
    int j = fastfloor(y + s);
    int k = fastfloor(z + s);
    int l = fastfloor(w + s);
    float t = (i + j + k + l) * G4; // Factor for 4D unskewing
    float X0 = i - t; // Unskew the cell origin back to (x,y,z,w) space
    float Y0 = j - t;
    float Z0 = k - t;
    float W0 = l - t;
    float x0 = x - X0;  // The x,y,z,w distances from the cell origin
    float y0 = y - Y0;
    float z0 = z - Z0;
    float w0 = w - W0;
    // For the 4D case, the simplex is a 4D shape I won't even try to describe.
    // To find out which of the 24 possible simplices we're in, we need to
    // determine the magnitude ordering of x0, y0, z0 and w0.
    // Six pair-wise comparisons are performed between each possible pair
    // of the four coordinates, and the results are used to rank the numbers.
    int rankx = 0;
    int ranky = 0;
    int rankz = 0;
    int rankw = 0;
    if(x0 > y0) rankx++; else ranky++;
    if(x0 > z0) rankx++; else rankz++;
    if(x0 > w0) rankx++; else rankw++;
    if(y0 > z0) ranky++; else rankz++;
    if(y0 > w0) ranky++; else rankw++;
    if(z0 > w0) rankz++; else rankw++;
    int i1, j1, k1, l1; // The integer offsets for the second simplex corner
    int i2, j2, k2, l2; // The integer offsets for the third simplex corner
    int i3, j3, k3, l3; // The integer offsets for the fourth simplex corner
    // simplex[c] is a 4-vector with the numbers 0, 1, 2 and 3 in some order.
    // Many values of c will never occur, since e.g. x>y>z>w makes x<z, y<w and x<w
    // impossible. Only the 24 indices which have non-zero entries make any sense.
    // We use a thresholding to set the coordinates in turn from the largest magnitude.
    // Rank 3 denotes the largest coordinate.
    i1 = rankx >= 3 ? 1 : 0;
    j1 = ranky >= 3 ? 1 : 0;
    k1 = rankz >= 3 ? 1 : 0;
    l1 = rankw >= 3 ? 1 : 0;
    // Rank 2 denotes the second largest coordinate.
    i2 = rankx >= 2 ? 1 : 0;
    j2 = ranky >= 2 ? 1 : 0;
    k2 = rankz >= 2 ? 1 : 0;
    l2 = rankw >= 2 ? 1 : 0;
    // Rank 1 denotes the second smallest coordinate.
    i3 = rankx >= 1 ? 1 : 0;
    j3 = ranky >= 1 ? 1 : 0;
    k3 = rankz >= 1 ? 1 : 0;
    l3 = rankw >= 1 ? 1 : 0;
    // The fifth corner has all coordinate offsets = 1, so no need to compute that.
    float x1 = x0 - i1 + G4; // Offsets for second corner in (x,y,z,w) coords
    float y1 = y0 - j1 + G4;
    float z1 = z0 - k1 + G4;
    float w1 = w0 - l1 + G4;
    float x2 = x0 - i2 + 2.0f*G4; // Offsets for third corner in (x,y,z,w) coords
    float y2 = y0 - j2 + 2.0f*G4;
    float z2 = z0 - k2 + 2.0f*G4;
    float w2 = w0 - l2 + 2.0f*G4;
    float x3 = x0 - i3 + 3.0f*G4; // Offsets for fourth corner in (x,y,z,w) coords
    float y3 = y0 - j3 + 3.0f*G4;
    float z3 = z0 - k3 + 3.0f*G4;
    float w3 = w0 - l3 + 3.0f*G4;
    float x4 = x0 - 1.0f + 4.0f*G4; // Offsets for last corner in (x,y,z,w) coords
    float y4 = y0 - 1.0f + 4.0f*G4;
    float z4 = z0 - 1.0f + 4.0f*G4;
    float w4 = w0 - 1.0f + 4.0f*G4;
    // Work out the hashed gradient indices of the five simplex corners
    int ii = i & 255;
    int jj = j & 255;
    int kk = k & 255;
    int ll = l & 255;
    int gi0 = perm[ii+perm[jj+perm[kk+perm[ll]]]] % 32;
    int gi1 = perm[ii+i1+perm[jj+j1+perm[kk+k1+perm[ll+l1]]]] % 32;
    int gi2 = perm[ii+i2+perm[jj+j2+perm[kk+k2+perm[ll+l2]]]] % 32;
    int gi3 = perm[ii+i3+perm[jj+j3+perm[kk+k3+perm[ll+l3]]]] % 32;
    int gi4 = perm[ii+1+perm[jj+1+perm[kk+1+perm[ll+1]]]] % 32;
    // Calculate the contribution from the five corners
    float t0 = 0.6f - x0*x0 - y0*y0 - z0*z0 - w0*w0;
    if(t0<0) n0 = 0.0f;
    else {
      t0 *= t0;
      n0 = t0 * t0 * dot(grad4[gi0], x0, y0, z0, w0);
    }
   float t1 = 0.6f - x1*x1 - y1*y1 - z1*z1 - w1*w1;
    if(t1<0) n1 = 0.0f;
    else {
      t1 *= t1;
      n1 = t1 * t1 * dot(grad4[gi1], x1, y1, z1, w1);
    }
   float t2 = 0.6f - x2*x2 - y2*y2 - z2*z2 - w2*w2;
    if(t2<0) n2 = 0.0f;
    else {
      t2 *= t2;
      n2 = t2 * t2 * dot(grad4[gi2], x2, y2, z2, w2);
    }
   float t3 = 0.6f - x3*x3 - y3*y3 - z3*z3 - w3*w3;
    if(t3<0) n3 = 0.0f;
    else {
      t3 *= t3;
      n3 = t3 * t3 * dot(grad4[gi3], x3, y3, z3, w3);
    }
   float t4 = 0.6f - x4*x4 - y4*y4 - z4*z4 - w4*w4;
    if(t4<0) n4 = 0.0f;
    else {
      t4 *= t4;
      n4 = t4 * t4 * dot(grad4[gi4], x4, y4, z4, w4);
    }
    // Sum up and scale the result to cover the range [-1,1]
    return 27.0f * (n0 + n1 + n2 + n3 + n4);
  }
#endif


    template<typename Type>
        float SimplexFBM(Type pos, float hgrid, float gain, float lacunarity, int octaves)
    {
        float total = 0.0f;
	    float frequency = 1.0f/(float)hgrid;
	    float amplitude = 1.f;
        
	    for (int i = 0; i < octaves; ++i) {
		    total += SimplexNoise(Type(pos * frequency)) * amplitude;
		    frequency *= lacunarity;
		    amplitude *= gain;
	    }
        
	    return total;
    }


    template float SimplexFBM(Float2, float, float, float, int);
    template float SimplexFBM(Float3, float, float, float, int);
    template float SimplexFBM(Float4, float, float, float, int);
  
}
float bePerlinNoise2D::Get(float x, float y)
{
	float xi, xf, yi, yf;
	xf = modf(x, &xi);
	yf = modf(y, &yi);
	constexpr float zf = 0.5f;

	if (xf < 0.0)
	{
		xi -= 1.0;
		xf += 1.0;
	}
	if (yf < 0.0)
	{
		yi -= 1.0;
		yf += 1.0;
	}

	int x0 = (int)xi;
	int y0 = (int)yi;
	const int maxX = 255;
	const int maxY = 255;

	x0 = ((x0 % maxX) + maxX) % maxX; // [0, maxX)
	y0 = ((y0 % maxY) + maxY) % maxY; // [0, maxX)
	const int x1 = (x0 + 1) % maxX; // [0, maxX)
	const int y1 = (y0 + 1) % maxY; // [0, maxX)
	
	const float u = beMath::SmootherStep(xf);
	const float v = beMath::SmootherStep(yf);
	constexpr float w = beMath::SmootherStep(zf);

	u8* p = m_hashTable.data();
	
	const int z0 = 0;
	const int z1 = 1;

	#pragma warning(push)
	#pragma warning(disable:26481) // pointer arithmetic
	int aaa, aba, aab, abb, baa, bba, bab, bbb;
	aaa = p[p[p[x0]+y0]+z0];
	aba = p[p[p[x0]+y1]+z0];
	aab = p[p[p[x0]+y0]+z1];
	abb = p[p[p[x0]+y1]+z1];
	baa = p[p[p[x1]+y0]+z0];
	bba = p[p[p[x1]+y1]+z0];
	bab = p[p[p[x1]+y0]+z1];
	bbb = p[p[p[x1]+y1]+z1];
	#pragma warning(pop)

	// The gradient function calculates the dot product between a pseudorandom
	// gradient vector and the vector from the input coordinate to the 8
	// surrounding points in its unit cube.
	// This is all then lerped together as a sort of weighted average based on the faded (u,v,w)
	// values we made earlier.


	float X1, X2, Y1, Y2;
	X1 = Lerp(Grad(aaa, xf, yf    , zf)    , Grad(baa, xf-1.f, yf    , zf)    , u);
	X2 = Lerp(Grad(aba, xf, yf-1.f, zf)    , Grad(bba, xf-1.f, yf-1.f, zf)    , u);
	Y1 = Lerp(X1, X2, v);
 
	X1 = Lerp(Grad(aab, xf, yf    , zf-1.f), Grad(bab, xf-1.f, yf    , zf-1.f), u);
	X2 = Lerp(Grad(abb, xf, yf-1.f, zf-1.f), Grad(bbb, xf-1.f, yf-1.f, zf-1.f), u);
	Y2 = Lerp(X1, X2, v);
	
	// Change (-1,1) => (0, 1)
	const float result = (Lerp(Y1, Y2, w)+1.f) * 0.5f;
	//LOG("X,Y,Z {%3.1f, %3.1f, %3.1f}\t = %3.3f", x, y, zf, result);
	return result;
}
Beispiel #8
0
void OptimizeGeometry(string type) {

  // Initialize geometry opt parameters
  int opt_cycle = 1;
  double dE = 1000, Gnorm = 1000; //nonsense initial values
  double econv = 1.0e-6;
  double gconv = 3.0e-4;
  double stepsize = 0.25;
  bool reset; // for resetting CG algorithm

  // Initialize some empty vectors with same dimensions as the Gradient
  Vector StepDir(Cluster::cluster().GetHMBIGradient(),false);
  Vector Grad_current(Cluster::cluster().GetHMBIGradient(),false);
  Vector StepDir_old(Cluster::cluster().GetHMBIGradient(),false);
  Vector Grad_old(Cluster::cluster().GetHMBIGradient(),false);


  if (type == "SteepestDescent") {
    while (opt_cycle <= Params::Parameters().GetMaxOptCycles() && 
	   (fabs(dE) > econv  || fabs(Gnorm) > gconv ) ) {
      
      
      //printf("XXX\nXXX Starting next opt cycle\n");
      
      // before the step
      double E_current = Cluster::cluster().GetHMBIEnergy();
      Grad_current = Cluster::cluster().GetHMBIGradient();
      Vector Coords_current = Cluster::cluster().GetCurrentCoordinates();
      
      //printf("XXX Current Gradient: %12.6f\n",Grad_current.Norm());
      
      // If this is the first cycle, do some special printing
      if (opt_cycle == 1) {
	printf("Cycle %d: Energy = %15.9f   |Grad| = %12.6f\n",
	       0, E_current, Grad_current.Max(true));
	printf("Cycle %d:     dE = %15.9f  |dGrad| = %12.6f\n",
	       0, 0.0, 0.0);
	Cluster::cluster().UpdateTrajectoryFile(0,true);
      }
      
      // use Gradient printer to show coords
      if (Params::Parameters().PrintLevel() > 0 )
	Cluster::cluster().PrintGradient("Original coordinates",Coords_current);
      
      // Create empty coords array with proper size
      Vector Coords_new(Coords_current, false); 
      
      // Take optimization step
      //Grad_current.Scale(-1.0);
	SteepestDescent(Coords_new, Coords_current, Grad_current, stepsize);
      
      // use Gradient printer to show coords
      if (Params::Parameters().PrintLevel() > 0 )
	Cluster::cluster().PrintGradient("New coordinates",Coords_new);
      
      // Update the coordinates in the cluster object
      Cluster::cluster().SetNewCoordinates(Coords_new);
      
      // Create the new jobs, run them, and get the HMBI energy
      Cluster::cluster().RunJobsAndComputeEnergy();
      
      // Print output
      double E = Cluster::cluster().GetHMBIEnergy();
      Vector Grad( Cluster::cluster().GetHMBIGradient() );
      
      //printf("XXX New Gradient: %12.6f\n",Grad.Max(true));
      
      Gnorm = Grad.Max(true);
      printf("Cycle %d: Energy = %15.9f   |Grad| = %10.6f\n",opt_cycle,
	     E,Gnorm);
      dE = E - E_current;
      Vector dGrad(Grad);
      dGrad -= Grad_current;
      double dG = dGrad.Max(true);
      
      printf("Cycle %d:     dE = %15.9f  |dGrad| = %10.6f  step = %8.3f\n",
	     opt_cycle, dE, dG, stepsize);
      
      Cluster::cluster().UpdateTrajectoryFile(opt_cycle);
      
      
      // Save a copy of the new geometry in a new input file.
      FILE *input;
      string input_file = "new_geom.in";
      if ((input = fopen(input_file.c_str(),"w"))==NULL) {
	printf("OptimizeGeometry() : Cannot open file '%s'\n",input_file.c_str());
	exit(1);
      }
      
      Cluster::cluster().PrintInputFile(input);
      printf("\nNew input file written to '%s'\n",input_file.c_str());
      fclose(input);
      
      // Adjust step size
      if (opt_cycle > 1) {
	// if stepped too far, backup and shrink stepsize
	if (dE > 0.0) {
	  printf("Cycle     Back-up.  Decreasing step size for next cycle.\n");
	  stepsize /= 1.5;
	  // Back up
	  Cluster::cluster().SetNewCoordinates(Coords_current);
	  Cluster::cluster().RunJobsAndComputeEnergy();
	  Grad_current = Grad_old;
	}
	else {
	  printf("Cycle    Increasing step size for next cycle.\n");
	  stepsize *= 1.2;
	}
	
	if (stepsize > 2.0)
	  stepsize = 2.0;
      }
      


      //stepsize = 0.5;
      opt_cycle++;
    }
  }
  else if (type == "ConjugateGradients") {
    // Start optimization cycles
    while (opt_cycle <= Params::Parameters().GetMaxOptCycles() && 
	   (fabs(dE) > econv  || fabs(Gnorm) > gconv ) ) {
      
      reset = false;
      
      //printf("XXX\nXXX Starting next opt cycle\n");
      
      // For CG optimizer, need to save previous gradient
      if (opt_cycle > 1) {
	Grad_old = Grad_current;
	StepDir_old = StepDir;
	
	//printf("Backing up Gradient and StepDir\n");
	//printf("XXX |Grad_old| = %12.6f, |StepDir_old| = %12.6f\n",
	//Grad_old.Norm(),StepDir_old.Norm());
      }
      
      // Grab Energy, Gradient, and XYZ coordinates for geometry
      // before the step
      double E_current = Cluster::cluster().GetHMBIEnergy();
      Grad_current = Cluster::cluster().GetHMBIGradient();
      Vector Coords_current = Cluster::cluster().GetCurrentCoordinates();
      
      //printf("XXX Current Gradient: %12.6f\n",Grad_current.Norm());
      
      // If this is the first cycle, do some special printing
      if (opt_cycle == 1) {
	printf("Cycle %d: Energy = %15.9f   |Grad| = %12.6f\n",
	       0, E_current, Grad_current.Max(true));
	printf("Cycle %d:     dE = %15.9f  |dGrad| = %12.6f\n",
	       0, 0.0, 0.0);
	Cluster::cluster().UpdateTrajectoryFile(0,true);
      }
      
      // use Gradient printer to show coords
      if (Params::Parameters().PrintLevel() > 0 )
	Cluster::cluster().PrintGradient("Original coordinates",Coords_current);
      
      // Create empty coords array with proper size
      Vector Coords_new(Coords_current, false); 
      
      if (opt_cycle % 20 == 0) {
	reset = true;
	//if (stepsize > 0.5)
	stepsize = 0.25;
      }
      
      // Take optimization step
      if (opt_cycle==1) {
	// Use steepest descent for first step, sets StepDir
	Grad_current.Scale(-1.0);
	SteepestDescent(Coords_new, Coords_current, Grad_current, stepsize);
	StepDir = Grad_current;
	StepDir.Scale(-1.0);
      }
      else
	ConjugateGradients(Coords_new, StepDir, Coords_current, Grad_current, 
			   Grad_old, StepDir_old,stepsize, reset);
      
      // use Gradient printer to show coords
      if (Params::Parameters().PrintLevel() > 0 )
	Cluster::cluster().PrintGradient("New coordinates",Coords_new);
      
      // Update the coordinates in the cluster object
      Cluster::cluster().SetNewCoordinates(Coords_new);
      
      // Create the new jobs, run them, and get the HMBI energy
      Cluster::cluster().RunJobsAndComputeEnergy();
      
      // Print output
      double E = Cluster::cluster().GetHMBIEnergy();
      Vector Grad( Cluster::cluster().GetHMBIGradient() );
      
      //printf("XXX New Gradient: %12.6f\n",Grad.Max(true));
      
      Gnorm = Grad.Max(true);
      printf("Cycle %d: Energy = %15.9f   |Grad| = %10.6f\n",opt_cycle,
	     E,Gnorm);
      dE = E - E_current;
      Vector dGrad(Grad);
      dGrad -= Grad_current;
      double dG = dGrad.Max(true);
      
      printf("Cycle %d:     dE = %15.9f  |dGrad| = %10.6f  step = %8.3f\n",
	     opt_cycle, dE, dG, stepsize);
      
      Cluster::cluster().UpdateTrajectoryFile(opt_cycle);
      
      
      // Save a copy of the new geometry in a new input file.
      FILE *input;
      string input_file = "new_geom.in";
      if ((input = fopen(input_file.c_str(),"w"))==NULL) {
	printf("OptimizeGeometry() : Cannot open file '%s'\n",input_file.c_str());
	exit(1);
      }
      
      Cluster::cluster().PrintInputFile(input);
      printf("\nNew input file written to '%s'\n",input_file.c_str());
      fclose(input);
      
      // Adjust step size
      if (opt_cycle > 1) {
	// if stepped too far, backup and shrink stepsize
	if (dE > 0.0) {
	  printf("Cycle     Back-up.  Decreasing step size for next cycle.\n");
	  stepsize /= 1.5;
	  // Back up
	  Cluster::cluster().SetNewCoordinates(Coords_current);
	  Cluster::cluster().RunJobsAndComputeEnergy();
	  Grad_current = Grad_old;
	  StepDir = StepDir_old;
	  
	  
	}
	else {
	  printf("Cycle    Increasing step size for next cycle.\n");
	  stepsize *= 1.2;
	}
	
	if (stepsize > 2.0)
	  stepsize = 2.0;
      }
      


      //stepsize = 0.5;
      opt_cycle++;
    }
  }
    
  printf("Cycle %d: Opt completed.  dE = %15.9f, |Grad| = %10.6f\n",opt_cycle-1,
	 dE,Gnorm);
  
  Cluster::cluster().ComputeDistanceMatrix();


  // Save a copy of the new geometry in a new input file.
  FILE *input;
  string input_file = "new_geom.in";
  if ((input = fopen(input_file.c_str(),"w"))==NULL) {
    printf("OptimizeGeometry() : Cannot open file '%s'\n",input_file.c_str());
    exit(1);
  }

  Cluster::cluster().PrintInputFile(input);
  printf("\nNew input file written to '%s'\n",input_file.c_str());
  fclose(input);

}
PreconditionerBlockMS<space_type>::PreconditionerBlockMS(space_ptrtype Xh,             // (u)x(p)
                                                         ModelProperties model,        // model
                                                         std::string const& p,         // prefix
                                                         sparse_matrix_ptrtype AA )    // The matrix
    :
        M_backend(backend()),           // the backend associated to the PC
        M_Xh( Xh ),
        M_Vh( Xh->template functionSpace<0>() ), // Potential
        M_Qh( Xh->template functionSpace<1>() ), // Lagrange
        M_Vh_indices( M_Vh->nLocalDofWithGhost() ),
        M_Qh_indices( M_Qh->nLocalDofWithGhost() ),
        M_uin( M_backend->newVector( M_Vh )  ),
        M_uout( M_backend->newVector( M_Vh )  ),
        M_pin( M_backend->newVector( M_Qh )  ),
        M_pout( M_backend->newVector( M_Qh )  ),
        U( M_Xh, "U" ),
        M_mass(M_backend->newMatrix(M_Vh,M_Vh)),
        M_L(M_backend->newMatrix(M_Qh,M_Qh)),
        M_er( 1. ),
        M_model( model ),
        M_prefix( p ),
        M_prefix_11( p+".11" ),
        M_prefix_22( p+".22" ),
        u(M_Vh, "u"),
        ozz(M_Vh, "ozz"),
        zoz(M_Vh, "zoz"),
        zzo(M_Vh, "zzo"),
        M_ozz(M_backend->newVector( M_Vh )),
        M_zoz(M_backend->newVector( M_Vh )),
        M_zzo(M_backend->newVector( M_Vh )),
        X(M_Qh, "X"),
        Y(M_Qh, "Y"),
        Z(M_Qh, "Z"),
        M_X(M_backend->newVector( M_Qh )),
        M_Y(M_backend->newVector( M_Qh )),
        M_Z(M_backend->newVector( M_Qh )),
        phi(M_Qh, "phi")
{
    tic();
    LOG(INFO) << "[PreconditionerBlockMS] setup starts";
    this->setMatrix( AA );
    this->setName(M_prefix);

    /* Indices are need to extract sub matrix */
    std::iota( M_Vh_indices.begin(), M_Vh_indices.end(), 0 );
    std::iota( M_Qh_indices.begin(), M_Qh_indices.end(), M_Vh->nLocalDofWithGhost() );

    M_11 = AA->createSubMatrix( M_Vh_indices, M_Vh_indices, true, true);

    /* Boundary conditions */
    BoundaryConditions M_bc = M_model.boundaryConditions();
    map_vector_field<FEELPP_DIM,1,2> m_dirichlet_u { M_bc.getVectorFields<FEELPP_DIM> ( "u", "Dirichlet" ) };
    map_scalar_field<2> m_dirichlet_p { M_bc.getScalarFields<2> ( "phi", "Dirichlet" ) };

    /* Compute the mass matrix (needed in first block, constant) */
    auto f2A = form2(_test=M_Vh, _trial=M_Vh, _matrix=M_mass);
    auto f1A = form1(_test=M_Vh);
    f2A = integrate(_range=elements(M_Vh->mesh()), _expr=inner(idt(u),id(u))); // M
    for(auto const & it : m_dirichlet_u )
    {
        LOG(INFO) << "Applying " << it.second << " on " << it.first << " for "<<M_prefix_11<<"\n";
        f2A += on(_range=markedfaces(M_Vh->mesh(),it.first), _expr=it.second,_rhs=f1A, _element=u, _type="elimination_symmetric");
    }
    
    /* Compute the L (= er * grad grad) matrix (the second block) */
    auto f2L = form2(_test=M_Qh,_trial=M_Qh, _matrix=M_L);
    for(auto it : M_model.materials() )
    { 
        f2L += integrate(_range=markedelements(M_Qh->mesh(),marker(it)), _expr=M_er*inner(gradt(phi), grad(phi)));
    }
    auto f1LQ = form1(_test=M_Qh);

    for(auto const & it : m_dirichlet_p)
    {
        LOG(INFO) << "Applying " << it.second << " on " << it.first << " for "<<M_prefix_22<<"\n";
        f2L += on(_range=markedfaces(M_Qh->mesh(),it.first),_element=phi, _expr=it.second, _rhs=f1LQ, _type="elimination_symmetric");
    }


    if(soption(_name="pc-type", _prefix=M_prefix_11) == "ams")
#if FEELPP_DIM == 3
    {
        M_grad  = Grad( _domainSpace=M_Qh, _imageSpace=M_Vh);

        // This preconditioner is linked to that backend : the backend will
        // automatically use the preconditioner.
        auto prec = preconditioner(_pc=pcTypeConvertStrToEnum(soption(M_prefix_11+".pc-type")),
                                   _backend=backend(_name=M_prefix_11),
                                   _prefix=M_prefix_11,
                                   _matrix=M_11
                                  );
        prec->setMatrix(M_11);
        prec->attachAuxiliarySparseMatrix("G",M_grad.matPtr());
        if(boption(M_prefix_11+".useEdge"))
        {
            LOG(INFO) << "[ AMS ] : using SetConstantEdgeVector \n";
            ozz.on(_range=elements(M_Vh->mesh()),_expr=vec(cst(1),cst(0),cst(0)));
            zoz.on(_range=elements(M_Vh->mesh()),_expr=vec(cst(0),cst(1),cst(0)));
            zzo.on(_range=elements(M_Vh->mesh()),_expr=vec(cst(0),cst(0),cst(1)));
            *M_ozz = ozz; M_ozz->close();
            *M_zoz = zoz; M_zoz->close();
            *M_zzo = zzo; M_zzo->close();

            prec->attachAuxiliaryVector("Px",M_ozz);
            prec->attachAuxiliaryVector("Py",M_zoz);
            prec->attachAuxiliaryVector("Pz",M_zzo);
        }
        else
        {
            LOG(INFO) << "[ AMS ] : using SetCoordinates \n";
            X.on(_range=elements(M_Vh->mesh()),_expr=Px());
            Y.on(_range=elements(M_Vh->mesh()),_expr=Py());
            Z.on(_range=elements(M_Vh->mesh()),_expr=Pz());
            *M_X = X; M_X->close();
            *M_Y = Y; M_Y->close();
            *M_Z = Z; M_Z->close();
            prec->attachAuxiliaryVector("X",M_X);
            prec->attachAuxiliaryVector("Y",M_Y);
            prec->attachAuxiliaryVector("Z",M_Z);
        }
    }
#else
    std::cerr << "ams preconditioner is not interfaced in two dimensions\n";
#endif
    toc( "[PreconditionerBlockMS] setup done ", FLAGS_v > 0 );
}