Beispiel #1
0
void FunctionTests::checkFunctionsAgree(FunctionPtr f1, FunctionPtr f2, BasisCachePtr basisCache) {
  ASSERT_EQ(f1->rank(), f2->rank())
    << "f1->rank() " << f1->rank() << " != f2->rank() " << f2->rank() << endl;

  int rank = f1->rank();
  int numCells = basisCache->getPhysicalCubaturePoints().dimension(0);
  int numPoints = basisCache->getPhysicalCubaturePoints().dimension(1);
  int spaceDim = basisCache->getPhysicalCubaturePoints().dimension(2);
  Teuchos::Array<int> dim;
  dim.append(numCells);
  dim.append(numPoints);
  for (int i=0; i<rank; i++) {
    dim.append(spaceDim);
  }
  FieldContainer<double> f1Values(dim);
  FieldContainer<double> f2Values(dim);
  f1->values(f1Values,basisCache);
  f2->values(f2Values,basisCache);
  
  double tol = 1e-14;
  double maxDiff;
  EXPECT_TRUE(fcsAgree(f1Values,f2Values,tol,maxDiff))
    << "Test failed: f1 and f2 disagree; maxDiff " << maxDiff << ".\n"
    << "f1Values: \n" << f1Values
    << "f2Values: \n" << f2Values;
}
Beispiel #2
0
bool ElementTests::testNeighborPointMapping()
{
  bool success = true;
  double tol = 1e-15;
  double maxDiff;

  int SOUTH = 0, EAST = 1, NORTH = 2, WEST = 3;
  // determine expected values
  int numPoints = _testPoints1D.dimension(0);

  FieldContainer<double> neighborPointsForSW_east_side = FieldContainer<double>(numPoints,1);
  // universal rule is just flip along (-1,1): x --> -x
  for (int i=0; i<numPoints; i++)
  {
    neighborPointsForSW_east_side(i, 0) = - _testPoints1D(i,0);
  }

  // determine actual values, and compare
  FieldContainer<double> neighborRefPoints = FieldContainer<double>(numPoints,1);
  _sw->getSidePointsInNeighborRefCoords(neighborRefPoints, EAST, _testPoints1D);

  if ( !fcsAgree(neighborRefPoints,neighborPointsForSW_east_side,tol,maxDiff) )
  {
    cout << "Failure in mapping to neighbor ref coords; maxDiff = " << maxDiff << endl;
    success = false;
  }

  return success;
}
Beispiel #3
0
bool ScratchPadTests::testConstantFunctionProduct()
{
  bool success = true;
  // set up basisCache (even though it won't really be used here)
  BasisCachePtr basisCache = Teuchos::rcp( new BasisCache( _elemType, _spectralConfusionMesh ) );
  vector<GlobalIndexType> cellIDs;
  int cellID = 0;
  cellIDs.push_back(cellID);
  basisCache->setPhysicalCellNodes( _spectralConfusionMesh->physicalCellNodesForCell(cellID),
                                    cellIDs, true );

  int numCells = _basisCache->getPhysicalCubaturePoints().dimension(0);
  int numPoints = _testPoints.dimension(0);
  FunctionPtr three = Function::constant(3.0);
  FunctionPtr two = Function::constant(2.0);

  FieldContainer<double> values(numCells,numPoints);
  two->values(values,basisCache);
  three->scalarMultiplyBasisValues( values, basisCache );

  FieldContainer<double> expectedValues(numCells,numPoints);
  expectedValues.initialize( 3.0 * 2.0 );

  double tol = 1e-15;
  double maxDiff = 0.0;
  if ( ! fcsAgree(expectedValues, values, tol, maxDiff) )
  {
    success = false;
    cout << "Expected product differs from actual; maxDiff: " << maxDiff << endl;
  }
  return success;
}
Beispiel #4
0
bool ElementTests::testParentPointMapping()
{
  bool success = true;
  double tol = 1e-15;
  double maxDiff;

  int SOUTH = 0, EAST = 1, NORTH = 2, WEST = 3;
  // determine expected values
  int numPoints = _testPoints1D.dimension(0);
  FieldContainer<double> sw_east_points_for_ne_child = FieldContainer<double>(numPoints,1);
  // along the east side, ne child is the second: so rule is add 1 and divide by 2
  for (int i=0; i<numPoints; i++)
  {
    sw_east_points_for_ne_child(i, 0) = (_testPoints1D(i,0)+1.0)/2.0;
  }
  FieldContainer<double> sw_east_points_for_se_child = FieldContainer<double>(numPoints,1);
  // along the east side, se child is the first: so rule is subtract 1 and divide by 2
  for (int i=0; i<numPoints; i++)
  {
    sw_east_points_for_se_child(i, 0) = (_testPoints1D(i,0)-1.0)/2.0;
  }

  // determine actual values, and compare
  FieldContainer<double> parentRefPoints = FieldContainer<double>(numPoints,1);
  _sw_ne->getSidePointsInParentRefCoords(parentRefPoints, EAST, _testPoints1D);
  if ( !fcsAgree(parentRefPoints,sw_east_points_for_ne_child,tol,maxDiff) )
  {
    cout << "Failure in mapping to parent ref coords for NE child; maxDiff = " << maxDiff << endl;
    success = false;
  }
  _sw_se->getSidePointsInParentRefCoords(parentRefPoints, EAST, _testPoints1D);
  if ( !fcsAgree(parentRefPoints,sw_east_points_for_se_child,tol,maxDiff) )
  {
    cout << "Failure in mapping to parent ref coords for SE child; maxDiff = " << maxDiff << endl;
    success = false;
  }

  return success;
}
Beispiel #5
0
bool ScratchPadTests::testSpatiallyFilteredFunction()
{
  bool success = true;
  FunctionPtr one = Function::constant(1.0);
  SpatialFilterPtr positiveX = Teuchos::rcp( new PositiveX );
  FunctionPtr heaviside = Teuchos::rcp( new SpatiallyFilteredFunction<double>(one, positiveX) );

  int numCells = _basisCache->getPhysicalCubaturePoints().dimension(0);
  int numPoints = _testPoints.dimension(0);

  FieldContainer<double> values(numCells,numPoints);
  FieldContainer<double> expectedValues(numCells,numPoints);

  for (int cellIndex=0; cellIndex<numCells; cellIndex++)
  {
    for (int ptIndex=0; ptIndex<numPoints; ptIndex++)
    {
      double x = _basisCache->getPhysicalCubaturePoints()(cellIndex,ptIndex,0);
      if (x > 0)
      {
        expectedValues(cellIndex,ptIndex) = 1.0;
      }
      else
      {
        expectedValues(cellIndex,ptIndex) = 0.0;
      }
    }
  }

  heaviside->values(values,_basisCache);

  double tol = 1e-15;
  double maxDiff = 0.0;
  if ( ! fcsAgree(expectedValues, values, tol, maxDiff) )
  {
    success = false;
    cout << "testSpatiallyFilteredFunction: Expected values differ from actual; maxDiff: " << maxDiff << endl;
  }
  return success;
}
Beispiel #6
0
TEST_F(MPIWrapperTests, TestEntryWiseSum)
{
  int numProcs = Teuchos::GlobalMPISession::getNProc();
  int rank = Teuchos::GlobalMPISession::getRank();
  
  FieldContainer<double> expectedValues(2);
  for (int i=0; i<numProcs; i++) {
    expectedValues[0] += i*i;
    expectedValues[1] += 1;
  }
  FieldContainer<double> values(2);
  values[0] = rank*rank;
  values[1] = 1;
  
  MPIWrapper::entryWiseSum(values);
  double tol = 1e-16;
  
  double maxDiff = 0;
  EXPECT_TRUE(fcsAgree(values, expectedValues, tol, maxDiff))
    << "MPIWrapperTests::testentryWiseSum() failed with maxDiff " << maxDiff << endl;
  // EXPECT_EQ(rank, 2) << "rank " << rank << endl;
}
Beispiel #7
0
bool MPIWrapperTests::testentryWiseSum() {
  bool success = true;
  int numProcs = Teuchos::GlobalMPISession::getNProc();
  int rank = Teuchos::GlobalMPISession::getRank();
  
  FieldContainer<double> expectedValues(2);
  for (int i=0; i<numProcs; i++) {
    expectedValues[0] += i*i;
    expectedValues[1] += 1;
  }
  FieldContainer<double> values(2);
  values[0] = rank*rank;
  values[1] = 1;
  
  MPIWrapper::entryWiseSum(values);
  double tol = 1e-16;
  
  double maxDiff = 0;
  if (! fcsAgree(values, expectedValues, tol, maxDiff) ) {
    success = false;
    cout << "MPIWrapperTests::testentryWiseSum() failed with maxDiff " << maxDiff << endl;
  }
  return success;
}
bool LinearTermTests::testBoundaryPlusVolumeTerms()
{
  bool success = true;

  // notion is integration by parts:
  // (div f, v) = < f * n, v > - (f, grad v)

  // We perform two subtests for each test: first we try with a particular
  // function substituted for the variable.  Second, we integrate over the
  // basis for the mesh (i.e. we test a whole bunch of functions, whose
  // precise definition is a bit complicated).

  // A third test is against the two-term LinearTerm::integrate() method.
  // This doesn't do integration by parts, but rather tests that
  // (u + u->dot_normal(), v) = (u,v) + (u->dot_normal(), v)

  /////////////   FIRST TEST  ////////////////

  // start simply: define f to be (x, 0)
  // (div f, v) = (1, v)
  // < f * n, v > - (f, grad v) = < x n1, v > - ( x, v->dx() )

  FunctionPtr x = Function::xn(1);
  FunctionPtr y = Function::yn(1);
  FunctionPtr x2 = Function::xn(2);
  FunctionPtr y2 = Function::yn(2);
  FunctionPtr x3 = Function::xn(3);
  FunctionPtr y3 = Function::yn(3);

  vector< FunctionPtr > f_fxns;
  f_fxns.push_back( Function::vectorize( x,    Function::zero() ) ); // div of this = 1
  f_fxns.push_back( Function::vectorize( x2 / 6.0, x2 * y / 2.0 ) ); // div of this = x / 3 + x^2 / 2

  for ( vector< FunctionPtr >::iterator fIt = f_fxns.begin(); fIt != f_fxns.end(); fIt++)
  {
    FunctionPtr vector_fxn = *fIt;
    LinearTermPtr lt_v = vector_fxn->div()*v1;

    // part a: substitute v1 = x*y^2

    FunctionPtr v1_value = x*y2;
    map< int, FunctionPtr > var_values;
    var_values[v1->ID()] = v1_value;

    double expectedValue = lt_v->evaluate(var_values, false)->integrate(mesh);

    FunctionPtr n = Function::normal();

    LinearTermPtr ibp = vector_fxn * n * v1 - vector_fxn * v1->grad();

    int numCells = basisCache->getPhysicalCubaturePoints().dimension(0);
    int numPoints = basisCache->getPhysicalCubaturePoints().dimension(1);
    int spaceDim = basisCache->getSpaceDim();
    FieldContainer<double> vector_fxn_values(numCells,numPoints,spaceDim);
    vector_fxn->values(vector_fxn_values,basisCache);
//    cout << "vector_fxn values: \n" << vector_fxn_values;

    double boundaryIntegralSum = ibp->evaluate(var_values,true)->integrate(mesh);
    double volumeIntegralSum   = ibp->evaluate(var_values,false)->integrate(mesh);
    double actualValue = boundaryIntegralSum + volumeIntegralSum;

    double tol = 1e-14;
    if (abs(expectedValue - actualValue)>tol)
    {
      success = false;
    }

    // part b: integrate the bases over each of the cells:
    int num_dofs = testOrder->totalDofs();
    FieldContainer<double> integrals_expected( mesh->numActiveElements(), num_dofs );
    FieldContainer<double> integrals_actual( mesh->numActiveElements(), num_dofs );

    lt_v->integrate(integrals_expected,testOrder,basisCache);
    ibp->integrate(integrals_actual,testOrder,basisCache);

    double maxDiff = 0;
    if (! fcsAgree(integrals_actual, integrals_expected, tol, maxDiff) )
    {
      cout << "LT integrated by parts does not agree with the original; maxDiff: " << maxDiff << endl;
      success = false;
    }

    // just on the odd chance that ordering makes a difference, repeat this test with the opposite order in ibp:
    ibp =  - vector_fxn * v1->grad() + vector_fxn * n * v1;
    ibp->integrate(integrals_actual,testOrder,basisCache, false, false);

    maxDiff = 0;
    if (! fcsAgree(integrals_actual, integrals_expected, tol, maxDiff) )
    {
      cout << "LT integrated by parts does not agree with the original; maxDiff: " << maxDiff << endl;
      success = false;
    }

    // part c: two-term integrals
    FieldContainer<double> integrals_expected_two_term( mesh->numActiveElements(), num_dofs, num_dofs);
    FieldContainer<double> integrals_actual_two_term( mesh->numActiveElements(), num_dofs, num_dofs );
    LinearTermPtr ibp1 = vector_fxn * n * v1;
    LinearTermPtr ibp2 = - vector_fxn * v1->grad();
    lt_v->integrate(integrals_expected_two_term, testOrder, ibp1 + ibp2, testOrder, basisCache, false, false);
    lt_v->integrate(integrals_actual_two_term, testOrder, ibp1, testOrder, basisCache, false, false); // don't forceBoundary, don't sumInto
    lt_v->integrate(integrals_actual_two_term, testOrder, ibp2, testOrder, basisCache, false, true);  // DO sumInto

    maxDiff = 0;
    if (! fcsAgree(integrals_actual_two_term, integrals_expected_two_term, tol, maxDiff) )
    {
      cout << "two-term integration is not bilinear; maxDiff: " << maxDiff << endl;
      success = false;
    }

    // now, same thing but with the roles of ibp{1|2} and lt_v reversed:
    (ibp1 + ibp2)->integrate(integrals_expected_two_term, testOrder, lt_v, testOrder, basisCache, false, false);
    ibp1->integrate(integrals_actual_two_term, testOrder, lt_v, testOrder, basisCache, false, false); // don't forceBoundary, don't sumInto
    ibp2->integrate(integrals_actual_two_term, testOrder, lt_v, testOrder, basisCache, false, true);  // DO sumInto

    maxDiff = 0;
    if (! fcsAgree(integrals_actual_two_term, integrals_expected_two_term, tol, maxDiff) )
    {
      cout << "two-term integration is not bilinear; maxDiff: " << maxDiff << endl;
      success = false;
    }

    // now, test that two-term integration commutes in the two terms:
    ibp1->integrate(integrals_expected_two_term, testOrder, lt_v, testOrder, basisCache, false, false);
    lt_v->integrate(integrals_actual_two_term, testOrder, ibp1, testOrder, basisCache, false, false);

    // we expect the integrals to commute up to a transpose, so let's transpose one of the containers:
    transposeFieldContainer(integrals_expected_two_term);
    maxDiff = 0;
    if (! fcsAgree(integrals_actual_two_term, integrals_expected_two_term, tol, maxDiff) )
    {
      cout << "two-term integration does not commute for boundary value (ibp1); maxDiff: " << maxDiff << endl;
      success = false;
    }

    ibp2->integrate(integrals_expected_two_term, testOrder, lt_v, testOrder, basisCache, false, false);
    lt_v->integrate(integrals_actual_two_term, testOrder, ibp2, testOrder, basisCache, false, false);

    // we expect the integrals to commute up to a transpose, so let's transpose one of the containers:
    transposeFieldContainer(integrals_expected_two_term);
    maxDiff = 0;
    if (! fcsAgree(integrals_actual_two_term, integrals_expected_two_term, tol, maxDiff) )
    {
      cout << "two-term integration does not commute for volume value (ibp2); maxDiff: " << maxDiff << endl;
      success = false;
    }

    // part d: to suss out where the integration failure happens in the non-commuting case:
    //         1. Substitute v1 = 1 in ibp2; get a function ibp2_at_v1_equals_one back.
    //         2. Substitute v1 = 1 in lt_v; get a function lt_v_at_v1_equals_one back.
    //         3. Integrate ibp2_at_v1_equals_one * lt_v_at_v1_equals_one over the mesh.  Get a double result.
    //         4. Because basis is nodal, the representation for v1 = 1 is just all 1s for coefficients.
    //            Therefore, the sum of the entries in the integrals_*_two_term matrices will should match
    //            the function integral.  Whichever doesn't match is wrong.

    // first, let's confirm that the v1 basis *is* nodal:
    BasisPtr v1Basis = testOrder->getBasis(v1->ID());
    if (! v1Basis->isNodal())
    {
      cout << "testBoundaryPlusVolumeTerms: final part of test relies on a nodal basis, but the basis is not nodal.";
      cout << "  Exiting test early (with whatever success value we have thus far).\n";
      return success;
    }

    map< int, FunctionPtr > v1_equals_one;
    v1_equals_one[v1->ID()] = Function::constant(1.0);

    FunctionPtr ibp1_at_v1_equals_one = ibp1->evaluate(v1_equals_one,true);  // ibp1 has only a boundary term, so we just ask for this
    FunctionPtr ibp2_at_v1_equals_one = ibp2->evaluate(v1_equals_one,false); // ibp2 has no boundary terms, so we don't ask for these
    FunctionPtr lt_v_at_v1_equals_one = lt_v->evaluate(v1_equals_one,false); // lt_v also has no boundary terms

    if (ibp1_at_v1_equals_one->isZero())
    {
      cout << "ibp1_at_v1_equals_one->isZero() = true.\n";
    }
    if (lt_v_at_v1_equals_one->isZero())
    {
      cout << "lt_v_at_v1_equals_one->isZero() = true.\n";
    }

    FieldContainer<double> integrals_lt_v_first( mesh->numActiveElements(), num_dofs, num_dofs );
    FieldContainer<double> integrals_ibp1_first( mesh->numActiveElements(), num_dofs, num_dofs );
    FieldContainer<double> integrals_ibp2_first( mesh->numActiveElements(), num_dofs, num_dofs );

    double lt_v_first_integral = 0.0, ibp1_first_integral = 0.0, ibp2_first_integral = 0.0;

    double integral = (ibp1_at_v1_equals_one * lt_v_at_v1_equals_one)->integrate(mesh);
    ibp1->integrate(integrals_ibp1_first,  testOrder, lt_v, testOrder, basisCache, false, false);
    lt_v->integrate(integrals_lt_v_first, testOrder, ibp1, testOrder, basisCache, false, false);

    for (int i=0; i<integrals_lt_v_first.size(); i++)
    {
      lt_v_first_integral += integrals_lt_v_first[i];
      ibp1_first_integral += integrals_ibp1_first[i];
    }

    if (abs(lt_v_first_integral - integral) > tol)
    {
      double diff = abs(lt_v_first_integral - integral);
      success = false;
      cout << "Integral with v1=1 substituted does not match two-term integration of (lt_v,ibp1) with lt_v as this. diff = " << diff << "\n";
      cout << "lt_v_first_integral = " << lt_v_first_integral << endl;
      cout << "    (true) integral = " << integral << endl;
    }

    if (abs(ibp1_first_integral - integral) > tol)
    {
      double diff = abs(ibp1_first_integral - integral);
      success = false;
      cout << "Integral with v1=1 substituted does not match two-term integration of (lt_v,ibp1) with ibp1 as this. diff = " << diff << "\n";
      cout << "ibp1_first_integral = " << ibp1_first_integral << endl;
      cout << "    (true) integral = " << integral << endl;
    }

    // now, do the same but for ibp2
    integral = (ibp2_at_v1_equals_one * lt_v_at_v1_equals_one)->integrate(mesh);
    ibp2->integrate(integrals_ibp2_first,  testOrder, lt_v, testOrder, basisCache, false, false);
    lt_v->integrate(integrals_lt_v_first,  testOrder, ibp2, testOrder, basisCache, false, false);

    // reset the sums:
    lt_v_first_integral = 0.0;
    ibp1_first_integral = 0.0;
    ibp2_first_integral = 0.0;
    for (int i=0; i<integrals_lt_v_first.size(); i++)
    {
      lt_v_first_integral += integrals_lt_v_first[i];
      ibp2_first_integral += integrals_ibp2_first[i];
    }

    if (abs(lt_v_first_integral - integral) > tol)
    {
      double diff = abs(lt_v_first_integral - integral);
      success = false;
      cout << "Integral with v1=1 substituted does not match two-term integration of (lt_v,ibp2) with lt_v as this. diff = " << diff << "\n";
      cout << "lt_v_first_integral = " << lt_v_first_integral << endl;
      cout << "    (true) integral = " << integral << endl;
    }

    if (abs(ibp2_first_integral - integral) > tol)
    {
      double diff = abs(ibp2_first_integral - integral);
      success = false;
      cout << "Integral with v1=1 substituted does not match two-term integration of (lt_v,ibp2) with ibp2 as this. diff = " << diff << "\n";
      cout << "ibp1_first_integral = " << ibp1_first_integral << endl;
      cout << "    (true) integral = " << integral << endl;
    }
  }

  return success;
}
bool ParametricCurveTests::testGradientWrapper()
{
  bool success = true;

  // create an artificial function whose gradient is "interesting" and known
  FunctionPtr t1 = Function::xn(1);
  FunctionPtr t2 = Function::yn(1);
  FunctionPtr xt = t1 + t1 * t2;
  FunctionPtr yt = t2 + 2 * t1 * t2;
  FunctionPtr xt_dt1 = 1 + t2;
  FunctionPtr xt_dt2 = t1;
  FunctionPtr yt_dt1 = 2 * t2;
  FunctionPtr yt_dt2 = 1 + 2 * t1;

  FunctionPtr ft = Function::vectorize(xt, yt);
  FunctionPtr ft_dt1 = Function::vectorize(xt_dt1, yt_dt1);
  FunctionPtr ft_dt2 = Function::vectorize(xt_dt2, yt_dt2);

  FunctionPtr ft_gradt = Function::vectorize(ft_dt1, ft_dt2);

  // first test: confirm that on a parametric quad, the wrapped function agrees with the naked one
  int cubatureDegree = 5;
  BasisCachePtr parametricQuadCache = BasisCache::parametricQuadCache(cubatureDegree);
  FunctionPtr fx_gradx = ParametricCurve::parametricGradientWrapper(ft_gradt, true);

  double tol = 1e-14;
  if (! ft_gradt->equals(fx_gradx, parametricQuadCache))
  {
    success = false;
    cout << "on a parametric quad, the wrapped gradient doesn't agree with the naked one";
    reportFunctionValueDifferences(ft_gradt, fx_gradx, parametricQuadCache, tol);
  }
  if (! ft_gradt->equals(ft->grad(), parametricQuadCache))
  {
    success = false;
    cout << "on a parametric quad, manual gradient disagrees with automatic one (error in test construction, likely).";
    reportFunctionValueDifferences(ft_gradt, ft->grad(), parametricQuadCache, tol);
  }

  // on the quad domain defined by (0,0), (1,0), (2,3), (0,1),
  // some algebra shows that for x and y as functions of the parametric
  // coordinates, we have
  // x = t1 +     t1 * t2
  // y = t2 + 2 * t1 * t2
  // which gives the result that our original function f(t1,t2) = (t1 + t1 * t2, t2 + 2 * t1 * t2) =  (x, y)

  FunctionPtr x = Function::xn(1); // understood in physical space
  FunctionPtr y = Function::yn(1);
  FunctionPtr f1_xy = x;
  FunctionPtr f2_xy = y;
  FunctionPtr f_xy = Function::vectorize(f1_xy, f2_xy);

  // set up the quad domain
  FieldContainer<double> physicalCellNodes(1,4,2); // (C,P,D)
  physicalCellNodes(0,0,0) = 0;
  physicalCellNodes(0,0,1) = 0;

  physicalCellNodes(0,1,0) = 1;
  physicalCellNodes(0,1,1) = 0;

  physicalCellNodes(0,2,0) = 2;
  physicalCellNodes(0,2,1) = 3;

  physicalCellNodes(0,3,0) = 0;
  physicalCellNodes(0,3,1) = 1;

  // physical space BasisCache:
  shards::CellTopology quad_4(shards::getCellTopologyData<shards::Quadrilateral<4> >() );
  BasisCachePtr basisCache = Teuchos::rcp( new BasisCache(physicalCellNodes, quad_4, cubatureDegree));

  // as a preliminary test, check that the Jacobian values and inverse values agree with our expectations
  // we expect the Jacobian to be:
  //        [ 1 + t2      t1 ]
  // 1/2 *  [                ]
  //        [ 2 * t2  1 + t2 ]
  // where (t1,t2) are parametric coordinates and the 1/2 comes from the transformation from reference
  // to parametric space
  int numCells = 1;
  int numPoints = basisCache->getRefCellPoints().dimension(0);
  int spaceDim = 2;
  FieldContainer<double> jacobianExpected(numCells,numPoints,spaceDim,spaceDim);
  FieldContainer<double> jacobianInvExpected(numCells,numPoints,spaceDim,spaceDim);
  // also check that the function we've chosen has the expected values
  // by first computing its gradient in parametric space and then dividing by 2 to account
  // for the transformation from reference to parametric space
  FieldContainer<double> fgrad_based_jacobian(numCells,numPoints,spaceDim,spaceDim);
  ft_gradt->values(fgrad_based_jacobian, parametricQuadCache);
  FieldContainer<double> parametricPoints = basisCache->computeParametricPoints();
  for (int ptIndex=0; ptIndex<numPoints; ptIndex++)
  {
    double t1 = parametricPoints(0,ptIndex,0);
    double t2 = parametricPoints(0,ptIndex,1);
    jacobianExpected(0,ptIndex,0,0) = 0.5 * (1 + t2);
    jacobianExpected(0,ptIndex,0,1) = 0.5 * (t1);
    jacobianExpected(0,ptIndex,1,0) = 0.5 * (2 * t2);
    jacobianExpected(0,ptIndex,1,1) = 0.5 * (1 + 2 * t1);
    jacobianInvExpected(0,ptIndex,0,0) = (2.0 / (1 + 2 * t1 + t2) ) * (1 + 2 * t1);
    jacobianInvExpected(0,ptIndex,0,1) = (2.0 / (1 + 2 * t1 + t2) ) * (- t1);
    jacobianInvExpected(0,ptIndex,1,0) = (2.0 / (1 + 2 * t1 + t2) ) * (- 2 * t2);
    jacobianInvExpected(0,ptIndex,1,1) = (2.0 / (1 + 2 * t1 + t2) ) * (1 + t2);

    fgrad_based_jacobian(0,ptIndex,0,0) /= 2.0;
    fgrad_based_jacobian(0,ptIndex,0,1) /= 2.0;
    fgrad_based_jacobian(0,ptIndex,1,0) /= 2.0;
    fgrad_based_jacobian(0,ptIndex,1,1) /= 2.0;
  }
  FieldContainer<double> jacobian = basisCache->getJacobian();
  FieldContainer<double> jacobianInv = basisCache->getJacobianInv();
  double maxDiff = 0;
  if (! fcsAgree(jacobianExpected, jacobian, tol, maxDiff))
  {
    success = false;
    cout << "Jacobian expected does not match actual.\n";
    reportFunctionValueDifferences(parametricPoints, jacobian, jacobianExpected, tol);
  }
  if (! fcsAgree(jacobianInvExpected, jacobianInv, tol, maxDiff))
  {
    success = false;
    cout << "Jacobian inverse expected does not match actual.\n";
    reportFunctionValueDifferences(parametricPoints, jacobianInv, jacobianInvExpected, tol);
  }
  if (! fcsAgree(fgrad_based_jacobian, jacobianExpected, tol, maxDiff))
  {
    success = false;
    cout << "Jacobian from fgrad does not agree with the transformation jacobian (problem with test?).\n";
    reportFunctionValueDifferences(parametricPoints, fgrad_based_jacobian, jacobianExpected, tol);
  }

  // test that the gradient values agree
  if (! fx_gradx->equals(f_xy->grad(), basisCache))
  {
    success = false;
    cout << "wrapped gradient does not agree with analytically transformed function.\n";
    reportFunctionValueDifferences(fx_gradx, f_xy->grad(), basisCache, tol);
  }

  // finally, although this isn't really the right place for this, it is convenient here
  // to test the TFI for the "mesh" we were concerned with above.
  int H1Order = 5;
  BFPtr bf = VGPStokesFormulation(1.0).bf();
  physicalCellNodes.resize(4,2);
  int horizontalElements = 1, verticalElements = 1;
  MeshPtr mesh = MeshFactory::quadMesh(bf, H1Order, physicalCellNodes);

  int cellID = 0;
  vector< ParametricCurvePtr > edges = mesh->parametricEdgesForCell(cellID);
  ParametricSurfacePtr tfi = ParametricSurface::transfiniteInterpolant(edges);

  double v2[2];
  edges[2]->value(0, v2[0], v2[1]);
//  cout << "v2 = (" << v2[0] << ", " << v2[1] << ")\n";

  if ( ! tfi->equals(f_xy, basisCache) )
  {
    success = false;
    cout << "TFI does not agree with analytically constructed transformation function.\n";
    reportFunctionValueDifferences(tfi, f_xy, basisCache, tol);
  }
  if ( ! tfi->grad()->equals(f_xy->grad(), basisCache) )
  {
    success = false;
    cout << "TFI does not agree with analytically constructed transformation function.\n";
    reportFunctionValueDifferences(tfi->grad(), f_xy->grad(), basisCache, tol);
  }

  return success;
}
Beispiel #10
0
bool FunctionTests::testValuesDottedWithTensor()
{
  bool success = true;

  vector< FunctionPtr > vectorFxns;

  double xValue = 3, yValue = 4;
  FunctionPtr simpleVector = Function::vectorize(Function::constant(xValue), Function::constant(yValue));
  vectorFxns.push_back(simpleVector);
  FunctionPtr x = Function::xn(1);
  FunctionPtr y = Function::yn(1);
  vectorFxns.push_back( Function::vectorize(x*x, x*y) );

  VGPStokesFormulation vgpStokes = VGPStokesFormulation(1.0);
  BFPtr bf = vgpStokes.bf();

  int h1Order = 1;
  MeshPtr mesh = MeshFactory::quadMesh(bf, h1Order);

  int cellID=0; // the only cell
  BasisCachePtr basisCache = BasisCache::basisCacheForCell(mesh, cellID);

  for (int i=0; i<vectorFxns.size(); i++)
  {
    FunctionPtr vectorFxn_i = vectorFxns[i];
    for (int j=0; j<vectorFxns.size(); j++)
    {
      FunctionPtr vectorFxn_j = vectorFxns[j];
      FunctionPtr dotProduct = vectorFxn_i * vectorFxn_j;
      FunctionPtr expectedDotProduct = vectorFxn_i->x() * vectorFxn_j->x() + vectorFxn_i->y() * vectorFxn_j->y();
      if (! expectedDotProduct->equals(dotProduct, basisCache))
      {
        cout << "testValuesDottedWithTensor() failed: expected dot product does not match dotProduct.\n";
        success = false;
        double tol = 1e-14;
        reportFunctionValueDifferences(dotProduct, expectedDotProduct, basisCache, tol);
      }
    }
  }

  // now, let's try the same thing, but for a LinearTerm dot product
  VarFactoryPtr vf = VarFactory::varFactory();
  VarPtr v = vf->testVar("v", HGRAD);

  DofOrderingPtr dofOrdering = Teuchos::rcp( new DofOrdering(CellTopology::quad()) );
  shards::CellTopology quad_4(shards::getCellTopologyData<shards::Quadrilateral<4> >() );
  BasisPtr basis = BasisFactory::basisFactory()->getBasis(h1Order, quad_4.getKey(), Camellia::FUNCTION_SPACE_HGRAD);
  dofOrdering->addEntry(v->ID(), basis, v->rank());

  int numCells = 1;
  int numFields = basis->getCardinality();

  for (int i=0; i<vectorFxns.size(); i++)
  {
    FunctionPtr f_i = vectorFxns[i];
    LinearTermPtr lt_i = f_i * v;
    LinearTermPtr lt_i_x = f_i->x() * v;
    LinearTermPtr lt_i_y = f_i->y() * v;
    for (int j=0; j<vectorFxns.size(); j++)
    {
      FunctionPtr f_j = vectorFxns[j];
      LinearTermPtr lt_j = f_j * v;
      LinearTermPtr lt_j_x = f_j->x() * v;
      LinearTermPtr lt_j_y = f_j->y() * v;
      FieldContainer<double> values(numCells,numFields,numFields);
      lt_i->integrate(values, dofOrdering, lt_j, dofOrdering, basisCache);
      FieldContainer<double> values_expected(numCells,numFields,numFields);
      lt_i_x->integrate(values_expected,dofOrdering,lt_j_x,dofOrdering,basisCache);
      lt_i_y->integrate(values_expected,dofOrdering,lt_j_y,dofOrdering,basisCache);
      double tol = 1e-14;
      double maxDiff = 0;
      if (!fcsAgree(values, values_expected, tol, maxDiff))
      {
        cout << "FunctionTests::testValuesDottedWithTensor: ";
        cout << "dot product and sum of the products of scalar components differ by maxDiff " << maxDiff;
        cout << " in LinearTerm::integrate().\n";
        success = false;
      }
    }
  }

//  // finally, let's try the same sort of thing, but now with a vector-valued basis
//  BasisPtr vectorBasisTemp = BasisFactory::basisFactory()->getBasis(h1Order, quad_4.getKey(), Camellia::FUNCTION_SPACE_VECTOR_HGRAD);
//  VectorBasisPtr vectorBasis = Teuchos::rcp( (VectorizedBasis<double, FieldContainer<double> > *)vectorBasisTemp.get(),false);
//
//  BasisPtr compBasis = vectorBasis->getComponentBasis();
//
//  // create a new v, and a new dofOrdering
//  VarPtr v_vector = vf->testVar("v_vector", VECTOR_HGRAD);
//  dofOrdering = Teuchos::rcp( new DofOrdering );
//  dofOrdering->addEntry(v_vector->ID(), vectorBasis, v_vector->rank());
//
//  DofOrderingPtr dofOrderingComp = Teuchos::rcp( new DofOrdering );
//  dofOrderingComp->addEntry(v->ID(), compBasis, v->rank());
//

  return success;
}
Beispiel #11
0
bool FunctionTests::testJacobianOrdering()
{
  bool success = true;

  FunctionPtr y = Function::yn(1);

  FunctionPtr f = Function::vectorize(y, Function::zero());

  // test 1: Jacobian ordering is f_i,j
  int spaceDim = 2;
  int cellID = 0;
  BasisCachePtr basisCache = BasisCache::basisCacheForCell(_spectralConfusionMesh, cellID);

  FieldContainer<double> physicalPoints = basisCache->getPhysicalCubaturePoints();
  int numCells = physicalPoints.dimension(0);
  int numPoints = physicalPoints.dimension(1);

  FieldContainer<double> expectedValues(numCells, numPoints, spaceDim, spaceDim);

  for (int cellIndex=0; cellIndex<numCells; cellIndex++)
  {
    for (int ptIndex=0; ptIndex<numPoints; ptIndex++)
    {
      expectedValues(cellIndex,ptIndex,0,0) = 0;
      expectedValues(cellIndex,ptIndex,0,1) = 1;
      expectedValues(cellIndex,ptIndex,1,0) = 0;
      expectedValues(cellIndex,ptIndex,1,1) = 0;
    }
  }

  FieldContainer<double> values(numCells, numPoints, spaceDim, spaceDim);
  f->grad(spaceDim)->values(values, basisCache);

  double maxDiff = 0;
  double tol = 1e-14;
  if (! fcsAgree(expectedValues, values, tol, maxDiff))
  {
    cout << "expectedValues does not match values in testJacobianOrdering().\n";
    reportFunctionValueDifferences(physicalPoints, expectedValues, values, tol);
    success = false;
  }

  // test 2: ordering of VectorizedBasis agrees
  // (actually implemented where it belongs, in Vectorized_BasisTestSuite)

  // test 3: ordering of CellTools::getJacobian
  FieldContainer<double> nodes(1,4,2);
  nodes(0,0,0) =  1;
  nodes(0,0,1) = -2;
  nodes(0,1,0) =  1;
  nodes(0,1,1) =  2;
  nodes(0,2,0) = -1;
  nodes(0,2,1) =  2;
  nodes(0,3,0) = -1;
  nodes(0,3,1) = -2;

  shards::CellTopology quad_4(shards::getCellTopologyData<shards::Quadrilateral<4> >() );
  int cubDegree = 4;
  BasisCachePtr rotatedCache = Teuchos::rcp( new BasisCache(nodes, quad_4, cubDegree) );

  physicalPoints = rotatedCache->getPhysicalCubaturePoints();
  numCells = physicalPoints.dimension(0);
  numPoints = physicalPoints.dimension(1);

  FieldContainer<double> expectedJacobian(numCells,numPoints,spaceDim,spaceDim);
  for (int cellIndex=0; cellIndex<numCells; cellIndex++)
  {
    for (int ptIndex=0; ptIndex<numPoints; ptIndex++)
    {
      expectedJacobian(cellIndex,ptIndex,0,0) = 0;
      expectedJacobian(cellIndex,ptIndex,0,1) = -1;
      expectedJacobian(cellIndex,ptIndex,1,0) = 2;
      expectedJacobian(cellIndex,ptIndex,1,1) = 0;
    }
  }

  FieldContainer<double> jacobianValues = rotatedCache->getJacobian();

  maxDiff = 0;
  if (! fcsAgree(expectedJacobian, jacobianValues, tol, maxDiff))
  {
    cout << "expectedJacobian does not match jacobianValues in testJacobianOrdering().\n";
    reportFunctionValueDifferences(physicalPoints, expectedJacobian, jacobianValues, tol);
    success = false;
  }

  return success;
}