Solver2.cpp 4.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
//
// Created by Dmitri Bagaev on 22.09.16.
//

#include <Source/Solver/refactoring/solver_petsc/SolverPETSc.h>
#include <inmost_sparse.h>
#include "Solver2.h"

namespace INMOST {

    int *Solver2::argc = NULL;
    char ***Solver2::argv = NULL;
    const char *Solver2::database = NULL;
    bool Solver2::is_initialized = false;
    bool Solver2::is_finalized = false;

    Solver2::Solver2(std::string solverName, std::string prefix, INMOST_MPI_Comm _comm) {
        this->solver = SolverFactory::getSolver(solverName);
        this->prefix = prefix;

21
        solver->SetCommunicator(_comm);
22 23 24 25 26 27 28 29
        std::string solverDatabasePath = Solver2::parseDatabase(solverName);
        solver->Initialize(argc, argv, solverDatabasePath.c_str(), prefix);
    }

    Solver2::Solver2(const Solver2 &other) {
        this->solver = SolverFactory::copySolver(other.solver);
        this->prefix = other.prefix;

30 31
        solver->SetCommunicator(other.solver->GetCommunicator());
        std::string solverDatabasePath = Solver2::parseDatabase(solver->SolverName());
32 33 34 35 36
        solver->Initialize(argc, argv, solverDatabasePath.c_str(), prefix);
    }

    Solver2& Solver2::operator=(const Solver2& other) {
        if( this != &other ) {
37
            this->solver->SetCommunicator(other.solver->GetCommunicator());
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
            this->prefix = other.prefix;
            this->solver->Assign(other.solver);
        }
        return *this;
    }

    void Solver2::Initialize(int *argc, char ***argv, const char *database) {
        Solver2::argc = argc;
        Solver2::argv = argv;
        Solver2::database = database;
        Solver2::is_initialized = true;
        Solver2::is_finalized = false;
        Sparse::CreateRowEntryType();
        //Register all available solvers
#if defined(USE_SOLVER_PETSC)
        SolverFactory::registerSolver<SolverPETSc>("petsc");
#endif
    }

    void Solver2::SetMatrix(Sparse::Matrix & A, bool ModifiedPattern, bool OldPreconditioner) {
        solver->SetMatrix(A, ModifiedPattern, OldPreconditioner);
    }

    bool Solver2::Solve(INMOST::Sparse::Vector & RHS, INMOST::Sparse::Vector & SOL) {
        if( !solver->isMatrixSet()) throw MatrixNotSetInSolver;
63
        if( RHS.GetCommunicator() != solver->GetCommunicator() || SOL.GetCommunicator() != solver->GetCommunicator()) throw DifferentCommunicatorInSolver;
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
        INMOST_DATA_ENUM_TYPE vbeg,vend;
        RHS.GetInterval(vbeg,vend);
        if( RHS.Size() != SOL.Size() )
        {
            if( SOL.Size() == 0 )
            {
                SOL.SetInterval(vbeg,vend);
                for(Sparse::Vector::iterator ri = SOL.Begin(); ri != SOL.End(); ++ri) *ri = 0.0;
            }
            else throw InconsistentSizesInSolver;
        }
        return solver->Solve(RHS, SOL);
    }

    void Solver2::Finalize() {
        Sparse::DestroyRowEntryType();
        Solver2::is_finalized = true;
        Solver2::is_initialized = false;
    }

    bool Solver2::isInitialized() {
        return is_initialized;
    }

    bool Solver2::isFinalized() {
        return is_finalized;
    }

    const INMOST_DATA_ENUM_TYPE Solver2::Iterations() const {
        return solver->Iterations();
    }

    const INMOST_DATA_REAL_TYPE Solver2::Residual() const {
        return solver->Residual();
    }

    const std::string Solver2::ReturnReason() const {
        return solver->ReturnReason();
    }

104 105
    std::string Solver2::SolverName() const {
        return solver->SolverName();
106 107
    }

108
    std::string Solver2::SolverPrefix() const {
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
        return prefix;
    }

    Solver2::~Solver2() {
        solver->Finalize();
        delete solver;
    }

    std::string Solver2::parseDatabase(std::string solverName) {
        const char *name = solverName.c_str();
        if( database != NULL ) {
            FILE * f = fopen(database, "r");
            if (f != NULL) {
                char str[4096];
                while( !feof(f) && fgets(str,4096,f)) {
                    int k = 0, l;
                    for(k = 0; k < (int)strlen(str); ++k) {
                        if( str[k] == ':' ) break;
                    }
                    if( k == strlen(str) ) continue; //invalid line
                    for(l = 0; l < k; ++l) str[l] = tolower(str[l]);
                    l = (int)strlen(str)-1; // Right-trim string
                    while(l > 0 && isspace(str[l]) ) --l;
                    str[l+1] = 0;
                    l = k+1;
                    while(l < (int)strlen(str) && isspace(str[l]) ) ++l;
                    if( l == strlen(str) ) continue; //skip empty entry
                    if( !strncmp(str, name, k) ) {
                        return std::string(str+l);
                    }
                }
                fclose(f);
            }
        }
        return std::string("");
    }

}