MMappedReader(const std::string &filename, bool unlink = false,
                size_t blocksize = 64*1024*1024, size_t off = 0, size_t sz = 0)
      : Unlink(unlink), FileName(filename), BlockSize(blocksize) {
    struct stat buf;

    FileSize = (sz ? sz : (stat(FileName.c_str(), &buf) != 0 ? 0 : buf.st_size));

    StreamFile = open(FileName.c_str(), O_RDONLY);
    VERIFY_MSG(StreamFile != -1,
               "open(2) failed. Reason: " << strerror(errno) << ". Error code: " << errno);

    if (BlockSize != -1ULL) {
      size_t PageSize = getpagesize();
      BlockSize = BlockSize / PageSize * PageSize;
    } else
      BlockSize = FileSize;

    if (BlockSize) {
      MappedRegion =
          (uint8_t*)mmap(NULL, BlockSize, PROT_READ | PROT_WRITE, MAP_FILE | MAP_PRIVATE,
                         StreamFile, off);
      VERIFY_MSG((intptr_t)MappedRegion != -1L,
                 "mmap(2) failed. Reason: " << strerror(errno) << ". Error code: " << errno);
    } else
      MappedRegion = NULL;

    BlockOffset = BytesRead = 0;
  }
void base::mesh::createBoundaryFromStructuredFace(
    const typename base::MultiIndex<DIM>::Type& gridSizes,
    const unsigned direction,
    const unsigned side,
    std::vector< std::pair<std::size_t,unsigned> >&
    boundaryElementContainer )
{
    VERIFY_MSG( (direction < DIM),    "Direction is nonsense ");
    VERIFY_MSG( (side==0) or (side==1), "Side ID is nonsense" );

    // fixed number
    const int fixed = ( side == 0 ? 0 : gridSizes[ direction ] - 1 );

    // number of element faces
    typedef typename base::MultiIndex<DIM-1> FaceMI;
    typedef typename FaceMI::Type            FaceMIT;
    FaceMIT numFacesM;

    unsigned ctr = 0;
    for ( unsigned d = 0; d < DIM; d++ )
        if ( d != direction ) numFacesM[ctr++] = gridSizes[d];
    const unsigned numFaces = static_cast<unsigned>( FaceMI::length( numFacesM ) );

    // face number
    const unsigned faceNum =
        detail_::FaceNumberLookUp<DIM>::apply( direction, side );

    // go through all faces
    for ( unsigned f = 0; f < numFaces; f ++ ) {

        // multi-index on the grid face
        const FaceMIT fM = FaceMI::wrap( f, numFacesM );

        // construct domain face index
        typename base::MultiIndex<DIM>::Type domIndexM;
        unsigned ctr = 0;
        for ( unsigned d = 0; d < DIM; d++ ) {
            if ( d == direction ) domIndexM[d] = fixed;
            else                  domIndexM[d] = fM[ctr++];
        }

        // linearise
        const std::size_t domIndex = base::MultiIndex<DIM>::unwrap( domIndexM,
                                                                    gridSizes );

        // store pair of element number and face number
        boundaryElementContainer.push_back( std::make_pair( domIndex, faceNum ) );
    }
        
    return;
}
Example #3
0
inline size_t get_memory_limit() {
  rlimit rl;
  int res = getrlimit(RLIMIT_AS, &rl);
  VERIFY_MSG(res == 0,
             "getrlimit(2) call failed, errno = " << errno);

  return rl.rlim_cur;
}
inline rlim_t limit_file(size_t limit) {
  struct rlimit rl;

  int res = getrlimit(RLIMIT_NOFILE, &rl);
  VERIFY_MSG(res == 0,
             "getrlimit(2) call failed, errno = " << errno);

  // We cannot go beyond hard limit and we might not have enough privileges to
  // increase the hard limit
  limit = std::max<size_t>(limit, rl.rlim_cur);
  rl.rlim_cur = std::min<size_t>(limit, rl.rlim_max);
  res = setrlimit(RLIMIT_NOFILE, &rl);
  VERIFY_MSG(res == 0,
             "setrlimit(2) call failed, errno = " << errno);
  INFO("Open file limit set to " << rl.rlim_cur);

  return rl.rlim_cur;
}
Example #5
0
inline void limit_memory(size_t limit) {
  rlimit rl;
  if (sizeof(rlim_t) < 8) {
    INFO("Can't limit virtual memory because of 32-bit system");
    return;
  }

  int res = getrlimit(RLIMIT_AS, &rl);
  VERIFY_MSG(res == 0,
             "getrlimit(2) call failed, errno = " << errno);

  // We cannot go beyond hard limit and we might not have enough privileges to
  // increase the hard limit
  rl.rlim_cur = std::min<size_t>(limit, rl.rlim_max);
  res = setrlimit(RLIMIT_AS, &rl);
  VERIFY_MSG(res == 0,
             "setrlimit(2) call failed, errno = " << errno);
  INFO("Memory limit set to " << (1.0 * (double)rl.rlim_cur / 1024 / 1024 / 1024) << " Gb");
}
Example #6
0
    /** Function call operator doing the main job
     *  \param[out] mesh  The mesh constructed from the file input
     *  \param[in]  smf   Input stream with the SMF-specified geometry
     */
    void operator()( Mesh & mesh, std::istream & smf ) const
    {
        // Read header and validate it
        std::pair<bool,std::string> externalNodes    = std::make_pair( false, "");
        std::pair<bool,std::string> externalElements = std::make_pair( false, "");
        const bool validHeader =
            this -> readAndValidateHeader_( smf, externalNodes, externalElements );
        VERIFY_MSG( validHeader, "Smf header is invalid" );

        unsigned nNodes, nElements;
        this -> readNumbers_( smf, nNodes, nElements );
        mesh.allocate( nNodes, nElements );

        // Read coordinates and pass them to the nodes
        if ( externalNodes.first ) {
            std::ifstream smfNodesExt( externalNodes.second.c_str() );
            
            if ( not smfNodesExt.is_open() ) {
                std::cerr << "Failed to open " << externalNodes.second << '\n';
                VERIFY_MSG( false, "IO Error (see above) " );
            }
                
            this -> readAndSetNodes_( smfNodesExt, mesh );
            smfNodesExt.close();
        }
        else
            this -> readAndSetNodes_( smf, mesh );

        // Read elements' connectivities and pass them to the elements
        if ( externalElements.first ) {
            std::ifstream smfConnExt( externalElements.second.c_str() );

            if ( not smfConnExt.is_open() ) {
                std::cerr << "Failed to open " << externalElements.second << '\n';
                VERIFY_MSG( false, "IO Error (see above) " );
            }

            this -> readAndSetElements_( smfConnExt, mesh );
            smfConnExt.close();
        }
        else 
            this -> readAndSetElements_( smf, mesh );
    }
  virtual ~MMappedReader() {
    if (StreamFile != -1)
      close(StreamFile);
    if (MappedRegion)
      munmap(MappedRegion, BlockSize);

    if (Unlink) {
      int res = unlink(FileName.c_str());
      VERIFY_MSG(res == 0,
                 "unlink(2) failed. Reason: " << strerror(errno) << ". Error code: " << errno);
    }
  }
Example #8
0
void generateMesh( MESH& mesh, const UIN& userInput ) 
{
    if ( userInput.readMeshFromFile ) {
        std::ifstream smf( userInput.meshFile.c_str() );
        VERIFY_MSG( smf.is_open(),
                    x2s("Cannot find input file ") + userInput.meshFile );
        base::io::smf::readMesh( smf, mesh );
    }
    else {
        ::generateMesh<UIN::dim>( mesh, userInput.N, userInput.bbmin, userInput.bbmax );
    }
}
Example #9
0
void constrainSupports( FIELD& field )
{
    VERIFY_MSG( (FIELD::DegreeOfFreedom::size==2),
                "This method only works for 2D" );
    
    typename FIELD::DoFPtrIter dIter = field.doFsBegin();

    const std::size_t numDoFs = std::distance( dIter, field.doFsEnd() );

    VERIFY_MSG( (numDoFs % 4) == 0, "Trying to fix the quarter points" );

    (*dIter) -> constrainValue( 1, 0. );

    std::advance( dIter, numDoFs/4 );
    (*dIter) -> constrainValue( 0, 0. );
        
    std::advance( dIter, numDoFs/4 );
    (*dIter) -> constrainValue( 1, 0. );

    std::advance( dIter, numDoFs/4 );
    (*dIter) -> constrainValue( 0, 0. );

}
Example #10
0
bool DicomRasterPager::openFile(const std::string &filename)
{
   mpImage.reset(new DicomImage(filename.c_str()));
   if(mpImage->getStatus() != EIS_Normal)
   {
      VERIFY_MSG(false, DicomImage::getString(mpImage->getStatus()));
   }
   if((mpImage->getPhotometricInterpretation() == EPI_RGB ||
       mpImage->getPhotometricInterpretation() == EPI_PaletteColor) &&
       static_cast<const RasterDataDescriptor*>(getRasterElement()->getDataDescriptor())->getBandCount() != mpImage->getFrameCount())
   {
      mConvertRgb = true;
   }
   return true;
}
Example #11
0
    /** Write itself and write either CData or child tags
     *  \param[in] out         Stream for output
     *  \param[in] indentLevel Level of indentation for legibility
     */
    void write( std::ostream & out, const unsigned indentLevel = 0 ) const
    {
        std::string indent( 2 * indentLevel, ' ' );
        
        out << indent << "<" << name_ << " ";

        // write attributes;
        for ( unsigned a = 0; a < attributes_.size(); a ++ ) {
            out << attributes_[a].first  << "=\""
                << attributes_[a].second << "\"";

            if ( a < (attributes_.size() - 1) ) out << " ";
        }

        // check children
        const bool noChildren = children_.empty();

        // check cdata_
        const bool noCData    = (cData_ == NULL);

        // closing symbol
        if ( noChildren and noCData ) {
            out << "/> \n";
        }
        else out << "> \n";

        // sanity check
        VERIFY_MSG( (noCData or noChildren),
                    "Cannot have data AND children" );

        //! Write CDATA if available (not indented)
        if ( not noCData ) {
            cData_ -> write( out );
            out << "\n";
        }

        //! Write children if available
        if ( not noChildren ) {
            for ( unsigned c = 0; c < children_.size(); c ++ )
                children_[c].write( out, indentLevel+1 );
        }

        //! write closing tag if their had been data or children
        if ( not( noChildren and noCData ) ) {
            out << indent << "</" << name_ << ">\n";
        }
        
    }
  void remap() {
    VERIFY(BlockSize != FileSize);

    if (MappedRegion)
      munmap(MappedRegion, BlockSize);

    BlockOffset += BlockSize;
    // We do not add PROT_WRITE here intentionaly - remapping and write access
    // is pretty error-prone.
    MappedRegion =
        (uint8_t*)mmap(NULL, BlockSize,
                       PROT_READ, MAP_FILE | MAP_PRIVATE,
                       StreamFile, BlockOffset);
    VERIFY_MSG((intptr_t)MappedRegion != -1L,
               "mmap(2) failed. Reason: " << strerror(errno) << ". Error code: " << errno);
  }
Example #13
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 #14
0
/** Compute the elastic (large!) deformation of a block of material.
 *  See problem description in ref06::PulledSheetProblem for a the boundary
 *  conditions. The problem is non-linear and therefore a Newton method is
 *  used. Moreover, the applied load (displacement or traction) is divided into
 *  load steps.
 *
 *  New features:
 *  - vectorial problem: DoFs are not scalar anymore
 *  - hyper-elasticity
 *
 */
int ref06::compressible( int argc, char * argv[] )
{
    // basic attributes of the computation
    const unsigned    geomDeg  = 1;
    const unsigned    fieldDeg = 2;
    const base::Shape shape    = base::HyperCubeShape<SPACEDIM>::value;

    // typedef mat::hypel::StVenant Material;
    typedef mat::hypel::NeoHookeanCompressible Material;

    // usage message
    if ( argc != 3 ) {
        std::cout << "Usage:  " << argv[0] << "  mesh.smf input.dat \n";
        return 0;
    }

    // read name of input file
    const std::string meshFile  = boost::lexical_cast<std::string>( argv[1] );
    const std::string inputFile = boost::lexical_cast<std::string>( argv[2] );

    // read from input file
    double E, nu, pull, traction, tolerance;
    unsigned maxIter, loadSteps;
    bool dispControlled;
    {    
        //Feed properties parser with the variables to be read
        base::io::PropertiesParser prop;
        prop.registerPropertiesVar( "E",                E );
        prop.registerPropertiesVar( "nu",               nu );
        prop.registerPropertiesVar( "pull",             pull );
        prop.registerPropertiesVar( "maxIter",          maxIter );
        prop.registerPropertiesVar( "loadSteps",        loadSteps );
        prop.registerPropertiesVar( "traction",         traction );
        prop.registerPropertiesVar( "dispControlled",   dispControlled );
        prop.registerPropertiesVar( "tolerance",        tolerance );

        // 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" );
        }
    }

    // find base name from mesh file
    const std::string baseName = base::io::baseName( meshFile, ".smf" );

    //--------------------------------------------------------------------------
    // define a mesh
    typedef base::Unstructured<shape,geomDeg>    Mesh;
    const unsigned dim = Mesh::Node::dim;

    // create a mesh and read from input
    Mesh mesh;
    {
        std::ifstream smf( meshFile.c_str() );
        base::io::smf::readMesh( smf, mesh );
        smf.close();
    }

    // quadrature objects for volume and surface
    const unsigned kernelDegEstimate = 3;
    typedef base::Quadrature<kernelDegEstimate,shape> Quadrature;
    Quadrature quadrature;
    typedef base::SurfaceQuadrature<kernelDegEstimate,shape> SurfaceQuadrature;
    SurfaceQuadrature surfaceQuadrature;

    // Create a field
    const unsigned    doFSize = dim;
    typedef base::fe::Basis<shape,fieldDeg>        FEBasis;
    typedef base::Field<FEBasis,doFSize>           Field;
    typedef Field::DegreeOfFreedom                 DoF;
    Field field;

    // generate DoFs from mesh
    base::dof::generate<FEBasis>( mesh, field );

    // Creates a list of <Element,faceNo> pairs along the boundary
    base::mesh::MeshBoundary meshBoundary;
    meshBoundary.create( mesh.elementsBegin(), mesh.elementsEnd() );

    // Create a boundary mesh from this list
    typedef base::mesh::BoundaryMeshBinder<Mesh::Element>::Type BoundaryMesh;
    BoundaryMesh boundaryMesh;
    {
        // Create a real mesh object from this list
        base::mesh::generateBoundaryMesh( meshBoundary.begin(),
                                          meshBoundary.end(),
                                          mesh, boundaryMesh );
    }

    // initial pull = (total amount) / (number of steps)
    const double firstPull = pull / static_cast<double>( loadSteps );

    // constrain the boundary
    base::dof::constrainBoundary<FEBasis>( meshBoundary.begin(),
                                           meshBoundary.end(),
                                           mesh, field, 
                                           boost::bind(
                                               &ref06::PulledSheet<dim>::dirichletBC<DoF>,
                                               _1, _2, dispControlled, firstPull ) );

    // Bind the fields together
    typedef base::asmb::FieldBinder<Mesh,Field> FieldBinder;
    FieldBinder fieldBinder( mesh, field );
    typedef FieldBinder::TupleBinder<1,1>::Type FTB;

    typedef base::asmb::SurfaceFieldBinder<BoundaryMesh,Field> SurfaceFieldBinder;
    SurfaceFieldBinder surfaceFieldBinder( boundaryMesh, field );
    typedef SurfaceFieldBinder::TupleBinder<1>::Type SFTB;

    // material object
    Material material( mat::Lame::lambda( E, nu), mat::Lame::mu( E, nu ) );

    // matrix kernel
    typedef solid::HyperElastic<Material,FTB::Tuple> HyperElastic;
    HyperElastic hyperElastic( material );
            
    // Number the degrees of freedom
    const std::size_t numDofs =
        base::dof::numberDoFsConsecutively( field.doFsBegin(), field.doFsEnd() );
    std::cout << "# Number of dofs " << numDofs << std::endl;

    // create table for writing the convergence behaviour of the nonlinear solves
    base::io::Table<4>::WidthArray widths = {{ 2, 5, 5, 15 }};
    base::io::Table<4> table( widths );
    table % "Step" % "Iter" % "|F|"  % "|x|";
    std::cout << "#" << table;

    // write a vtk file
    ref06::writeVTKFile( baseName, 0, mesh, field, material );


    //--------------------------------------------------------------------------
    // Loop over load steps
    //--------------------------------------------------------------------------
    for ( unsigned step = 0; step < loadSteps; step++ ) {

        // rescale constraints in every load step: (newValue / oldValue)
        const double  pullFactor =
            (step == 0 ?
             static_cast<double>( step+1 ) :
             static_cast<double>( step+1 )/ static_cast<double>(step) );

        // scale constraints
        base::dof::scaleConstraints( field, pullFactor );

        //----------------------------------------------------------------------
        // Nonlinear iterations
        //----------------------------------------------------------------------
        unsigned iter = 0;
        while ( iter < maxIter ) {

            table % step % iter;
    
            // Create a solver object
            typedef base::solver::Eigen3           Solver;
            Solver solver( numDofs );

            // apply traction boundary condition, if problem is not disp controlled
            if ( not dispControlled ) {
                
                // value of applied traction
                const double tractionFactor =
                    traction * 
                    static_cast<double>(step+1) / static_cast<double>( loadSteps );

                // apply traction load
                base::asmb::neumannForceComputation<SFTB>(
                    surfaceQuadrature, solver,
                    surfaceFieldBinder,
                    boost::bind( &ref06::PulledSheet<dim>::neumannBC,
                                 _1, _2, tractionFactor ) );
            }

            // residual forces
            base::asmb::computeResidualForces<FTB>( quadrature, solver,
                                                    fieldBinder,
                                                    hyperElastic );
            
            // Compute element stiffness matrices and assemble them
            base::asmb::stiffnessMatrixComputation<FTB>( quadrature, solver,
                                                         fieldBinder,
                                                         hyperElastic );

            // Finalise assembly
            solver.finishAssembly();

            // norm of residual 
            const double conv1 = solver.norm();
            table % conv1;

            // convergence via residual norm
            if ( conv1 < tolerance * E ) { // note the tolerance multiplier
                std::cout << table;
                break;
            }

            // Solve
            //solver.choleskySolve();
            solver.cgSolve();
            
            // distribute results back to dofs
            base::dof::addToDoFsFromSolver( solver, field );

            // norm of displacement increment
            const double conv2 = solver.norm();
            table % conv2;
            std::cout << table;
            iter++;
            
            // convergence via increment
            if ( conv2 < tolerance ) break;
        }
        // Finished non-linear iterations
        //----------------------------------------------------------------------

        // warning
        if ( iter == maxIter ) {
            std::cout << "# (WW) Step " << step << " has not converged within "
                      << maxIter << " iterations \n";
        }

        // write a vtk file
        ref06::writeVTKFile( baseName, step+1, mesh, field, material );
        
    }
    // Finished load steps
    //--------------------------------------------------------------------------
    
    return 0;
}
Example #15
0
//------------------------------------------------------------------------------
int main( int argc, char * argv[] )
{
    // basic attributes of the computation
    const unsigned    geomDeg   = 1;
    const unsigned    fieldDegU = 2;
    const unsigned    fieldDegP = 1;
    const unsigned    tiOrder   = 2;   // order of time integrator
    const base::Shape shape     = base::QUAD;

    //typedef  base::time::BDF<tiOrder> MSM;
    typedef base::time::AdamsMoulton<tiOrder> MSM;

    // time stepping method determines the history size
    const unsigned nHist = MSM::numSteps;

    
    const std::string inputFile = "terz.inp";
    double E, nu, alpha, c0, k, H, F, tMax;
    unsigned numSteps, numIntervals;
    {
        base::io::PropertiesParser pp;
        pp.registerPropertiesVar( "E",     E     );
        pp.registerPropertiesVar( "nu",    nu    );
        pp.registerPropertiesVar( "alpha", alpha );
        pp.registerPropertiesVar( "c0",    c0    );
        pp.registerPropertiesVar( "k",     k     );
        pp.registerPropertiesVar( "H",     H     );
        pp.registerPropertiesVar( "F",     F     );

        pp.registerPropertiesVar( "tMax",         tMax  );
        pp.registerPropertiesVar( "numSteps",     numSteps );
        pp.registerPropertiesVar( "numIntervals", numIntervals );

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

    }

    const double deltaT = tMax / static_cast<double>( numSteps );

    // usage message
    if ( argc != 2 ) {
        std::cout << "Usage:  " << argv[0] << "  mesh.smf \n";
        return 0;
    }

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

    

    // Analytic solution
    Terzaghi terzaghi( E, nu, alpha, c0, k, H, F );
    

    //--------------------------------------------------------------------------
    // define a mesh
    typedef base::Unstructured<shape,geomDeg>    Mesh;
    const unsigned dim = Mesh::Node::dim;

    // create a mesh and read from input
    Mesh mesh;
    {
        std::ifstream smf( meshFile.c_str() );
        base::io::smf::readMesh( smf, mesh );
        smf.close();
    }

    // quadrature objects for volume and surface
    const unsigned kernelDegEstimate = 3;
    typedef base::Quadrature<kernelDegEstimate,shape> Quadrature;
    Quadrature quadrature;
    typedef base::SurfaceQuadrature<kernelDegEstimate,shape> SurfaceQuadrature;
    SurfaceQuadrature surfaceQuadrature;

    // Create a displacement field
    const unsigned    doFSizeU = dim;
    typedef base::fe::Basis<shape,fieldDegU>           FEBasisU;
    typedef base::Field<FEBasisU,doFSizeU,nHist>       Displacement;
    typedef Displacement::DegreeOfFreedom              DoFU;
    Displacement displacement;

    // Create a pressure field
    const unsigned    doFSizeP = 1;
    typedef base::fe::Basis<shape,fieldDegP>           FEBasisP;
    typedef base::Field<FEBasisP,doFSizeP,nHist>       Pressure;
    typedef Pressure::DegreeOfFreedom                  DoFP;
    Pressure pressure;

    // generate DoFs from mesh
    base::dof::generate<FEBasisU>( mesh, displacement );
    base::dof::generate<FEBasisP>( mesh, pressure );

    // Creates a list of <Element,faceNo> pairs along the boundary
    base::mesh::MeshBoundary meshBoundary;
    meshBoundary.create( mesh.elementsBegin(), mesh.elementsEnd() );

    // Create a boundary mesh from this list
    typedef base::mesh::CreateBoundaryMesh<Mesh::Element> CreateBoundaryMesh;
    typedef CreateBoundaryMesh::BoundaryMesh BoundaryMesh;
    BoundaryMesh boundaryMesh;
    {
        CreateBoundaryMesh::apply( meshBoundary.begin(),
                                   meshBoundary.end(),
                                   mesh, boundaryMesh );
    }



    // material object
    typedef mat::hypel::StVenant Material;
    Material material( mat::Lame::lambda( E, nu), mat::Lame::mu( E, nu ) );

    typedef base::asmb::FieldBinder<Mesh,Displacement,Pressure> Field;
    Field field( mesh, displacement, pressure );

    typedef Field::TupleBinder<1,1>::Type TopLeft;
    typedef Field::TupleBinder<1,2>::Type TopRight;
    typedef Field::TupleBinder<2,1>::Type BotLeft;
    typedef Field::TupleBinder<2,2>::Type BotRight;

    // surface displacement field
    typedef base::asmb::SurfaceFieldBinder<BoundaryMesh,Displacement> SurfaceFieldBinder;
    SurfaceFieldBinder surfaceFieldBinder( boundaryMesh, displacement );
    typedef SurfaceFieldBinder::TupleBinder<1>::Type SFTB;
    
    // kernel objects
    typedef solid::HyperElastic<Material,TopLeft::Tuple> HyperElastic;
    HyperElastic hyperElastic( material );

    typedef fluid::PressureGradient<TopRight::Tuple> GradP;
    GradP gradP;

    //typedef fluid::VelocityDivergence<FieldPUUTuple> DivU;
    //DivU divU( true ); // * alpha
    typedef PoroDivU<BotLeft::Tuple> DivU;
    DivU divU( alpha );

    typedef heat::Laplace<BotRight::Tuple> Laplace;
    Laplace laplace( k );

    // constrain the boundary
    base::dof::constrainBoundary<FEBasisU>( meshBoundary.begin(),
                                            meshBoundary.end(),
                                            mesh, displacement, 
                                            boost::bind( &dirichletU<dim,DoFU>, _1, _2, 1.0 ) );
    
    base::dof::constrainBoundary<FEBasisP>( meshBoundary.begin(),
                                            meshBoundary.end(),
                                            mesh, pressure, 
                                            boost::bind( &dirichletP<dim,DoFP>, _1, _2, H ) );


    // Number the degrees of freedom
    const std::size_t numDoFsU =
        base::dof::numberDoFsConsecutively( displacement.doFsBegin(), displacement.doFsEnd() );
    std::cout << "# Number of displacement dofs " << numDoFsU << std::endl;
    const std::size_t numDoFsP =
        base::dof::numberDoFsConsecutively( pressure.doFsBegin(), pressure.doFsEnd(), numDoFsU );
    std::cout << "# Number of pressure     dofs " << numDoFsP << std::endl;


    // write VTK file
    writeVTK( mesh, displacement, pressure, meshFile, 0 );

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

        const double time = (n+1) * deltaT;
        std::cout << time << "  ";

        // initialise current displacement to zero (linear elasticity)
        std::for_each( displacement.doFsBegin(), displacement.doFsEnd(),
                       boost::bind( &DoFU::clearValue, _1 ) );

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

        //------------------------------------------------------------------
        base::asmb::stiffnessMatrixComputation<TopLeft>( quadrature, solver, 
                                                         field, hyperElastic );

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

        base::asmb::stiffnessMatrixComputation<BotRight>( quadrature, solver,
                                                          field, laplace);

        // time integration terms
        base::time::computeReactionTerms<BotLeft,MSM>( divU, quadrature, solver,
                                                       field, deltaT, n );

        base::time::computeInertiaTerms<BotRight,MSM>( quadrature, solver,
                                                       field, deltaT, n, c0 );
        
        base::time::computeResidualForceHistory<BotRight,MSM>( laplace, 
                                                               quadrature, solver,
                                                               field, n );


        // Neumann boundary condition
        base::asmb::neumannForceComputation<SFTB>( surfaceQuadrature, solver, surfaceFieldBinder,
                                                   boost::bind( &neumannBC<dim>, _1, _2,
                                                                H, F ) );


        // Finalise assembly
        solver.finishAssembly();

        // Solve
        solver.superLUSolve();
            
        // distribute results back to dofs
        base::dof::setDoFsFromSolver( solver, displacement );
        base::dof::setDoFsFromSolver( solver, pressure );
        
        // push history
        std::for_each( displacement.doFsBegin(), displacement.doFsEnd(),
                       boost::bind( &DoFU::pushHistory, _1 ) );
        std::for_each( pressure.doFsBegin(), pressure.doFsEnd(),
                       boost::bind( &DoFP::pushHistory, _1 ) );


        // write VTK file
        writeVTK( mesh, displacement, pressure, meshFile, n+1 );
        
        // Finished time steps
        //--------------------------------------------------------------------------

        const std::pair<double,double> approx = probe( mesh, displacement, pressure );

        const double p = terzaghi.pressure( H/2., time );
        const double u = terzaghi.displacement( H/2., time );
        
        std::cout << u  << "  " << approx.first << "  "
                  << p  << "  " << approx.second << '\n';
    }
    
    return 0;
}
Example #16
0
//------------------------------------------------------------------------------
int main( int argc, char * argv[] )
{
    // basic attributes of the computation
    const unsigned    geomDeg  = 1;
    const unsigned    fieldDeg = 1;
    const unsigned    dim      = 2;
    const base::Shape shape    = base::SimplexShape<dim-1>::value;

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

    // read name of input file
    const std::string inputFile = boost::lexical_cast<std::string>( argv[1] );

    // read from input file
    std::string meshFile;
    double A, B, tolerance, pressure;
    unsigned maxIter, loadSteps;
    {    
        //Feed properties parser with the variables to be read
        base::io::PropertiesParser prop;
        prop.registerPropertiesVar( "meshFile",         meshFile );
        prop.registerPropertiesVar( "A",                A );
        prop.registerPropertiesVar( "B",                B );
        prop.registerPropertiesVar( "maxIter",          maxIter );
        prop.registerPropertiesVar( "loadSteps",        loadSteps );
        prop.registerPropertiesVar( "tolerance",        tolerance );
        prop.registerPropertiesVar( "pressure",         pressure );

        // 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" );
        }
    }

    // find base name from mesh file
    const std::string baseName = base::io::baseName( meshFile, ".smf" );

    //--------------------------------------------------------------------------
    // define a mesh
    typedef base::Unstructured<shape,geomDeg,dim>    Mesh;

    // create a mesh and read from input
    Mesh mesh;
    {
        std::ifstream smf( meshFile.c_str() );
        base::io::smf::readMesh( smf, mesh );
        smf.close();
    }

    // quadrature objects for volume and surface
    const unsigned kernelDegEstimate = 1; //3;
    typedef base::Quadrature<kernelDegEstimate,shape> Quadrature;
    Quadrature quadrature;
    
    // Create a field
    const unsigned    doFSize = dim;
    typedef base::fe::Basis<shape,fieldDeg>        FEBasis;
    typedef base::Field<FEBasis,doFSize>           Field;
    typedef Field::DegreeOfFreedom                 DoF;
    Field field;

    // generate DoFs from mesh
    base::dof::generate<FEBasis>( mesh, field );


    // constrain a dof
    constrainSupports( field );

    // Bind the fields together
    typedef base::asmb::FieldBinder<Mesh,Field> FieldBinder;
    FieldBinder fieldBinder( mesh, field );
    typedef FieldBinder::TupleBinder<1,1>::Type FTB;

    // material object
    typedef surf::Skalak Energy;
    Energy   energy( A, B );

    //typedef surf::NeoHookean Energy;
    //Energy   energy( A  );

    typedef surf::HyperElasticMembrane<Energy> Material;
    Material material( energy );

    // matrix kernel
    typedef solid::HyperElastic<Material,FTB::Tuple> HyperElastic;
    HyperElastic hyperElastic( material );

    // Number the degrees of freedom
    const std::size_t numDofs =
        base::dof::numberDoFsConsecutively( field.doFsBegin(), field.doFsEnd() );
    std::cout << "# Number of dofs " << numDofs << std::endl;

    // write a vtk file
    writeVTKFile( baseName, 0, mesh, field, material );

    // load increment
    const double deltaP = pressure / static_cast<double>( loadSteps );

    std::cout << "# pressure   radius \n"
              << 0.0  << "   "  << giveRadius( mesh, field ) << "\n";
    
    //--------------------------------------------------------------------------
    // Loop over load steps
    //--------------------------------------------------------------------------
    for ( unsigned step = 0; step < loadSteps; step++ ) {

        // current load
        const double p = (step+1) * deltaP;

        //----------------------------------------------------------------------
        // Nonlinear iterations
        //----------------------------------------------------------------------
        unsigned iter = 0;
        while ( iter < maxIter ) {

            //std::cout << "Iter " << iter;

            // Create a solver object
            typedef base::solver::Eigen3           Solver;
            Solver solver( numDofs );

            
            base::asmb::computeResidualForces<FTB>( quadrature, solver,
                                                    fieldBinder, hyperElastic );
            
            // Compute element stiffness matrices and assemble them
            base::asmb::stiffnessMatrixComputation<FTB>( quadrature, solver,
                                                         fieldBinder, hyperElastic,
                                                         iter > 0 );

            // internal pressure load
            base::asmb::bodyForceComputation2<FTB>( quadrature, solver, fieldBinder,
                                                    boost::bind( &internalPressure<Mesh::Element>,
                                                                 _1, _2, p ) );


            // Finalise assembly
            solver.finishAssembly();

            // norm of residual 
            const double conv1 = solver.norm();

            //std::cout << " |F| = " << conv1;

            // convergence via residual norm
            if ( conv1 < tolerance * A ) { // note the tolerance multiplier
                //std::cout << "\n";
                break;
            }

            // Solve
            solver.choleskySolve();
            
            // distribute results back to dofs
            base::dof::addToDoFsFromSolver( solver, field );

            // norm of displacement increment
            const double conv2 = solver.norm();
            //std::cout << " | DU | = " << conv2 << "\n";
            
            // convergence via increment
            if ( conv2 < tolerance ) break;

            iter++;

        }
        // Finished non-linear iterations
        //----------------------------------------------------------------------

        // warning
        if ( iter == maxIter ) {
            std::cout << "# (WW) Step " << step << " has not converged within "
                      << maxIter << " iterations \n";
        }

        // write a vtk file
        writeVTKFile( baseName, step+1, mesh, field, material );

        std::cout << p << " " << giveRadius( mesh, field ) << std::endl;

    }
    // Finished load steps
    //--------------------------------------------------------------------------

    
    return 0;
}
    void operator()( const Grid & grid,
                     const unsigned dir,
                     const bool begin,
                     SurfaceMesh & surfaceMesh ) const
    {
        //! Sanity check of direction
        VERIFY_MSG( (dir < Grid::dim), "Input argument for direction wrong" );

        //! Dimensions of the grid
        const MultiIndexType gridSizes = grid.gridSizes();

        //! Multi-index component to compare with
        const int mIndexComp = ( begin == false ? 0 : gridSizes[dir]-1 );

        //! Number of elements in the structured grid
        const std::size_t numElements = MultiIndex::length( gridSizes );

        //! Number of elements on the requested surface
        const std::size_t numElementsOnSurface = numElements / gridSizes[ dir ];

        //! Construct parametric geometry of the element
        const unsigned surfaceID =
            detail_::convertToSurfaceID<VolumeElement::shape>( dir, begin );

        //! List of indices of the parameter space vertices which form the surface
        typename ParameterSurface::Surface
            parameterSurfaceIndices = ParameterSurface::surfaceTable[ surfaceID ];

        //! Interpolation points of the surface shape function
        boost::array< typename SurfaceShapeFun::VecDim,
                      SurfaceShapeFun::numFun> surfaceSupportPoints;
        SurfaceShapeFun::supportPoints( surfaceSupportPoints );

        
        //! Vertices of the parameter volume
        boost::array< typename LinearVolumeFun::VecDim,
                      LinearVolumeFun::numFun> volumeVertices;
        LinearVolumeFun::supportPoints( volumeVertices );

        // --> Reorder for hiearchical ordering
        //     Then, the object ParameterFaces< shape, dim-1> can be used and
        //     ParamaterSurface discarded.

        //! Iterator to surface mesh elements
        typename SurfaceMesh::ElementPtrIter surfElemIter
            = surfaceMesh.elementsBegin();

        //! Linear shape function on the surface simplex
        LinearSimplexFun linearSimplexFun;

        //! Hexahedra will have two triangles per face
        const unsigned numSurfElementsPerElement = 
            detail_::NumSimplicesPerElementSurface<VolumeElement::shape>::value;

        //! Temporary storage of surface elements and nodes
        std::vector<SurfaceElement*> surfaceElements;
        surfaceElements.reserve( numElementsOnSurface * numSurfElementsPerElement );
        std::vector<SurfaceNode*>    surfaceNodes;

        //! node counter
        std::size_t nodeCtr = 0;

        //! Go through all elements
        for ( std::size_t e = 0; e < numElements; e ++ ) {

            //! Construct multi-index from linear counter
            const MultiIndexType eM = MultiIndex::wrap( e, gridSizes );

            //! Check if on requested boundary surface
            const bool onBoundary = ( eM[ dir ] == mIndexComp );

            //! If so, construct the surface element(s)
            if ( onBoundary ) {

                //! Get pointer to volume element
                VolumeElement * vep = grid.elementPtr( eM );

                //! Go through elements on the surface of the volume element
                for ( unsigned se = 0; se < numSurfElementsPerElement; se ++ ) {

                    //! Create new surface element
                    SurfaceElement * surfElem = new SurfaceElement;

                    //! Extract the surface simplex's vertices
                    boost::array<unsigned, numSurfSimplexVertices> surfSimplex;
                    detail_::ExtractSurfaceSimplex<VolumeElement::shape>()( parameterSurfaceIndices,
                                                                            se, surfSimplex );

                    //! Set volume element pointer
                    surfElem -> setVolumeElementPointer( vep );

                    //! Access to surface elements geometry nodes
                    typename SurfaceElement::NodePtrIter nodePtrIter =
                        surfElem -> nodesBegin();

                    //! Go through the parameter points of the surface element
                    typename SurfaceElement::ParamIter paramIter =
                        surfElem -> parametricBegin();
                    typename SurfaceElement::ParamIter paramEnd  =
                        surfElem -> parametricEnd();

                    for ( unsigned p = 0; paramIter != paramEnd;
                          ++paramIter, ++nodePtrIter, p++ ) {

                        //! ..
                        typename base::Vector<surfaceDim>::Type eta
                            = surfaceSupportPoints[ p ];

                        typename LinearSimplexFun::FunArray phi;
                        linearSimplexFun.evaluate( eta, phi );

                        typename base::Vector<volumeDim>::Type xi
                            = base::constantVector<volumeDim>( 0. );

                        for ( unsigned s = 0; s < phi.size(); s ++ ) {
                            xi += phi[s] * volumeVertices[ surfSimplex[s] ];

                        }

                        *paramIter = xi;

                        //! evaluate geometry at the parameter point
                        const typename VolumeElement::Node::VecDim x =
                            base::Geometry<VolumeElement>()( vep, xi );

                        //! convert to vector and pass to node
                        std::vector<double> xV( x.size() );
                        for ( int d = 0; d < x.size(); d ++ )
                            xV[d] = x[d];

                        SurfaceNode * surfNode = new SurfaceNode;
                        surfNode -> setX( xV.begin() );
                        surfNode -> setID( nodeCtr++ );
                        
                        *nodePtrIter = surfNode;

                        surfaceNodes.push_back( surfNode );
                                                
                    } // end loop over surface element's nodes

                    //! Store element pointer
                    surfaceElements.push_back( surfElem );
                    
                } // end loop over simplices per volume element
                
            } // end condition if volume element lies on requested bdry

        }// end loop over all volume elements

        surfaceMesh.allocate( surfaceNodes.size(), surfaceElements.size() );

        std::copy( surfaceNodes.begin(), surfaceNodes.end(),
                   surfaceMesh.nodesBegin() );
        
        std::copy( surfaceElements.begin(), surfaceElements.end(),
                   surfaceMesh.elementsBegin() );
        
        return;
    }
Example #18
0
/** Analysis of a CSG-modelled geometry (elasticity)
 */
int cutCell::csgElastic( int argc, char* argv[] )
{
    // spatial dimension
    const unsigned    dim = 3;
    typedef base::Vector<dim,double>::Type VecDim;

    //--------------------------------------------------------------------------
    // surfaces
    
    // sphere
    const double rs = 0.65;
    const VecDim cs = base::constantVector<dim>( 0.5 );
    base::cut::Sphere<dim> sphere( rs, cs, true );
    
    // cylinder
    const double rc = 0.3;
    const VecDim cc = cs;
    const VecDim zero =  base::constantVector<dim>(0.);
    VecDim e1 = zero; e1[0] = 1.;
    VecDim e2 = zero; e2[1] = 1.;
    VecDim e3 = zero; e3[2] = 1.;
    base::cut::Cylinder<dim> cyl1( rc, cc, e1, false );
    base::cut::Cylinder<dim> cyl2( rc, cc, e2, false );
    base::cut::Cylinder<dim> cyl3( rc, cc, e3, false );
    
    if ( argc != 3 ) {
        std::cerr << "Usage: " << argv[0] << " N  input.dat\n"
                  << "(Compiled for dim=" << dim << ")\n\n";
        return -1;
    }

    // read name of input file
    const unsigned    numElements = boost::lexical_cast<unsigned>(    argv[1] );
    const std::string   inputFile = boost::lexical_cast<std::string>( argv[2] );

    // read from input file
    double E, nu, xmax, cutThreshold, sX, sY, sZ;
    std::string meshFile;
    unsigned stabilise; // 0 - not, 1 - Höllig
    bool compute;
    unsigned maxIter, loadSteps;
    double tolerance, forceVal;
    {    
        //Feed properties parser with the variables to be read
        base::io::PropertiesParser prop;
        prop.registerPropertiesVar( "E",            E );
        prop.registerPropertiesVar( "nu",           nu );
        
        prop.registerPropertiesVar( "xmax",         xmax );

        prop.registerPropertiesVar( "sX",           sX );
        prop.registerPropertiesVar( "sY",           sY );
        prop.registerPropertiesVar( "sZ",           sZ );

        prop.registerPropertiesVar( "stabilise",    stabilise );
        prop.registerPropertiesVar( "meshFile",     meshFile );
        prop.registerPropertiesVar( "compute",      compute );
        prop.registerPropertiesVar( "cutThreshold", cutThreshold );

        prop.registerPropertiesVar( "maxIter",      maxIter );
        prop.registerPropertiesVar( "tolerance",    tolerance );
        prop.registerPropertiesVar( "loadSteps",    loadSteps );
        prop.registerPropertiesVar( "forceVal",     forceVal );
        
        // Read variables from the input file
        std::ifstream inp( inputFile.c_str()  );
        VERIFY_MSG( inp.is_open(), "Cannot open input file" );
        VERIFY_MSG( prop.readValuesAndCheck( inp ), "Input error" );
        inp.close( );
    }

    // in case of no computation, do not stabilise
    if ( not compute ) stabilise = 0;
    
    // basic attributes of the computation
    const unsigned             geomDeg  = 1;
    const unsigned             fieldDeg = 1;
    const base::Shape             shape = //base::SimplexShape<dim>::value;
        base::HyperCubeShape<dim>::value;
    const base::Shape surfShape = base::SimplexShape<dim-1>::value;
    const unsigned    kernelDegEstimate = 5;

    // Bulk mesh
    typedef base::Unstructured<shape,geomDeg>  Mesh;
    typedef Mesh::Node::VecDim VecDim;
    Mesh mesh;
    std::string baseName;

    VecDim a, b;
    for ( unsigned d = 0; d < dim; d++ ) {
        a[d] = 0.;
        b[d] = xmax;
    }
    base::auxi::BoundingBox<dim> bbox( a, b );
    
    if ( numElements > 0 ) {
        base::Vector<dim,unsigned>::Type N;
        for ( unsigned d = 0; d < dim; d++ ) {
            N[d] = numElements;
        }
        generateMesh<dim>( mesh, N, a, b );

        baseName = argv[0] + std::string(".") + base::io::leadingZeros( numElements );
    }
    else{
        std::ifstream smf( meshFile.c_str() );
        base::io::smf::readMesh( smf, mesh );

        baseName = base::io::baseName( meshFile, ".smf" );
    }

    // Boundary mesh
    typedef base::mesh::BoundaryMeshBinder<Mesh,true>::Type BoundaryMesh;
    BoundaryMesh boundaryMesh;
    base::mesh::MeshBoundary meshBoundary;
    meshBoundary.create( mesh.elementsBegin(), mesh.elementsEnd() );
    base::mesh::generateBoundaryMesh( meshBoundary.begin(), meshBoundary.end(),
                                      mesh, boundaryMesh );

    // Cell structures
    typedef base::cut::Cell<shape> Cell;
    std::vector<Cell> cells;

    typedef base::cut::Cell<surfShape> SurfCell;
    std::vector<SurfCell> surfCells;

    // intersection of all level sets
    typedef base::cut::LevelSet<dim> LevelSet;
    std::vector<LevelSet> levelSetIntersection;

    //--------------------------------------------------------------------------
    // go through immersed surfaces
    //ImplicitGeometry<Mesh> geometry( mesh, boundaryMesh, sphere );
    cutCell::ImplicitGeometry<Mesh> geometry( mesh, boundaryMesh );
    geometry.intersectAnalytical( sphere, cutThreshold );
    geometry.intersectAnalytical( cyl1, cutThreshold );
    geometry.intersectAnalytical( cyl2, cutThreshold );
    geometry.intersectAnalytical( cyl3, cutThreshold );

    levelSetIntersection = geometry.getLevelSet();

#ifdef EMBEDFIRST
    cells                = geometry.getCells();
    surfCells            = geometry.getSurfCells();
#else
    base::cut::generateCutCells( mesh,         levelSetIntersection, cells,
                                 base::cut::CREATE );
    base::cut::generateCutCells( boundaryMesh, levelSetIntersection, surfCells,
                                 base::cut::CREATE );
#endif

    // Generate a mesh from the immersed surface
    typedef base::cut::SurfaceMeshBinder<Mesh>::SurfaceMesh SurfaceMesh;
    SurfaceMesh surfaceMesh;
    base::cut::generateSurfaceMesh<Mesh,Cell>( mesh, cells, surfaceMesh );

    //--------------------------------------------------------------------------
    // FE
#ifdef LINEAR
    typedef mat::hypel::StVenant               Material;
#else
    typedef mat::hypel::NeoHookeanCompressible Material;
#endif
    
    typedef cutCell::HyperElastic<Mesh,Material,fieldDeg> HyperElastic;
    HyperElastic hyperElastic( mesh, E, nu );

    typedef cutCell::SurfaceField<SurfaceMesh,HyperElastic::Field> SurfaceField;
    SurfaceField surfaceField(      surfaceMesh,         hyperElastic.getField() );
    SurfaceField boundaryField(     boundaryMesh,        hyperElastic.getField() );

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

    typedef base::Quadrature<kernelDegEstimate,surfShape> SurfaceQuadrature;
    SurfaceQuadrature surfaceQuadrature;

    typedef base::cut::Quadrature<kernelDegEstimate,surfShape> SurfaceCutQuadrature;
    SurfaceCutQuadrature surfaceCutQuadrature( surfCells, true );

    // compute supports
    const std::size_t numDoFs = std::distance( hyperElastic.getField().doFsBegin(),
                                               hyperElastic.getField().doFsEnd() );
    std::vector<double> supports;
    supports.resize(  numDoFs );
    
    base::cut::supportComputation( mesh, hyperElastic.getField(), cutQuadrature,  supports );
    std::vector<std::pair<std::size_t,VecDim> > doFLocation;
    base::dof::associateLocation( hyperElastic.getField(), doFLocation );

    // Fundamental solution
#ifdef LINEAR
    HyperElastic::VecDim sourcePoint = base::constantVector<dim>( 0. );
    HyperElastic::VecDim pointForce  = base::constantVector<dim>( 0. );
    sourcePoint[0] = sX; pointForce[0] = 1.;
    if ( dim > 1 ) { sourcePoint[1] = sY; pointForce[1] = 2.; }
    if ( dim > 2 ) { sourcePoint[2] = sZ; pointForce[2] = 3.; }

    typedef base::auxi::FundSolElastoStatic<dim> FSol;
    FSol fSol( mat::Lame::lambda( E, nu ), mat::Lame::mu( E, nu ) );

    typedef boost::function< HyperElastic::VecDoF( const VecDim& ) > FFun;
    FFun fFun = boost::bind( &FSol::fun, &fSol, _1, sourcePoint, pointForce );
    
    // apply dirichlet constraints
    base::dof::constrainBoundary<HyperElastic::FEBasis>(
        meshBoundary.begin(), meshBoundary.end(),
        mesh, hyperElastic.getField(), 
        boost::bind( &dirichletBCFromFSol<FFun,HyperElastic::DoF>, _1, _2, fFun ) );

    typedef boost::function< HyperElastic::VecDoF( const VecDim&,
                                                   const VecDim&) > FFun2;
    FFun2 fFun2 = boost::bind( &FSol::coNormal, &fSol, _1, sourcePoint, pointForce, _2 );
    
#else
    
    base::dof::constrainBoundary<HyperElastic::FEBasis>(
        meshBoundary.begin(), meshBoundary.end(),
        mesh, hyperElastic.getField(), 
        boost::bind( &fixBottom<dim,HyperElastic::DoF>, _1, _2, bbox ) );
    
#endif

    base::cut::stabiliseBasis( mesh, hyperElastic.getField(), supports, doFLocation );

    // number DoFs
    const std::size_t activeDoFsU = 
        base::dof::numberDoFsConsecutively( hyperElastic.getField().doFsBegin(),
                                            hyperElastic.getField().doFsEnd() );

    //--------------------------------------------------------------------------
    // Load step loop
#ifdef LINEAR
    const unsigned numSteps = 1;
    const unsigned numIter  = 1;
#else
    const unsigned numSteps = loadSteps;
    const unsigned numIter  = maxIter;

    // write zero state 
    hyperElastic.writeVTKFile(    baseName, 0, levelSetIntersection, cells, true );
    hyperElastic.writeVTKFileCut( baseName, 0, levelSetIntersection, cells, true );
#endif

    for ( unsigned s = 0; s < numSteps and compute; s++ ) {

        //----------------------------------------------------------------------
        // Nonlinear iterations
        unsigned iter = 0;
        while( iter < numIter ) {

            // Create a solver object
            typedef base::solver::Eigen3           Solver;
            Solver solver( activeDoFsU );

#ifdef LINEAR            
            // Neumann boundary condition -- box boundary
            boundaryField.applyNeumannBoundaryConditions( surfaceCutQuadrature,
                                                          solver, fFun2 );
        
            // Neumann boundary condition -- immersed surface
            surfaceField.applyNeumannBoundaryConditions( surfaceQuadrature,
                                                         solver, fFun2 );
            
#else
            const double factor =
                static_cast<double>( s+1 ) / static_cast<double>( numSteps );
            
            boundaryField.applyNeumannBoundaryConditions(
                surfaceCutQuadrature,
                solver,
                boost::bind( &twistTop<dim>, _1, _2, bbox, forceVal * factor ) );

            
#endif
        
            hyperElastic.assembleBulk( cutQuadrature, solver, iter );
            
            // Finalise assembly
            solver.finishAssembly();

            // norm of residual 
            const double conv1 = solver.norm();
#ifndef LINEAR
            std::cout << s << "  " << iter << "  " << conv1 << "  ";
#endif
            // convergence via residual norm
            if ( conv1 < tolerance * E ) { // note the tolerance multiplier
#ifndef LINEAR
                std::cout << std::endl;
#endif
                break;
            }

            // Solve
            //solver.choleskySolve();
            //solver.cgSolve();
            solver.superLUSolve();
            
            // distribute results back to dofs
            base::dof::addToDoFsFromSolver( solver, hyperElastic.getField() );

            // norm of displacement increment
            const double conv2 = solver.norm();
#ifndef LINEAR
            std::cout << conv2 << std::endl;
#endif
            iter++;
            
            // convergence via increment
            if ( conv2 < tolerance ) break;
            
        } // end iterations
            

        // warning
        if ( iter == maxIter ) {
            std::cout << "# (WW) Step " << s << " has not converged within "
                      << maxIter << " iterations \n";
        }

        //----------------------------------------------------------------------
        // write a vtk file
        hyperElastic.writeVTKFile(    baseName, s+1, levelSetIntersection, cells );
        hyperElastic.writeVTKFileCut( baseName, s+1, levelSetIntersection, cells );
        
    } // end load steps

    //------------------------------------------------------------------------------
    // Compute error and mesh volume for convergence (linear only)
#ifdef LINEAR            
    double hmin;
    {
        std::vector<double> h;
        Mesh::ElementPtrConstIter eIter = mesh.elementsBegin();
        Mesh::ElementPtrConstIter eEnd  = mesh.elementsEnd();
        for ( ; eIter != eEnd; ++eIter )  {
            h.push_back( base::mesh::elementSize( *eIter ) );
        }
     
        hmin = *std::min_element( h.begin(), h.end() );
    }

    std::cout << hmin << "  ";
    
    //--------------------------------------------------------------------------
    // Error
    std::cout << hyperElastic.computeL2Error( cutQuadrature, fFun ) << "  ";
    
    //--------------------------------------------------------------------------
    // Compute mesh volume
    const double volume = hyperElastic.computeVolume( cutQuadrature );
    std::cout << std::abs(volume-exactV) << "  ";

    //--------------------------------------------------------------------------
    // Compute surface area
    double area = surfaceField.computeArea( surfaceQuadrature );
    area += boundaryField.computeArea( surfaceCutQuadrature );
        
    std::cout << std::abs(area-exactA) << "  " << std::endl;

#endif

    return 0;
}
Example #19
0
//------------------------------------------------------------------------------
int main( int argc, char * argv[] )
{
    // spatial dimension
    const unsigned    dim = 2; 
    
    // basic attributes of the computation
    const unsigned    geomDeg  = 1;
    const unsigned    fieldDeg = 1;
    const base::Shape shape    = base::HyperCubeShape<dim>::value;
    const unsigned kernelDegEstimate = 3;

    // usage message
    if ( argc != 3 ) {
        std::cout << "Usage:  " << argv[0] << "  mesh.smf input.dat \n"
                  << "Compiled for dim=" << dim << "\n\n";
        return 0;
    }

    // read name of input file
    const std::string meshFile  = boost::lexical_cast<std::string>( argv[1] );
    const std::string inputFile = boost::lexical_cast<std::string>( argv[2] );

    // read from input file
    double E, nu, ubar1, ubar2, ubar3, tolerance;
    unsigned maxIter;
    {    
        //Feed properties parser with the variables to be read
        base::io::PropertiesParser prop;
        prop.registerPropertiesVar( "E",                E );
        prop.registerPropertiesVar( "nu",               nu );
        prop.registerPropertiesVar( "ubar1",             ubar1 );
        prop.registerPropertiesVar( "ubar2",             ubar2 );
        prop.registerPropertiesVar( "ubar3",             ubar3 );
        prop.registerPropertiesVar( "maxIter",          maxIter );
        prop.registerPropertiesVar( "tolerance",        tolerance );

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

    // find base name from mesh file
    const std::string baseName = "euler";

    const double lambda = mat::Lame::lambda( E, nu );
    const double mu     = mat::Lame::mu(     E, nu );

    boost::array<double,dim> ubar;
    {
        const boost::array<double,3> aux = {{ ubar1, ubar2, ubar3 }};
        for ( unsigned d = 0; d < dim; d++ ) ubar[d] = aux[d];
    }

    const AnalyticEulerTensor<dim> analyticEuler( lambda, mu, ubar );

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

    Mesh mesh;
    {
        std::ifstream smf( meshFile.c_str() );
        base::io::smf::readMesh( smf, mesh );
    }

    // quadrature objects for volume and surface
    typedef base::Quadrature<kernelDegEstimate,shape> Quadrature;
    Quadrature quadrature;

    // Create a field
    const unsigned    doFSize = dim;
    typedef base::fe::Basis<shape,fieldDeg>        FEBasis;
    typedef base::Field<FEBasis,doFSize>           Field;
    typedef Field::DegreeOfFreedom                 DoF;
    Field displacement;

    // generate DoFs from mesh
    base::dof::generate<FEBasis>( mesh, displacement );

    // constrain the boundary
    {
        base::mesh::MeshBoundary meshBoundary;
        meshBoundary.create( mesh.elementsBegin(), mesh.elementsEnd() );

        base::dof::constrainBoundary<FEBasis>( meshBoundary.begin(),
                                               meshBoundary.end(),
                                               mesh, displacement,
                                               boost::bind( &dirichletBC<dim,
                                                            Field::DegreeOfFreedom>,
                                                            _1, _2 ) );
        
    }

    // Bind the fields together
    typedef base::asmb::FieldBinder<Mesh,Field> FieldBinder;
    FieldBinder fieldBinder( mesh, displacement );
    typedef FieldBinder::TupleBinder<1,1>::Type FTB;

    // matrix kernel
    typedef mat::hypel::NeoHookeanCompressible Material;
    Material material( lambda, mu );
    typedef HyperElasticEuler<Material,FTB::Tuple> HyperElastic;
    HyperElastic hyperElastic( material );
            
    // Number the degrees of freedom
    const std::size_t numDofs =
        base::dof::numberDoFsConsecutively( displacement.doFsBegin(), displacement.doFsEnd() );
    std::cout << "# Number of dofs " << numDofs << std::endl;

    // write a vtk file
    writeVTKFile( baseName, 0, mesh, displacement );

    //----------------------------------------------------------------------
    // Nonlinear iterations
    //----------------------------------------------------------------------
    unsigned iter = 0;
    while ( iter < maxIter ) {

        std::cout << iter << "  ";
        
        // Create a solver object
        typedef base::solver::Eigen3           Solver;
        Solver solver( numDofs );

        // Residual forces
        base::asmb::computeResidualForces<FTB>( quadrature, solver,
                                                fieldBinder,
                                                hyperElastic );
            
        // Compute element stiffness matrices and assemble them
        base::asmb::stiffnessMatrixComputation<FTB>( quadrature, solver,
                                                     fieldBinder,
                                                     hyperElastic,
                                                     iter > 0 );

        // Body force
        base::asmb::bodyForceComputation<FTB>( quadrature, solver, fieldBinder,
                                               boost::bind( &AnalyticEulerTensor<dim>::force,
                                                            &analyticEuler, _1 ) );

        // Finalise assembly
        solver.finishAssembly();

        // norm of residual 
        const double conv1 = solver.norm();
        std::cout << conv1 << "  ";

        // convergence via residual norm
        if ( conv1 < tolerance * E ) { // note the tolerance multiplier
            std::cout << std::endl;
            break;
        }

        // Solve
        //solver.choleskySolve();
        solver.superLUSolve();
            
        // distribute results back to dofs
        base::dof::addToDoFsFromSolver( solver, displacement, iter > 0 );

        // write a vtk file
        writeVTKFile( baseName, iter+1, mesh, displacement );
        
        // norm of displacement increment
        const double conv2 = solver.norm();
        std::cout << conv2 << std::endl;
        iter++;
            
        // convergence via increment
        if ( conv2 < tolerance ) break;
    }
    // Finished non-linear iterations
    //----------------------------------------------------------------------
    
    // warning
    if ( iter == maxIter ) {
        std::cout << "# (WW) Solution has not converged within "
                  << maxIter << " iterations \n";
    }
    
    // Finished load steps
    //--------------------------------------------------------------------------

    //--------------------------------------------------------------------------
    // compute L2-error
    std::cout << "L2-error = "
              << base::post::errorComputation<0>(
                  quadrature, mesh, displacement,
                  boost::bind( &AnalyticEulerTensor<dim>::solution, 
                               &analyticEuler, _1 ) )
              << '\n';


    return 0;
}