예제 #1
0
void testPointUnitSphere( const math::Vector3<real_t> & p )
{
   static const geometry::Sphere UNIT_SPHERE( math::Vector3<real_t>( 0, 0, 0 ), real_t( 1 ) );
   static const real_t EPSILON = real_t(1e-4);

   real_t q = lbm::intersectionRatioBisection( UNIT_SPHERE, p, -p, EPSILON );
   
   Vector3<real_t> intersectionPoint = p + (-p) * q;
   real_t intersectionRadius = intersectionPoint.length();

   WALBERLA_CHECK_LESS( std::fabs( intersectionRadius - real_t( 1 ) ), EPSILON );

   q = lbm::intersectionRatioSphere( UNIT_SPHERE, p, -p );
   
   intersectionPoint = p + ( -p ) * q;
   intersectionRadius = intersectionPoint.length();
   
   WALBERLA_CHECK_LESS( std::fabs( intersectionRadius - real_t( 1 ) ), EPSILON );
   
   q = lbm::intersectionRatio( UNIT_SPHERE, p, -p, EPSILON );
   
   intersectionPoint = p + ( -p ) * q;
   intersectionRadius = intersectionPoint.length();
   
   WALBERLA_CHECK_LESS( std::fabs( intersectionRadius - real_t( 1 ) ), EPSILON );
}
예제 #2
0
void testAABB()
{

   static const math::Vector3<real_t> ZERO( real_t( 0 ), real_t( 0 ), real_t( 0 ) );
   static const math::Vector3<real_t> UNIT( real_t( 1 ), real_t( 1 ), real_t( 1 ) );
   static const real_t EPSILON = real_t(1e-4);

   boost::random::mt19937 randomEngine;

   std::vector<math::AABB> testAABBs;
   testAABBs.push_back( math::AABB( -UNIT, UNIT ) );
   testAABBs.push_back( math::AABB(  ZERO, UNIT ) );
   testAABBs.push_back( math::AABB( -UNIT, ZERO ) );

   for( auto aabbIt = testAABBs.begin(); aabbIt != testAABBs.end(); ++aabbIt )
   {
      const math::AABB outerAABB = aabbIt->getScaled( real_t( 2 ) );
      std::vector< std::pair< Vector3<real_t>, Vector3<real_t> > > testPoints;

      for( int i = 0; i < 100; ++i )
      {
         Vector3<real_t> outerPoint, innerPoint;
         do { outerPoint = outerAABB.randomPoint( randomEngine ); } while( aabbIt->contains( outerPoint ) );
         innerPoint = aabbIt->randomPoint( randomEngine );
         testPoints.push_back( std::make_pair( outerPoint, innerPoint - outerPoint ) );
      }
      
      for( auto pointIt = testPoints.begin(); pointIt != testPoints.end(); ++pointIt )
      {
         const Vector3<real_t> & fluidPoint = pointIt->first;
         const Vector3<real_t> & direction  = pointIt->second;

         real_t q = lbm::intersectionRatio( *aabbIt, fluidPoint, direction, EPSILON );
         Vector3<real_t> intersectionPoint = fluidPoint + direction * q;
         WALBERLA_CHECK_LESS( std::fabs( aabbIt->sqSignedDistance( intersectionPoint ) ), EPSILON * EPSILON );

         q = lbm::intersectionRatioBisection( *aabbIt, fluidPoint, direction, EPSILON );
         intersectionPoint = fluidPoint + direction * q;
         WALBERLA_CHECK_LESS( std::fabs( aabbIt->sqSignedDistance( intersectionPoint ) ), EPSILON * EPSILON );
      }
   }

}
예제 #3
0
   void checkSphWallLubricationForce()
   {
      const uint_t timestep (timeloop_->getCurrentTimeStep()+1);

      // variables for output of total force - requires MPI-reduction
      pe::Vec3 forceSphr1(0);

      // temporary variables
      real_t gap        (0);

      for( auto blockIt = blocks_->begin(); blockIt != blocks_->end(); ++blockIt )
      {
         for( auto curSphereIt = pe::BodyIterator::begin<pe::Sphere>( *blockIt, bodyStorageID_); curSphereIt != pe::BodyIterator::end<pe::Sphere>(); ++curSphereIt )
         {
            pe::SphereID sphereI = ( curSphereIt.getBodyID() );
            if ( sphereI->getID() == id1_ )
            {
               for( auto globalBodyIt = globalBodyStorage_->begin(); globalBodyIt != globalBodyStorage_->end(); ++globalBodyIt)
               {
                  if( globalBodyIt->getID() == id2_ )
                  {
                     pe::PlaneID planeJ = static_cast<pe::PlaneID>( globalBodyIt.getBodyID() );
                     gap = pe::getSurfaceDistance(sphereI, planeJ);
                     break;
                  }
               }
               break;
            }
         }
      }

      WALBERLA_MPI_SECTION()
      {
         mpi::reduceInplace( gap, mpi::MAX );
      }
      WALBERLA_ROOT_SECTION()
      {
         if (gap < real_comparison::Epsilon<real_t>::value )
         {
            gap = walberla::math::Limits<real_t>::inf();
            WALBERLA_LOG_INFO_ON_ROOT( "Sphere still too far from wall to calculate gap!" );
         } else {
            WALBERLA_LOG_INFO_ON_ROOT( "Gap between sphere and wall: " << gap );
         }
      }

      // get force on sphere
      for( auto blockIt = blocks_->begin(); blockIt != blocks_->end(); ++blockIt )
      {
         for( auto bodyIt = pe::BodyIterator::begin<pe::Sphere>( *blockIt, bodyStorageID_); bodyIt != pe::BodyIterator::end<pe::Sphere>(); ++bodyIt )
         {
            if( bodyIt->getID() == id1_ )
            {
               forceSphr1 += bodyIt->getForce();
            }
         }
      }

      // MPI reduction of pe forces over all processes
      WALBERLA_MPI_SECTION()
      {
         mpi::reduceInplace( forceSphr1[0], mpi::SUM );
         mpi::reduceInplace( forceSphr1[1], mpi::SUM );
         mpi::reduceInplace( forceSphr1[2], mpi::SUM );
      }
      WALBERLA_LOG_INFO_ON_ROOT("Total force on sphere " << id1_ << " : " << forceSphr1);

      if ( print_ )
      {
         WALBERLA_ROOT_SECTION()
         {
            std::ofstream file1;
            std::string filename1("Gap_LubricationForceBody1.txt");
            file1.open( filename1.c_str(), std::ofstream::app );
            file1.setf( std::ios::unitbuf );
            file1.precision(15);
            file1 << gap << " " << forceSphr1[0] << std::endl;
            file1.close();
         }
      }

      WALBERLA_ROOT_SECTION()
      {
         if ( timestep == uint_t(26399) )
         {
            // according to the formula from Ding & Aidun 2003
            // F = 6 * M_PI * rho_L * nu_L * relative velocity of both bodies=relative velocity of the sphere * r * r * 1/gap
            // the correct analytically calculated value is 339.292006996217
            // in this geometry setup the relative error is 0.183515322065561 %
            real_t analytical = real_c(6.0) * walberla::math::M_PI * real_c(1.0) * nu_L_ * real_c(-vel_[0]) * radius_ * radius_ * real_c(1.0)/gap;
            real_t relErr     = std::fabs( analytical - forceSphr1[0] ) / analytical * real_c(100.0);
            WALBERLA_CHECK_LESS( relErr, real_t(1) );
         }
      }

   }
예제 #4
0
   void checkSphSphLubricationForce()
   {
      const uint_t timestep (timeloop_->getCurrentTimeStep()+1);

      // variables for output of total force - requires MPI-reduction
      pe::Vec3 forceSphr1(0);
      pe::Vec3 forceSphr2(0);

      // temporary variables
      real_t gap        (0);

      // calculate gap between the two spheres
      for( auto blockIt = blocks_->begin(); blockIt != blocks_->end(); ++blockIt )
      {
         for( auto curSphereIt = pe::BodyIterator::begin<pe::Sphere>( *blockIt, bodyStorageID_); curSphereIt != pe::BodyIterator::end<pe::Sphere>(); ++curSphereIt )
         {
            pe::SphereID sphereI = ( curSphereIt.getBodyID() );
            if ( sphereI->getID() == id1_ )
            {
               for( auto blockIt2 = blocks_->begin(); blockIt2 != blocks_->end(); ++blockIt2 )
               {
                  for( auto oSphereIt = pe::BodyIterator::begin<pe::Sphere>( *blockIt2, bodyStorageID_); oSphereIt != pe::BodyIterator::end<pe::Sphere>(); ++oSphereIt )
                  {
                     pe::SphereID sphereJ = ( oSphereIt.getBodyID() );
                     if ( sphereJ->getID() == id2_ )
                     {
                        gap = pe::getSurfaceDistance( sphereI, sphereJ );
                        break;
                     }
                  }
               }
               break;
            }
         }
      }

      WALBERLA_MPI_SECTION()
      {
         mpi::reduceInplace( gap, mpi::MAX );
      }
      WALBERLA_ROOT_SECTION()
      {
         if (gap < real_comparison::Epsilon<real_t>::value )
         {
            // shadow copies have not been synced yet as the spheres are outside the overlap region
            gap = walberla::math::Limits<real_t>::inf();
            WALBERLA_LOG_INFO_ON_ROOT( "Spheres still too far apart to calculate gap!" );
         } else {
            WALBERLA_LOG_INFO_ON_ROOT( "Gap between sphere 1 and 2: " << gap );
         }
      }


      // get force on spheres
      for( auto blockIt = blocks_->begin(); blockIt != blocks_->end(); ++blockIt )
      {
         for( auto bodyIt = pe::BodyIterator::begin<pe::Sphere>( *blockIt, bodyStorageID_); bodyIt != pe::BodyIterator::end<pe::Sphere>(); ++bodyIt )
         {
            if( bodyIt->getID() == id1_ )
            {
               forceSphr1 += bodyIt->getForce();
            } else if( bodyIt->getID() == id2_ )
            {
               forceSphr2 += bodyIt->getForce();
            }
         }
      }

      // MPI reduction of pe forces over all processes
      WALBERLA_MPI_SECTION()
      {
         mpi::reduceInplace( forceSphr1[0], mpi::SUM );
         mpi::reduceInplace( forceSphr1[1], mpi::SUM );
         mpi::reduceInplace( forceSphr1[2], mpi::SUM );
         mpi::reduceInplace( forceSphr2[0], mpi::SUM );
         mpi::reduceInplace( forceSphr2[1], mpi::SUM );
         mpi::reduceInplace( forceSphr2[2], mpi::SUM );
      }
      WALBERLA_LOG_INFO_ON_ROOT("Total force on sphere " << id1_ << " : " << forceSphr1);
      WALBERLA_LOG_INFO_ON_ROOT("Total force on sphere " << id2_ << " : " << forceSphr2);

      if ( print_ )
      {
         WALBERLA_ROOT_SECTION()
         {
            std::ofstream file1;
            std::string filename1("Gap_LubricationForceBody1.txt");
            file1.open( filename1.c_str(), std::ofstream::app );
            file1.setf( std::ios::unitbuf );
            file1.precision(15);
            file1 << gap << " " << forceSphr1[0] << std::endl;
            file1.close();

            std::ofstream file2;
            std::string filename2("Gap_LubricationForceBody2.txt");
            file2.open( filename2.c_str(), std::ofstream::app );
            file2.setf( std::ios::unitbuf );
            file2.precision(15);
            file2 << gap << " " << forceSphr2[0] << std::endl;
            file2.close();
         }
      }


      WALBERLA_ROOT_SECTION()
      {
         if ( timestep == uint_t(1000) )
         {
            // both force x-components should be the same only with inverted signs
            WALBERLA_CHECK_FLOAT_EQUAL ( forceSphr2[0], -forceSphr1[0] );

            // according to the formula from Ding & Aidun 2003
            // F = 3/2 * M_PI * rho_L * nu_L * relative velocity of both spheres * r * r * 1/gap
            // the correct analytically calculated value is 339.2920063998
            // in this geometry setup the relative error is 0.1246489711 %
            real_t analytical = real_c(3.0)/real_c(2.0) * walberla::math::M_PI * real_c(1.0) * nu_L_ * real_c(2.0) * real_c(vel_[0]) * radius_ * radius_ * real_c(1.0)/gap;
            real_t relErr     = std::fabs( analytical - forceSphr2[0] ) / analytical * real_c(100.0);
            WALBERLA_CHECK_LESS( relErr, real_t(1) );
         }
      }
   }