<commit_before>/*
   Clique: a scalable implementation of the multifrontal algorithm

   Copyright (C) 2011 <NAME>, <NAME>, and 
   The University of Texas at Austin
 
   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
 
   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "clique.hpp"
using namespace elemental;

void Usage()
{
    std::cout << "PanelLDL <nx> <ny> <nz> <cutoff>\n"
              << "<nx>: size of panel in x direction\n"
              << "<ny>: size of panel in y direction\n"
              << "<nz>: size of panel in z direction\n"
              << "<cutoff>: minimum required leaf size\n" << std::endl;
}

int ReorderedIndexRecursion
( int x, int y, int z, int nx, int ny, int nz,
  int stepsLeft, int cutoff, int offset );

int ReorderedIndex
( int x, int y, int z, int nx, int ny, int nz,
  int minBalancedDepth, int cutoff );

void CountLocalTreeSize
( int nxSub, int nySub, int nz, int cutoff, int& numSupernodes );

void FillOrigStruct
( int nx, int ny, int nz, int cutoff, mpi::Comm comm, int log2CommSize,
  clique::symbolic::LocalSymmOrig& localOrig, 
  clique::symbolic::DistSymmOrig& distOrig );

void FillDistOrigStruct
( int nx, int ny, int nz, int& nxSub, int& nySub, int& xOffset, int& yOffset, 
  int cutoff, mpi::Comm comm, int log2CommSize,
  clique::symbolic::DistSymmOrig& SOrig );

void FillLocalOrigStruct
( int nx, int ny, int nz, int nxSub, int nySub, int xOffset, int yOffset, 
  int cutoff, int log2CommSize,
  clique::symbolic::LocalSymmOrig& SOrig );

int
main( int argc, char* argv[] )
{
    clique::Initialize( argc, argv );
    mpi::Comm comm = mpi::COMM_WORLD;
    const int commRank = mpi::CommRank( comm );
    const int commSize = mpi::CommSize( comm );
    typedef std::complex<double> F;

    // Ensure that we have a power of two number of processes
    unsigned temp = commSize;
    unsigned log2CommSize = 0;
    while( temp >>= 1 )
        ++log2CommSize;
    if( 1u<<log2CommSize != commSize )
    {
        if( commRank == 0 )
        {
            std::cerr << "Must use a power of two number of processes" 
                      << std::endl;
        }
        clique::Finalize();
        return 0;
    }

    if( argc < 5 )
    {
        if( commRank == 0 )        
            Usage();
        clique::Finalize();
        return 0;
    }

    int argNum = 1;
    const int nx = atoi( argv[argNum++] );
    const int ny = atoi( argv[argNum++] );
    const int nz = atoi( argv[argNum++] );
    const int cutoff = atoi( argv[argNum++] );
    if( commRank == 0 )
        std::cout << "(nx,ny,nz)=(" << nx << "," << ny << "," << nz << ")\n"
                  << "cutoff=" << cutoff << std::endl;

    try
    {
        // Fill the distributed portion of the original structure
        clique::symbolic::LocalSymmOrig localSOrig;
        clique::symbolic::DistSymmOrig distSOrig;
        FillOrigStruct
        ( nx, ny, nz, cutoff, comm, log2CommSize, localSOrig, distSOrig );

        // Call the symbolic factorization routine
        clique::symbolic::DistSymmFact distS;
        clique::symbolic::LocalSymmFact localS;
        clique::symbolic::SymmetricFactorization
        ( localSOrig, distSOrig, localS, distS, true );

        // Directly initialize the frontal matrices with the original 
        // sparse matrix (for now, use an original matrix equal to identity)
        clique::numeric::LocalSymmFact<F> localL;
        localL.supernodes.resize( localS.supernodes.size() );
        for( int s=0; s<localS.supernodes.size(); ++s )
        {
            const clique::symbolic::LocalSymmFactSupernode& symbSN  =
                localS.supernodes[s];
            clique::numeric::LocalSymmFactSupernode<F>& sn = 
                localL.supernodes[s];

            const int frontSize = symbSN.size+symbSN.lowerStruct.size();
            sn.front.ResizeTo( frontSize, frontSize );
            sn.front.SetToZero();
            Matrix<F> frontTL;
            frontTL.View( sn.front, 0, 0, symbSN.size, symbSN.size );
            frontTL.SetToIdentity();
            basic::Scal( (F)2, frontTL );
        }
        clique::numeric::DistSymmFact<F> distL;
        distL.mode = clique::MANY_RHS;
        distL.supernodes.resize( log2CommSize+1 );
        for( int s=0; s<log2CommSize+1; ++s )
        {
            const clique::symbolic::DistSymmFactSupernode& symbSN = 
                distS.supernodes[s];
            clique::numeric::DistSymmFactSupernode<F>& sn = distL.supernodes[s];

            sn.front2d.SetGrid( *symbSN.grid );
            const int frontSize = symbSN.size+symbSN.lowerStruct.size();
            sn.front2d.ResizeTo( frontSize, frontSize );
            sn.front2d.SetToZero();
            DistMatrix<F,MC,MR> frontTL;
            frontTL.View( sn.front2d, 0, 0, symbSN.size, symbSN.size );
            frontTL.SetToIdentity();
            basic::Scal( (F)2, frontTL );
        }

        // Call the numerical factorization routine
        clique::numeric::LDL( TRANSPOSE, localS, distS, localL, distL );

        // Redistribute to 1d for fast solves with few right-hand sides
        clique::numeric::SetSolveMode( distL, clique::FEW_RHS );

        // Set up the properly ordered RHS and call a solve routine
        const int localHeight1d = 
            distS.supernodes.back().localOffset1d + 
            distS.supernodes.back().localSize1d;
        Matrix<F> localX( localHeight1d, 5 );
        localX.SetToRandom();
        Matrix<F> localXCopy = localX;
        clique::numeric::LDLSolve
        ( TRANSPOSE, localS, distS, localL, distL, localX, true );
        if( commRank == 0 )
        {
            basic::Axpy( (F)-0.5, localXCopy, localX );
            std::cout << "Error norm: " << advanced::Norm( localX ) 
                      << std::endl;
        }
    }
    catch( std::exception& e )
    {
#ifndef RELEASE
        elemental::DumpCallStack();
        clique::DumpCallStack();
#endif
        std::ostringstream msg;
        msg << "Process " << commRank << " caught message:\n"
            << e.what() << "\n";
        std::cerr << msg.str() << std::endl;
    }

    clique::Finalize();
    return 0;
}<commit_msg>Adding timers to the driver.<commit_after>/*
   Clique: a scalable implementation of the multifrontal algorithm

   Copyright (C) 2011 <NAME>, <NAME>, and 
   The University of Texas at Austin
 
   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
 
   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "clique.hpp"
using namespace elemental;

void Usage()
{
    std::cout << "PanelLDL <nx> <ny> <nz> <cutoff>\n"
              << "<nx>: size of panel in x direction\n"
              << "<ny>: size of panel in y direction\n"
              << "<nz>: size of panel in z direction\n"
              << "<cutoff>: minimum required leaf size\n" << std::endl;
}

int ReorderedIndexRecursion
( int x, int y, int z, int nx, int ny, int nz,
  int stepsLeft, int cutoff, int offset );

int ReorderedIndex
( int x, int y, int z, int nx, int ny, int nz,
  int minBalancedDepth, int cutoff );

void CountLocalTreeSize
( int nxSub, int nySub, int nz, int cutoff, int& numSupernodes );

void FillOrigStruct
( int nx, int ny, int nz, int cutoff, mpi::Comm comm, int log2CommSize,
  clique::symbolic::LocalSymmOrig& localOrig, 
  clique::symbolic::DistSymmOrig& distOrig );

void FillDistOrigStruct
( int nx, int ny, int nz, int& nxSub, int& nySub, int& xOffset, int& yOffset, 
  int cutoff, mpi::Comm comm, int log2CommSize,
  clique::symbolic::DistSymmOrig& SOrig );

void FillLocalOrigStruct
( int nx, int ny, int nz, int nxSub, int nySub, int xOffset, int yOffset, 
  int cutoff, int log2CommSize,
  clique::symbolic::LocalSymmOrig& SOrig );

int
main( int argc, char* argv[] )
{
    clique::Initialize( argc, argv );
    mpi::Comm comm = mpi::COMM_WORLD;
    const int commRank = mpi::CommRank( comm );
    const int commSize = mpi::CommSize( comm );
    typedef std::complex<double> F;

    // Ensure that we have a power of two number of processes
    unsigned temp = commSize;
    unsigned log2CommSize = 0;
    while( temp >>= 1 )
        ++log2CommSize;
    if( 1u<<log2CommSize != commSize )
    {
        if( commRank == 0 )
        {
            std::cerr << "Must use a power of two number of processes" 
                      << std::endl;
        }
        clique::Finalize();
        return 0;
    }

    if( argc < 5 )
    {
        if( commRank == 0 )        
            Usage();
        clique::Finalize();
        return 0;
    }

    int argNum = 1;
    const int nx = atoi( argv[argNum++] );
    const int ny = atoi( argv[argNum++] );
    const int nz = atoi( argv[argNum++] );
    const int cutoff = atoi( argv[argNum++] );
    if( commRank == 0 )
        std::cout << "(nx,ny,nz)=(" << nx << "," << ny << "," << nz << ")\n"
                  << "cutoff=" << cutoff << std::endl;

    try
    {
        // Fill the distributed portion of the original structure
        mpi::Barrier( comm );
        const double initStartTime = mpi::Time();
        clique::symbolic::LocalSymmOrig localSOrig;
        clique::symbolic::DistSymmOrig distSOrig;
        FillOrigStruct
        ( nx, ny, nz, cutoff, comm, log2CommSize, localSOrig, distSOrig );
        mpi::Barrier( comm );
        const double initStopTime = mpi::Time();
        if( commRank == 0 )
            std::cout << "Init time: " << initStopTime-initStartTime << " secs"
                      << std::endl;

        // Call the symbolic factorization routine
        const double symbFactStartTime = mpi::Time();
        clique::symbolic::DistSymmFact distS;
        clique::symbolic::LocalSymmFact localS;
        clique::symbolic::SymmetricFactorization
        ( localSOrig, distSOrig, localS, distS, true );
        mpi::Barrier( comm );
        const double symbFactStopTime = mpi::Time();
        if( commRank == 0 )
            std::cout << "Symbolic factorization time: " 
                      << symbFactStopTime-symbFactStartTime << " secs"
                      << std::endl;

        // Directly initialize the frontal matrices with the original 
        // sparse matrix (for now, use an original matrix equal to identity)
        const double fillStartTime = mpi::Time();
        clique::numeric::LocalSymmFact<F> localL;
        localL.supernodes.resize( localS.supernodes.size() );
        for( int s=0; s<localS.supernodes.size(); ++s )
        {
            const clique::symbolic::LocalSymmFactSupernode& symbSN  =
                localS.supernodes[s];
            clique::numeric::LocalSymmFactSupernode<F>& sn = 
                localL.supernodes[s];

            const int frontSize = symbSN.size+symbSN.lowerStruct.size();
            sn.front.ResizeTo( frontSize, frontSize );
            sn.front.SetToZero();
            Matrix<F> frontTL;
            frontTL.View( sn.front, 0, 0, symbSN.size, symbSN.size );
            frontTL.SetToIdentity();
            basic::Scal( (F)2, frontTL );
        }
        clique::numeric::DistSymmFact<F> distL;
        distL.mode = clique::MANY_RHS;
        distL.supernodes.resize( log2CommSize+1 );
        for( int s=0; s<log2CommSize+1; ++s )
        {
            const clique::symbolic::DistSymmFactSupernode& symbSN = 
                distS.supernodes[s];
            clique::numeric::DistSymmFactSupernode<F>& sn = distL.supernodes[s];

            sn.front2d.SetGrid( *symbSN.grid );
            const int frontSize = symbSN.size+symbSN.lowerStruct.size();
            sn.front2d.ResizeTo( frontSize, frontSize );
            sn.front2d.SetToZero();
            DistMatrix<F,MC,MR> frontTL;
            frontTL.View( sn.front2d, 0, 0, symbSN.size, symbSN.size );
            frontTL.SetToIdentity();
            basic::Scal( (F)2, frontTL );
        }
        mpi::Barrier( comm );
        const double fillStopTime = mpi::Time();
        if( commRank == 0 )
            std::cout << "Fill time: " << fillStopTime-fillStartTime
                      << " secs" << std::endl;

        // Call the numerical factorization routine
        const double factStartTime = mpi::Time();
        clique::numeric::LDL( TRANSPOSE, localS, distS, localL, distL );
        mpi::Barrier( comm );
        const double factStopTime = mpi::Time();
        if( commRank == 0 )
            std::cout << "Factorization time: " << factStopTime-factStartTime
                      << " secs" << std::endl;

        // Redistribute to 1d for fast solves with few right-hand sides
        const double redistStartTime = mpi::Time();
        clique::numeric::SetSolveMode( distL, clique::FEW_RHS );
        mpi::Barrier( comm );
        const double redistStopTime = mpi::Time();
        if( commRank == 0 )
            std::cout << "Redistribution time: " 
                      << redistStopTime-redistStartTime << " secs" << std::endl;

        // Set up the properly ordered RHS and call a solve routine
        const int localHeight1d = 
            distS.supernodes.back().localOffset1d + 
            distS.supernodes.back().localSize1d;
        Matrix<F> localX( localHeight1d, 5 );
        localX.SetToRandom();
        Matrix<F> localXCopy = localX;

        mpi::Barrier( comm );
        const double solveStartTime = mpi::Time();
        clique::numeric::LDLSolve
        ( TRANSPOSE, localS, distS, localL, distL, localX, true );
        mpi::Barrier( comm );
        const double solveStopTime = mpi::Time();
        if( commRank == 0 )
        {
            std::cout << "Solve time: " << solveStopTime-solveStartTime
                      << " secs" << std::endl;

            basic::Axpy( (F)-0.5, localXCopy, localX );
            std::cout << "Error norm: " << advanced::Norm( localX ) 
                      << std::endl;
        }
    }
    catch( std::exception& e )
    {
#ifndef RELEASE
        elemental::DumpCallStack();
        clique::DumpCallStack();
#endif
        std::ostringstream msg;
        msg << "Process " << commRank << " caught message:\n"
            << e.what() << "\n";
        std::cerr << msg.str() << std::endl;
    }

    clique::Finalize();
    return 0;
}
{'fraction_non_alphanumeric': 0.12165819526041323, 'fraction_numerical': 0.006667106739718793, 'mean_word_length': 2.3399470899470898, 'pattern_counts': {'":': 0, '<': 213, '<?xml version=': 0, '>': 47, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3697955', 'n_tokens_mistral': 4821, 'n_tokens_neox': 4620, 'n_words': 1338}