//--------------------------------------------------------------
void WeakEquationElectronMomentum::B_integrand(
  const FIELD_MATS &fields,
  const GRAD_FIELD_MATS &grad_fields,
  const Material * material,
  DENS_MAT_VEC &flux) const
{
  convection(fields,material,flux);
}
void NSThermalEqResid<EvalT, Traits>::
evaluateFields(typename Traits::EvalData workset)
{
  typedef Intrepid2::FunctionSpaceTools FST;

  FST::scalarMultiplyDataData<ScalarT> (flux, ThermalCond, TGrad);

  FST::integrate<ScalarT>(TResidual, flux, wGradBF, Intrepid2::COMP_CPP, false); // "false" overwrites
  
  for (std::size_t cell=0; cell < workset.numCells; ++cell) {
    for (std::size_t qp=0; qp < numQPs; ++qp) {
      convection(cell,qp) = 0.0;
      if (haveSource) convection(cell,qp) -= Source(cell,qp);
      if (workset.transientTerms && enableTransient) 
	convection(cell,qp) += rho(cell,qp) * Cp(cell,qp) * Tdot(cell,qp);
      if (haveFlow) {
	for (std::size_t i=0; i < numDims; ++i) { 
	  convection(cell,qp) += 
	    rho(cell,qp) * Cp(cell,qp) * V(cell,qp,i) * TGrad(cell,qp,i);
	}
      }
    }
  }

  FST::integrate<ScalarT>(TResidual, convection, wBF, Intrepid2::COMP_CPP, true); // "true" sums into

  if (haveSUPG) {
    for (std::size_t cell=0; cell < workset.numCells; ++cell) {
      for (std::size_t node=0; node < numNodes; ++node) {          
	for (std::size_t qp=0; qp < numQPs; ++qp) {               
	  for (std::size_t j=0; j < numDims; ++j) { 
	    TResidual(cell,node) += 
	      rho(cell,qp) * Cp(cell,qp) * TauT(cell,qp) * convection(cell,qp) *
	      V(cell,qp,j) * wGradBF(cell,node,qp,j);
	  }  
	}
      }
    }
  }

}
Example #3
0
bool FEMPhysics::eulerian_residual (bool request_jacobian,
                                    DiffContext &/*c*/)
{
  // Only calculate a mesh movement residual if it's necessary
  if (!_mesh_sys)
    return request_jacobian;

  libmesh_not_implemented();

#if 0
  FEMContext &context = libmesh_cast_ref<FEMContext&>(c);

  // This function only supports fully coupled mesh motion for now
  libmesh_assert_equal_to (_mesh_sys, this);

  unsigned int n_qpoints = (context.get_element_qrule())->n_points();

  const unsigned int n_x_dofs = (_mesh_x_var == libMesh::invalid_uint) ?
                                0 : context.dof_indices_var[_mesh_x_var].size();
  const unsigned int n_y_dofs = (_mesh_y_var == libMesh::invalid_uint) ?
                                0 : context.dof_indices_var[_mesh_y_var].size();
  const unsigned int n_z_dofs = (_mesh_z_var == libMesh::invalid_uint) ?
                                0 : context.dof_indices_var[_mesh_z_var].size();

  const unsigned int mesh_xyz_var = n_x_dofs ? _mesh_x_var :
                                   (n_y_dofs ? _mesh_y_var :
                                   (n_z_dofs ? _mesh_z_var :
                                    libMesh::invalid_uint));

  // If we're our own _mesh_sys, we'd better be in charge of
  // at least one coordinate, and we'd better have the same
  // FE type for all coordinates we are in charge of
  libmesh_assert_not_equal_to (mesh_xyz_var, libMesh::invalid_uint);
  libmesh_assert(!n_x_dofs || context.element_fe_var[_mesh_x_var] ==
                              context.element_fe_var[mesh_xyz_var]);
  libmesh_assert(!n_y_dofs || context.element_fe_var[_mesh_y_var] ==
                              context.element_fe_var[mesh_xyz_var]);
  libmesh_assert(!n_z_dofs || context.element_fe_var[_mesh_z_var] ==
                              context.element_fe_var[mesh_xyz_var]);

  const std::vector<std::vector<Real> >     &psi =
    context.element_fe_var[mesh_xyz_var]->get_phi();

  for (unsigned int var = 0; var != context.n_vars(); ++var)
    {
      // Mesh motion only affects time-evolving variables
      if (this->is_time_evolving(var))
        continue;

      // The mesh coordinate variables themselves are Lagrangian,
      // not Eulerian, and no convective term is desired.
      if (/*_mesh_sys == this && */
          (var == _mesh_x_var ||
           var == _mesh_y_var ||
           var == _mesh_z_var))
        continue;

      // Some of this code currently relies on the assumption that
      // we can pull mesh coordinate data from our own system
      if (_mesh_sys != this)
        libmesh_not_implemented();

      // This residual should only be called by unsteady solvers:
      // if the mesh is steady, there's no mesh convection term!
      UnsteadySolver *unsteady;
      if (this->time_solver->is_steady())
        return request_jacobian;
      else
	unsteady = libmesh_cast_ptr<UnsteadySolver*>(this->time_solver.get());

      const std::vector<Real> &JxW =
        context.element_fe_var[var]->get_JxW();

      const std::vector<std::vector<Real> >     &phi =
        context.element_fe_var[var]->get_phi();

      const std::vector<std::vector<RealGradient> > &dphi =
        context.element_fe_var[var]->get_dphi();

      const unsigned int n_u_dofs = context.dof_indices_var[var].size();

      DenseSubVector<Number> &Fu = *context.elem_subresiduals[var];
      DenseSubMatrix<Number> &Kuu = *context.elem_subjacobians[var][var];

      DenseSubMatrix<Number> *Kux = n_x_dofs ?
        context.elem_subjacobians[var][_mesh_x_var] : NULL;
      DenseSubMatrix<Number> *Kuy = n_y_dofs ?
        context.elem_subjacobians[var][_mesh_y_var] : NULL;
      DenseSubMatrix<Number> *Kuz = n_z_dofs ?
        context.elem_subjacobians[var][_mesh_z_var] : NULL;

      std::vector<Real> delta_x(n_x_dofs, 0.);
      std::vector<Real> delta_y(n_y_dofs, 0.);
      std::vector<Real> delta_z(n_z_dofs, 0.);

      for (unsigned int i = 0; i != n_x_dofs; ++i)
        {
          unsigned int j = context.dof_indices_var[_mesh_x_var][i];
          delta_x[i] = libmesh_real(this->current_solution(j)) -
                       libmesh_real(unsteady->old_nonlinear_solution(j));
        }

      for (unsigned int i = 0; i != n_y_dofs; ++i)
        {
          unsigned int j = context.dof_indices_var[_mesh_y_var][i];
          delta_y[i] = libmesh_real(this->current_solution(j)) -
                       libmesh_real(unsteady->old_nonlinear_solution(j));
        }

      for (unsigned int i = 0; i != n_z_dofs; ++i)
        {
          unsigned int j = context.dof_indices_var[_mesh_z_var][i];
          delta_z[i] = libmesh_real(this->current_solution(j)) -
                       libmesh_real(unsteady->old_nonlinear_solution(j));
        }

      for (unsigned int qp = 0; qp != n_qpoints; ++qp)
        {
          Gradient grad_u = context.interior_gradient(var, qp);
          RealGradient convection(0.);

          for (unsigned int i = 0; i != n_x_dofs; ++i)
	    convection(0) += delta_x[i] * psi[i][qp];
          for (unsigned int i = 0; i != n_y_dofs; ++i)
	    convection(1) += delta_y[i] * psi[i][qp];
          for (unsigned int i = 0; i != n_z_dofs; ++i)
	    convection(2) += delta_z[i] * psi[i][qp];

          for (unsigned int i = 0; i != n_u_dofs; ++i)
            {
              Number JxWxPhiI = JxW[qp] * phi[i][qp];
              Fu(i) += (convection * grad_u) * JxWxPhiI;
              if (request_jacobian)
                {
                  Number JxWxPhiI = JxW[qp] * phi[i][qp];
                  for (unsigned int j = 0; j != n_u_dofs; ++j)
                    Kuu(i,j) += JxWxPhiI * (convection * dphi[j][qp]);

                  Number JxWxPhiIoverDT = JxWxPhiI/this->deltat;

                  Number JxWxPhiIxDUDXoverDT = JxWxPhiIoverDT * grad_u(0);
                  for (unsigned int j = 0; j != n_x_dofs; ++j)
                    (*Kux)(i,j) += JxWxPhiIxDUDXoverDT * psi[j][qp];

                  Number JxWxPhiIxDUDYoverDT = JxWxPhiIoverDT * grad_u(1);
                  for (unsigned int j = 0; j != n_y_dofs; ++j)
                    (*Kuy)(i,j) += JxWxPhiIxDUDYoverDT * psi[j][qp];

                  Number JxWxPhiIxDUDZoverDT = JxWxPhiIoverDT * grad_u(2);
                  for (unsigned int j = 0; j != n_z_dofs; ++j)
                    (*Kuz)(i,j) += JxWxPhiIxDUDZoverDT * psi[j][qp];
                }
            }
        }
    }
#endif // 0

  return request_jacobian;
}
Example #4
0
//------------------------------------------------------------------------------
int main( int argc, char * argv[] )
{
    //--------------------------------------------------------------------------
    const unsigned    geomDeg   = 1;
    const unsigned    dim       = 2;
    // degrees of lowest-order TH element
    const unsigned    fieldDegU = 2; 
    const unsigned    fieldDegP = 1;

    const unsigned    tiOrder   = 1;
    typedef  base::time::BDF<tiOrder> MSM;
    
    const base::Shape shape     = base::SimplexShape<dim>::value;
    const base::Shape surfShape = base::SimplexShape<dim-1>::value;

    //--------------------------------------------------------------------------
    if ( argc != 2 ) {
        std::cout << "Usage:  " << argv[0] << " input.dat \n\n";
        return -1;
    }

    const std::string inputFile = boost::lexical_cast<std::string>( argv[1] );

    //--------------------------------------------------------------------------
    std::string meshFile, surfFile;
    double viscosity, density, tolerance, penaltyFactor, stepSize;
    unsigned maxIter, numSteps;
    {    
        //Feed properties parser with the variables to be read
        base::io::PropertiesParser prop;
        prop.registerPropertiesVar( "meshFile",         meshFile );
        prop.registerPropertiesVar( "surfFile",         surfFile );
        prop.registerPropertiesVar( "viscosity",        viscosity );
        prop.registerPropertiesVar( "density",          density );
        prop.registerPropertiesVar( "maxIter",          maxIter );
        prop.registerPropertiesVar( "tolerance",        tolerance );
        prop.registerPropertiesVar( "penaltyFactor",    penaltyFactor );
        prop.registerPropertiesVar( "stepSize",         stepSize );
        prop.registerPropertiesVar( "numSteps",         numSteps );

        // Read variables from the input file
        std::ifstream inp( inputFile.c_str()  );
        VERIFY_MSG( inp.is_open(), "Cannot open input file" );
        prop.readValues( inp );
        inp.close( );

        // Make sure all variables have been found
        if ( not prop.isEverythingRead() ) {
            prop.writeUnread( std::cerr );
            VERIFY_MSG( false, "Could not find above variables" );
        }
    }

    const std::string baseName = base::io::baseName( meshFile, ".smf" );

    //--------------------------------------------------------------------------
    typedef base::Unstructured<shape,geomDeg>     Mesh;

    Mesh mesh;
    {
        std::ifstream smf( meshFile.c_str() );
        VERIFY_MSG( smf.is_open(), "Cannot open mesh file" );
        base::io::smf::readMesh( smf, mesh );
        smf.close();
    }

    //--------------------------------------------------------------------------
    // Surface mesh
    typedef base::Unstructured<surfShape,1,dim>    SurfMesh;

    SurfMesh surfMesh;
    {
        std::ifstream smf( surfFile.c_str() );
        base::io::smf::readMesh( smf, surfMesh );
        smf.close();
    }

    //--------------------------------------------------------------------------
    // Compute the level set data
    typedef base::cut::LevelSet<dim> LevelSet;
    std::vector<LevelSet> levelSet;
    const bool isSigned = true;
    base::cut::bruteForce( mesh, surfMesh, isSigned, levelSet );

    const unsigned kernelDegEstimate = 5;

    //--------------------------------------------------------------------------
    // Make cut cell structure
    typedef base::cut::Cell<shape> Cell;
    std::vector<Cell> cells;
    base::cut::generateCutCells( mesh, levelSet, cells );

    // Quadrature 
    typedef base::cut::Quadrature<kernelDegEstimate,shape> CutQuadrature;
    CutQuadrature quadrature( cells, true );

    // for surface
    typedef base::SurfaceQuadrature<kernelDegEstimate,shape> SurfaceQuadrature;
    SurfaceQuadrature surfaceQuadrature;

    //------------------------------------------------------------------------------
    // Finite element bases
    const unsigned    nHist = MSM::numSteps;
    
    const unsigned    doFSizeU = dim;
    typedef base::fe::Basis<shape,fieldDegU>                FEBasisU;
    typedef base::cut::ScaledField<FEBasisU,doFSizeU,nHist> Velocity;
    Velocity velocity;
    base::dof::generate<FEBasisU>( mesh, velocity );
    
    const unsigned    doFSizeP = 1;
    typedef base::fe::Basis<shape,fieldDegP>                FEBasisP;
    typedef base::cut::ScaledField<FEBasisP,doFSizeP,nHist> Pressure;
    Pressure pressure;
    base::dof::generate<FEBasisP>( mesh, pressure );

    const unsigned    doFSizeS = dim;
    typedef base::fe::Basis<surfShape,1>              FEBasisS;
    typedef base::Field<FEBasisS,doFSizeS>            SurfField;
    SurfField surfVelocity, surfForces;
    base::dof::generate<FEBasisS>( surfMesh, surfVelocity );
    base::dof::generate<FEBasisS>( surfMesh, surfForces   );

    // set initial condition to the identity 
    base::dof::setField( surfMesh, surfVelocity,
                         boost::bind( &surfaceVelocity<dim,
                                      SurfField::DegreeOfFreedom>, _1, _2 ) );


    // boundary datum    
    base::cut::TransferSurfaceDatum<SurfMesh,SurfField,Mesh::Element>
        s2d( surfMesh, surfVelocity, levelSet );
    
    //--------------------------------------------------------------------------
    //  surface mesh
    typedef base::mesh::BoundaryMeshBinder<Mesh>::Type BoundaryMesh;
    BoundaryMesh boundaryMesh, immersedMesh;

    // from boundary
    {
        // identify list of element boundary faces
        base::mesh::MeshBoundary meshBoundary;
        meshBoundary.create( mesh.elementsBegin(), mesh.elementsEnd() );

        // generate a mesh from that list (with a filter)
        base::mesh::generateBoundaryMesh( meshBoundary.begin(),
                                          meshBoundary.end(),
                                          mesh, boundaryMesh,
                                          boost::bind( &boundaryFilter<dim>, _1 ) );

        // make a surface mesh from the implicit surface
        base::cut::generateSurfaceMesh<Mesh,Cell>( mesh, cells, immersedMesh );
    }

    // the composite field with geometry, velocity and pressure
    typedef base::asmb::FieldBinder<Mesh,Velocity,Pressure> Field;
    Field field( mesh, velocity, pressure );

    // define the system blocks (U,U), (U,P), and (P,U)
    typedef Field::TupleBinder<1,1,1>::Type TopLeft;
    typedef Field::TupleBinder<1,2>::Type   TopRight;
    typedef Field::TupleBinder<2,1>::Type   BotLeft;


    std::vector<double> supportsU, supportsP;
    std::size_t numDoFsU = std::distance( velocity.doFsBegin(), velocity.doFsEnd() );
    supportsU.resize( numDoFsU );
    std::size_t numDoFsP = std::distance( pressure.doFsBegin(), pressure.doFsEnd() );
    supportsP.resize( numDoFsP );

    base::cut::supportComputation( mesh, velocity, quadrature, supportsU );
    base::cut::supportComputation( mesh, pressure, quadrature, supportsP );

    velocity.scaleAndTagBasis( supportsU, 1.e-8 );
    pressure.scaleAndTagBasis( supportsP, 1.e-8 ); 
    //velocity.tagBasis( supportsU, 1.e-8 );
    //pressure.tagBasis( supportsP, 1.e-8 ); 

    // Fix one pressure dof
    // Pressure::DoFPtrIter pIter = pressure.doFsBegin();
    // std::advance( pIter, std::distance( pressure.doFsBegin(), pressure.doFsEnd() )/5 );
    // (*pIter) -> constrainValue( 0, 0.0 );

    // Number of DoFs after constraint application!
    numDoFsU =
        base::dof::numberDoFsConsecutively( velocity.doFsBegin(), velocity.doFsEnd() );
    std::cout << "# Number of velocity dofs " << numDoFsU << std::endl;

    numDoFsP =
        base::dof::numberDoFsConsecutively( pressure.doFsBegin(), pressure.doFsEnd(),
            numDoFsU );
    std::cout << "# Number of pressure dofs " << numDoFsP << std::endl;

    // kernels
    typedef fluid::StressDivergence<  TopLeft::Tuple>  StressDivergence;
    typedef fluid::Convection<        TopLeft::Tuple>  Convection;
    typedef fluid::PressureGradient<  TopRight::Tuple> GradP;
    typedef fluid::VelocityDivergence<BotLeft::Tuple>  DivU;

    StressDivergence stressDivergence( viscosity );
    Convection       convection(       density );
    GradP            gradP;
    DivU             divU( true );

    // for surface fields
    typedef base::asmb::SurfaceFieldBinder<BoundaryMesh,Velocity,Pressure> SurfaceFieldBinder;
    typedef SurfaceFieldBinder::TupleBinder<1,1,1>::Type STBUU;
    typedef SurfaceFieldBinder::TupleBinder<1,2  >::Type STBUP;
    SurfaceFieldBinder   boundaryFieldBinder(  boundaryMesh, velocity, pressure );
    SurfaceFieldBinder   immersedFieldBinder(  immersedMesh, velocity, pressure );

    std::ofstream forces( "forces.dat" );

    for ( unsigned step = 0; step < numSteps; step++ ) {

        const double time = step * stepSize;
        const double factor = ( time < 1.0 ? time : 1.0 );
    
        std::cout << step << ":  time=" << time << ", factor=" << factor
                  << "\n";

        //base::dof::clearDoFs( velocity );
        //base::dof::clearDoFs( pressure );
        
        //--------------------------------------------------------------------------
        // Nonlinear iterations
        unsigned iter = 0;
        while( iter < maxIter ) {

            // Create a solver object
            typedef base::solver::Eigen3           Solver;
            Solver solver( numDoFsU + numDoFsP );

            std::cout << "* Iteration " << iter << std::flush;

            // compute inertia terms, d/dt, due to time integration
            base::time::computeInertiaTerms<TopLeft,MSM>( quadrature, solver,
                                                          field, stepSize, step,
                                                          density );
    
            // Compute system matrix
            base::asmb::stiffnessMatrixComputation<TopLeft>( quadrature, solver,
                                                             field, stressDivergence );

            base::asmb::stiffnessMatrixComputation<TopLeft>( quadrature, solver,
                                                             field, convection );

            base::asmb::stiffnessMatrixComputation<TopRight>( quadrature, solver,
                                                              field, gradP );

            base::asmb::stiffnessMatrixComputation<BotLeft>( quadrature, solver,
                                                             field, divU );
            // compute residual forces
            base::asmb::computeResidualForces<TopLeft >( quadrature, solver, field,
                                                         stressDivergence );
            base::asmb::computeResidualForces<TopLeft >( quadrature, solver, field, convection );
            base::asmb::computeResidualForces<TopRight>( quadrature, solver, field, gradP );
            base::asmb::computeResidualForces<BotLeft >( quadrature, solver, field, divU );
        
            // Parameter classes
            base::nitsche::OuterBoundary ob( viscosity );
            base::nitsche::ImmersedBoundary<Cell> ib( viscosity, cells );

            // Penalty method
            base::nitsche::penaltyLHS<STBUU>( surfaceQuadrature, solver,
                                              boundaryFieldBinder, ob, penaltyFactor );
        
            base::nitsche::penaltyRHS<STBUU>( surfaceQuadrature, solver, boundaryFieldBinder, 
                                              boost::bind( &dirichlet<dim>, _1, factor),
                                              ob, penaltyFactor );

            base::nitsche::penaltyLHS<STBUU>( surfaceQuadrature, solver,
                                              immersedFieldBinder, ib, penaltyFactor );
        
            base::nitsche::penaltyRHS2<STBUU>( surfaceQuadrature, solver, immersedFieldBinder,
                                               s2d, ib, penaltyFactor );

            // Nitsche terms
            base::nitsche::primalEnergyLHS<STBUU>( stressDivergence, surfaceQuadrature, solver,
                                                   boundaryFieldBinder, ob );
            base::nitsche::dualEnergyLHS<STBUU>( stressDivergence, surfaceQuadrature, solver,
                                                 boundaryFieldBinder, ob );
            base::nitsche::energyRHS<STBUU>( stressDivergence, surfaceQuadrature, solver,
                                             boundaryFieldBinder,
                                             boost::bind( &dirichlet<dim>, _1, factor),
                                             ob );
        
            base::nitsche::primalEnergyLHS<STBUP>( gradP, surfaceQuadrature, solver,
                                                   boundaryFieldBinder, ob );
            base::nitsche::dualEnergyLHS<STBUP>( gradP, surfaceQuadrature, solver,
                                                 boundaryFieldBinder, ob );
         
            base::nitsche::energyRHS<STBUP>( gradP, surfaceQuadrature, solver,
                                             boundaryFieldBinder,
                                             boost::bind( &dirichlet<dim>, _1, factor), ob );

            base::nitsche::energyResidual<STBUU>( stressDivergence, surfaceQuadrature, solver,
                                                  boundaryFieldBinder, ob );
            
            base::nitsche::energyResidual<STBUP>( gradP, surfaceQuadrature, solver,
                                                  boundaryFieldBinder, ob );

            base::nitsche::primalEnergyLHS<STBUU>( stressDivergence, surfaceQuadrature, solver,
                                                   immersedFieldBinder, ib );
            base::nitsche::dualEnergyLHS<STBUU>( stressDivergence, surfaceQuadrature, solver,
                                                 immersedFieldBinder, ib );

            base::nitsche::energyRHS2<STBUU>( stressDivergence, surfaceQuadrature, solver,
                                              immersedFieldBinder, s2d, ib );
            
            base::nitsche::primalEnergyLHS<STBUP>( gradP, surfaceQuadrature, solver,
                                                   immersedFieldBinder, ib );
            base::nitsche::dualEnergyLHS<STBUP>( gradP, surfaceQuadrature, solver,
                                                 immersedFieldBinder, ib );

            base::nitsche::energyRHS2<STBUP>( gradP, surfaceQuadrature, solver,
                                              immersedFieldBinder, s2d, ib );

            base::nitsche::energyResidual<STBUU>( stressDivergence, surfaceQuadrature, solver,
                                                  immersedFieldBinder, ib );

            base::nitsche::energyResidual<STBUP>( gradP, surfaceQuadrature, solver,
                                                  immersedFieldBinder, ib );
        
            // Finalise assembly
            solver.finishAssembly();

            // check convergence via solver norms
            const double residualNorm = solver.norm();
            std::cout << " |R| = " << residualNorm << std::flush;

            if ( residualNorm < tolerance * viscosity) {
                std::cout << std::endl;
                break;
            }

            // Solve
            solver.superLUSolve();

            // distribute results back to dofs
            base::dof::addToDoFsFromSolver( solver, velocity );
            base::dof::addToDoFsFromSolver( solver, pressure );
            //base::dof::setDoFsFromSolver( solver, pressure );
        
            // check convergence via solver norms
            const double incrementNorm = solver.norm(0, numDoFsU );
            std::cout << " |dU| = " << incrementNorm << std::endl;

            // push history
            base::dof::pushHistory( velocity );
            base::dof::pushHistory( pressure );
        
            if ( incrementNorm < tolerance ) break;

            iter++;

        }

        writeVTKFile( baseName, step, mesh, velocity, pressure, levelSet, viscosity );
        {
            base::Vector<dim>::Type sumOfForces = base::constantVector<dim>( 0. );
            
            typedef Field::TupleBinder<1,2>::Type UP;
            //typedef fluid::Stress<UP::Tuple> Stress;
            //Stress stress( viscosity );
            typedef fluid::Traction<UP::Tuple> Traction;
            Traction traction( viscosity );
                
            base::cut::ComputeSurfaceForces<SurfMesh,SurfField,
                                            SurfaceQuadrature,STBUP::Tuple,Traction>
                computeSurfaceForces( surfMesh, surfForces, surfaceQuadrature, levelSet, traction );

            SurfaceFieldBinder::FieldIterator first = immersedFieldBinder.elementsBegin();
            SurfaceFieldBinder::FieldIterator  last = immersedFieldBinder.elementsEnd();
            for ( ; first != last; ++first ) {
                
                sumOfForces +=
                    computeSurfaceForces( STBUP::makeTuple( *first ) );
                
            }

            writeSurfaceVTKFile( baseName, step, surfMesh, surfVelocity, surfForces );


            std::cout << "  F= " << sumOfForces.transpose() << " \n";

            forces << time << " " << sumOfForces.transpose() << std::endl;;
        }

    }

    forces.close();

    return 0;
}
Example #5
0
int main(int argc, char **argv)
{
    MPI_Init(&argc, &argv);
    int commsize, commrank;
    MPI_Comm_size(MPI_COMM_WORLD, &commsize);
    MPI_Comm_rank(MPI_COMM_WORLD, &commrank);
    const bool isRoot = commrank == 0;
    const bool isLast = commrank == commsize - 1;

    if (isRoot)
        std::cout << "Initialization...\n" << std::endl;

    RuntimeConfiguration conf(argc, argv);

    // Compute my start and end time
    const double timeStart = conf.timeSliceSize() * commrank;
    const double timeEnd = conf.timeSliceSize() * (commrank + 1);

    if (isRoot)
    std::cout << "Running with:\n"
        << " - initial diffusion coefficient: " << conf.nu0() << "\n"
        << " - frequence of diffusion coefficient: " << conf.nufreq() << "\n"
        << " - advection velocity in x: " << conf.cx() << "\n"
        << " - advection velocity in y: " << conf.cy() << "\n"
        << " - advection velocity in z: " << conf.cz() << "\n"
        << " - spatial discretization step: " << conf.dx() << "\n"
        << " - endtime: " << conf.endTime() << "\n"
        << " - number of time slices: " << conf.timeSlices() << "\n"
        << " - time slice size: " << conf.timeSliceSize() << "\n"
        << " - CFL fine: " << conf.cflFine() << "\n"
        << " - CFL coarse: " << conf.cflCoarse() << "\n"
        << " - timestep size fine: " << conf.dtFine() << "\n"
        << " - timestep size coarse: " << conf.dtCoarse() << "\n"
        << " - timesteps per slice fine propagator: " << conf.timeStepsFinePerTimeSlice() << "\n"
        << " - timesteps per slice coarse propagator: " << conf.timeStepsCoarsePerTimeSlice() << "\n"
        << " - parareal iterations: " << conf.kmax() << "\n"
        << " - asynchronous communications: " << (conf.async() ? "Enabled" : "Disabled") << "\n"
        << " - intermediate fields in mat files: " << (conf.mat() ? "Yes" : "No") << "\n"
        << std::endl;

    // Calculation domain and boundaries
    IJKSize domain; domain.Init(conf.gridSize(), conf.gridSize(), conf.gridSize());
    KBoundary kboundary; kboundary.Init(-convectionBoundaryLines, convectionBoundaryLines);

    // Initialize fields
    ConvectionField q, qinitial;
    q.Init("q", domain, kboundary);
    qinitial.Init("qinitial", domain, kboundary);
    Convection convection(conf.gridSize(), conf.gridSize(), conf.gridSize(), conf.dx(), conf.nu0(), conf.nufreq(), conf.cx(), conf.cy(), conf.cz());

    // Initialize parareal
    Parareal<Convection, ConvectionField> parareal(convection, qinitial, q, timeStart, conf, MPI_COMM_WORLD);

    if (conf.mode() == ModeCompare)
    {
        // Measure time required by convection
        const int tauSamples = 4;
        double tauF = MPI_Wtime();
        convection.DoRK4(qinitial, qinitial, 0., conf.dtFine(), tauSamples*conf.timeStepsFinePerTimeSlice());
        SynchronizeCUDA();
        tauF = MPI_Wtime() - tauF;
        double tauG = MPI_Wtime();
        convection.DoEuler(qinitial, qinitial, 0., conf.dtCoarse(), tauSamples*conf.timeStepsCoarsePerTimeSlice());
        SynchronizeCUDA();
        tauG = MPI_Wtime() - tauG;

        const double tauRatio = tauG / tauF;
        const double Nit_Np = static_cast<double>(conf.kmax()) / commsize;
        const double maxSpeedup = 1. / (tauRatio * (1. + Nit_Np) + Nit_Np);

        // Fill initial solution
        SynchronizeHost(qinitial);
        fillQ(qinitial, conf.nu0(), conf.nufreq(), conf.cx(), conf.cy(), conf.cz(), 0., 0., 1., 0., 1., 0., 1.);
        SynchronizeDevice(qinitial);

        // Run serial
        MPI_Barrier(MPI_COMM_WORLD);
        double eserial = MPI_Wtime();
        parareal.DoSerial();
        eserial = MPI_Wtime() - eserial;

        // Save reference
        ConvectionField qreference = q;
        SynchronizeHost(qreference);

        // Fill initial solution
        SynchronizeHost(qinitial);
        fillQ(qinitial, conf.nu0(), conf.nufreq(), conf.cx(), conf.cy(), conf.cz(), 0., 0., 1., 0., 1., 0., 1.);
        SynchronizeDevice(qinitial);

        // Run serial
        MPI_Barrier(MPI_COMM_WORLD);
        double eparallel = MPI_Wtime();
        parareal.DoParallel();
        eparallel = MPI_Wtime() - eparallel;

        // Output
        MPI_Barrier(MPI_COMM_WORLD);
        if (isLast)
        {
            double e = computeErrorReference(q, qreference);
            std::cout << "\n"
                << "Serial run time: " << eserial << "\n"
                << "Parallel run time: " << eparallel << "\n"
                << "Speedup: " << eserial / eparallel << "\n"
                << "Maximal speedup: " << maxSpeedup << "\n"
                << "Error at end: " << e << "\n"
                << std::endl;

            MatFile matfile("result.mat");
            matfile.addField("q", q);
            matfile.addField("qreference", qreference);
        }
    }
    else if (conf.mode() == ModeSerial)
    {
        // Fill initial solution
        SynchronizeHost(qinitial);
        fillQ(qinitial, conf.nu0(), conf.nufreq(), conf.cx(), conf.cy(), conf.cz(), 0., 0., 1., 0., 1., 0., 1.);
        SynchronizeDevice(qinitial);

        // Run serial
        double e = MPI_Wtime();
        double energyStart = energy();
        double deviceEnergyStart = deviceEnergy();

        parareal.DoSerial();

        e = MPI_Wtime() - e;
        double energyEnd = energy();
        double deviceEnergyEnd = deviceEnergy();

        const double totDevice = totalEnergy(deviceEnergyStart, deviceEnergyEnd);
        const double totNode = totalEnergy(energyStart, energyEnd) - totDevice;
        const double totNetwork = e * powerNetwork;
        const double totBlower = e * powerBlower;
        const double totEnergy = totNode + totDevice + totNetwork + totBlower;

        // Output
        MPI_Barrier(MPI_COMM_WORLD);
        if (isLast)
        {
            std::cout << "\n" << "Serial run time: " << e << "\n";
            std::printf("Node energy   : %8f J  (%8.3e W/node)\n", totNode   , totNode/e);
            std::printf("Device energy : %8f J  (%8.3e W/node)\n", totDevice , totDevice/e);
            std::printf("Network energy: %8f J  (%8.3e W/node)\n", totNetwork, totNetwork/e);
            std::printf("Blower energy : %8f J  (%8.3e W/node)\n", totBlower , totBlower/e);
            std::printf("Total energy  : %8f J  (%8.3e W/node)\n", totEnergy , totEnergy/e);
            std::cout << std::endl;
        }
    }
    else if (conf.mode() == ModeParallel)
    {
        // Fill initial solution
        SynchronizeHost(qinitial);
        fillQ(qinitial, conf.nu0(), conf.nufreq(), conf.cx(), conf.cy(), conf.cz(), 0., 0., 1., 0., 1., 0., 1.);
        SynchronizeDevice(qinitial);

        // Run serial
        parareal.DoSerial();
        std::cout << " -- The serial computation is done\n";
        ConvectionField qreference = q;

        // Run parallel
        MPI_Barrier(MPI_COMM_WORLD);
        double e = MPI_Wtime();
        double energyStart = energy();
        double deviceEnergyStart = deviceEnergy();

        parareal.DoParallel();

        MPI_Barrier(MPI_COMM_WORLD);
        e = MPI_Wtime() - e;

        std::cout << " -- The parallel computation is done\n";
        double energyEnd = energy();
        double deviceEnergyEnd = deviceEnergy();

        const double totDevice = totalEnergy(deviceEnergyStart, deviceEnergyEnd, MPI_COMM_WORLD);
        const double totNode = totalEnergy(energyStart, energyEnd, MPI_COMM_WORLD) - totDevice;
        const double totNetwork = e * powerNetwork * commsize;
        const double totBlower = e * powerBlower * commsize;
        const double totEnergy = totNode + totDevice + totNetwork + totBlower;

        // Compute error
        double error = computeErrorReference(q, qreference);

        // Output
        MPI_Barrier(MPI_COMM_WORLD);
        if (isLast)
        {
            const double fac = 1./e/commsize;

            std::cout << std::endl;
            std::printf("Parallel run time: %f s\n", e);
            std::printf("Node energy   : %8f J  (%8.3e W/node)\n", totNode   , fac*totNode);
            std::printf("Device energy : %8f J  (%8.3e W/node)\n", totDevice , fac*totDevice);
            std::printf("Network energy: %8f J  (%8.3e W/node)\n", totNetwork, fac*totNetwork);
            std::printf("Blower energy : %8f J  (%8.3e W/node)\n", totBlower , fac*totBlower);
            std::printf("Total energy  : %8f J  (%8.3e W/node)\n", totEnergy , fac*totEnergy);
            std::printf("Error of parareal: %.4e\n", error);
            std::cout << std::endl;
        }
    }
    else if (conf.mode() == ModeTiming)
    {
        // Fill initial solution
        SynchronizeHost(qinitial);
        fillQ(qinitial, conf.nu0(), conf.nufreq(), conf.cx(), conf.cy(), conf.cz(), 0., 0., 1., 0., 1., 0., 1.);
        SynchronizeDevice(qinitial);

        // Run serial
        std::vector<double> times;
        MPI_Barrier(MPI_COMM_WORLD);
        parareal.DoTimedParallel(times);

        // Gather on root
        const int s = times.size();
        std::vector<double> timesGlobal;
        timesGlobal.resize(s * commsize);
        MPI_Gather(&times[0], s, MPI_DOUBLE, &timesGlobal[0], s, MPI_DOUBLE, 0, MPI_COMM_WORLD);

        // Output
        if (isRoot)
        {
            std::cout << "\nTimes:\n";
            for(int i = 0; i < s; ++i)
            {
                for(int p = 0; p < commsize; ++p)
                {
                    std::cout << std::scientific << std::setprecision(6) << timesGlobal[p*s + i] << "   ";
                }
                std::cout << "\n";
            }
        }
    }

    // Finalize
    MPI_Finalize();

    return 0;
}
Example #6
0
void HeatEqResid<EvalT, Traits>::
evaluateFields(typename Traits::EvalData workset)
{

//// workset.print(std::cout);


  typedef Intrepid::FunctionSpaceTools FST;

  // Since Intrepid will later perform calculations on the entire workset size
  // and not just the used portion, we must fill the excess with reasonable
  // values. Leaving this out leads to floating point exceptions !!!
  for (std::size_t cell=workset.numCells; cell < worksetSize; ++cell)
    for (std::size_t qp=0; qp < numQPs; ++qp){
      ThermalCond(cell,qp) = 0.0;
      for (std::size_t i=0; i < numDims; ++i){
        flux(cell,qp,i) = 0.0;
        TGrad(cell,qp,i) = 0.0;
      }
    }

  FST::scalarMultiplyDataData<ScalarT> (flux, ThermalCond, TGrad);

  FST::integrate<ScalarT>(TResidual, flux, wGradBF, Intrepid::COMP_CPP, false); // "false" overwrites

  if (haveSource) {

    for (std::size_t cell=workset.numCells; cell < worksetSize; ++cell)
      for (std::size_t qp=0; qp < numQPs; ++qp)
        Source(cell,qp) = 0.0;

    for (int i =0; i< Source.dimension(0); i++)
     for (int j =0; j< Source.dimension(1); j++)
        Source(i,j) *= -1.0;
    FST::integrate<ScalarT>(TResidual, Source, wBF, Intrepid::COMP_CPP, true); // "true" sums into
  }

  if (workset.transientTerms && enableTransient){

    for (std::size_t cell=workset.numCells; cell < worksetSize; ++cell)
      for (std::size_t qp=0; qp < numQPs; ++qp)
        Tdot(cell,qp) = 0.0;

    FST::integrate<ScalarT>(TResidual, Tdot, wBF, Intrepid::COMP_CPP, true); // "true" sums into

  }

  if (haveConvection)  {
    Intrepid::FieldContainer<ScalarT> convection(worksetSize, numQPs);

    for (std::size_t cell=workset.numCells; cell < worksetSize; ++cell)
      for (std::size_t qp=0; qp < numQPs; ++qp)
        convection(cell,qp) = 0.0;

    for (std::size_t cell=0; cell < workset.numCells; ++cell) {
      for (std::size_t qp=0; qp < numQPs; ++qp) {
        convection(cell,qp) = 0.0;
        for (std::size_t i=0; i < numDims; ++i) {
          if (haverhoCp)
            convection(cell,qp) += rhoCp(cell,qp) * convectionVels[i] * TGrad(cell,qp,i);
          else
            convection(cell,qp) += convectionVels[i] * TGrad(cell,qp,i);
        }
      }
    }

    FST::integrate<ScalarT>(TResidual, convection, wBF, Intrepid::COMP_CPP, true); // "true" sums into
  }


  if (haveAbsorption) {

    // Since Intrepid will later perform calculations on the entire workset size
    // and not just the used portion, we must fill the excess with reasonable
    // values. Leaving this out leads to floating point exceptions !!!
    for (std::size_t cell=workset.numCells; cell < worksetSize; ++cell)
      for (std::size_t qp=0; qp < numQPs; ++qp){
        aterm(cell,qp) = 0.0;
        Absorption(cell,qp) = 0.0;
        Temperature(cell,qp) = 0.0;
      }

    FST::scalarMultiplyDataData<ScalarT> (aterm, Absorption, Temperature);
    FST::integrate<ScalarT>(TResidual, aterm, wBF, Intrepid::COMP_CPP, true); 
  }

//TResidual.print(std::cout, true);

}