solver.cpp 9.36 KB
Newer Older
1
#include <inmost.h>
Dmitry Bagaev's avatar
Dmitry Bagaev committed
2
#include "SolverMaster.h"
igor's avatar
igor committed
3
#include "../Misc/utils.h"
4
#if defined(USE_SOLVER)
5

Dmitry Bagaev's avatar
Dmitry Bagaev committed
6
namespace INMOST {
Kirill Terekhov's avatar
Kirill Terekhov committed
7

Dmitry Bagaev's avatar
Dmitry Bagaev committed
8 9 10 11
    int *Solver::argc = NULL;
    char ***Solver::argv = NULL;
    bool Solver::is_initialized = false;
    bool Solver::is_finalized = false;
Dmitry Bagaev's avatar
Dmitry Bagaev committed
12
    std::vector<SolverParameters> Solver::parameters = std::vector<SolverParameters>();
13 14 15
	
	void Solver::SetParameterEnum(std::string name, INMOST_DATA_ENUM_TYPE value) {SetParameter(name,to_string(value));}
	void Solver::SetParameterReal(std::string name, INMOST_DATA_REAL_TYPE value) {SetParameter(name,to_string(value));}
16

Dmitry Bagaev's avatar
Dmitry Bagaev committed
17
    Solver::Solver(std::string solverName, std::string prefix, INMOST_MPI_Comm _comm) {
Dmitry Bagaev's avatar
Dmitry Bagaev committed
18
        std::string lowerName = string_to_lower(solverName);
Dmitry Bagaev's avatar
Dmitry Bagaev committed
19
        this->solver = SolverMaster::getSolver(solverName);
Dmitry Bagaev's avatar
Dmitry Bagaev committed
20
        this->prefix = string_to_lower(prefix);
Dmitry Bagaev's avatar
Dmitry Bagaev committed
21
        solver->SetCommunicator(_comm);
Dmitry Bagaev's avatar
Dmitry Bagaev committed
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
        //TODO find easiest way
        bool parametersFound = false;
        if (Solver::parameters.size() > 0) {
            for (solver_parameters_iterator_t parameters = Solver::parameters.end() - 1; parameters >= Solver::parameters.begin(); parameters--) {
                if ((*parameters).solverName == lowerName && (*parameters).solverPrefix == (this->prefix)) {
                    solver->Setup(argc, argv, *parameters);
                    parametersFound = true;
                    break;
                }
            }
        }
        if (!parametersFound) {
            SolverParameters emptyParameters(lowerName, this->prefix, "");
            solver->Setup(argc, argv, emptyParameters);
        }

Dmitry Bagaev's avatar
Dmitry Bagaev committed
38
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
39

Dmitry Bagaev's avatar
Dmitry Bagaev committed
40
    Solver::Solver(const Solver &other) {
Dmitry Bagaev's avatar
Dmitry Bagaev committed
41 42
        this->solver = SolverMaster::getSolver(other.solver->SolverName());
        this->solver->Copy(other.solver);
Dmitry Bagaev's avatar
Dmitry Bagaev committed
43 44
        this->prefix = other.prefix;
        solver->SetCommunicator(other.solver->GetCommunicator());
Dmitry Bagaev's avatar
Dmitry Bagaev committed
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
        //TODO find easiest way
        bool parametersFound = false;
        if (Solver::parameters.size() > 0) {
            for (solver_parameters_iterator_t parameters = Solver::parameters.end() - 1; parameters >= Solver::parameters.begin(); parameters--) {
                if ((*parameters).solverName == other.solver->SolverName() && (*parameters).solverPrefix == (this->prefix)) {
                    solver->Setup(argc, argv, *parameters);
                    parametersFound = true;
                    break;
                }
            }
        }
        if (!parametersFound) {
            SolverParameters emptyParameters(other.solver->SolverName(), this->prefix, "");
            solver->Setup(argc, argv, emptyParameters);
        }
Dmitry Bagaev's avatar
Dmitry Bagaev committed
60
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
61

Dmitry Bagaev's avatar
Dmitry Bagaev committed
62 63
    Solver &Solver::operator=(const Solver &other) {
        if (this != &other) {
Dmitry Bagaev's avatar
Dmitry Bagaev committed
64 65 66 67 68
            this->solver->SetCommunicator(other.solver->GetCommunicator());
            this->prefix = other.prefix;
            this->solver->Assign(other.solver);
        }
        return *this;
Kirill Terekhov's avatar
Kirill Terekhov committed
69 70
    }

Dmitry Bagaev's avatar
Dmitry Bagaev committed
71 72 73
    std::string Solver::SolverName() const {
        return solver->SolverName();
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
74

Dmitry Bagaev's avatar
Dmitry Bagaev committed
75 76 77
    std::string Solver::SolverPrefix() const {
        return prefix;
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
78

Dmitry Bagaev's avatar
Dmitry Bagaev committed
79 80 81 82 83
    void Solver::Initialize(int *argc, char ***argv, const char *database) {
        Solver::argc = argc;
        Solver::argv = argv;
        Solver::is_initialized = true;
        Solver::is_finalized = false;
Kirill Terekhov's avatar
Kirill Terekhov committed
84
#if defined(USE_MPI)
Dmitry Bagaev's avatar
Dmitry Bagaev committed
85 86 87 88 89
        {
            int flag = 0;
            int ierr = 0;
            MPI_Initialized(&flag);
            if (!flag) {
Dmitry Bagaev's avatar
Dmitry Bagaev committed
90 91
                ierr = MPI_Init(argc, argv);
                if (ierr != MPI_SUCCESS) {
Dmitry Bagaev's avatar
Dmitry Bagaev committed
92 93 94 95
                    std::cout << __FILE__ << ":" << __LINE__ << "problem in MPI_Init" << std::endl;
                }
            }
        }
Kirill Terekhov's avatar
Kirill Terekhov committed
96
#endif
Dmitry Bagaev's avatar
Dmitry Bagaev committed
97
        Solver::parseXMLDatabase(database);
Dmitry Bagaev's avatar
Dmitry Bagaev committed
98 99
        Sparse::CreateRowEntryType();
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
100

Dmitry Bagaev's avatar
Dmitry Bagaev committed
101 102 103
    void Solver::Finalize() {
        Sparse::DestroyRowEntryType();
#if defined(USE_MPI)
Dmitry Bagaev's avatar
Dmitry Bagaev committed
104 105 106 107 108 109
        {
            int flag = 0;
            MPI_Finalized(&flag);
            if (!flag) {
                MPI_Finalize();
            }
Dmitry Bagaev's avatar
Dmitry Bagaev committed
110
        }
Kirill Terekhov's avatar
Kirill Terekhov committed
111
#endif
Dmitry Bagaev's avatar
Dmitry Bagaev committed
112 113 114
        Solver::is_finalized = true;
        Solver::is_initialized = false;
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
115

Dmitry Bagaev's avatar
Dmitry Bagaev committed
116 117 118
    bool Solver::isInitialized() {
        return is_initialized;
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
119

Dmitry Bagaev's avatar
Dmitry Bagaev committed
120 121 122
    bool Solver::isFinalized() {
        return is_finalized;
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
123

Dmitry Bagaev's avatar
Dmitry Bagaev committed
124
    void Solver::SetMatrix(Sparse::Matrix &A, bool ModifiedPattern, bool OldPreconditioner) {
Dmitry Bagaev's avatar
Dmitry Bagaev committed
125 126
        solver->SetMatrix(A, ModifiedPattern, OldPreconditioner);
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
127

Dmitry Bagaev's avatar
Dmitry Bagaev committed
128 129 130 131 132 133 134
    bool Solver::Solve(INMOST::Sparse::Vector &RHS, INMOST::Sparse::Vector &SOL) {
        if (!solver->isMatrixSet()) throw MatrixNotSetInSolver;
        if (RHS.GetCommunicator() != solver->GetCommunicator() ||
            SOL.GetCommunicator() != solver->GetCommunicator())
            throw DifferentCommunicatorInSolver;
        INMOST_DATA_ENUM_TYPE vbeg, vend;
        RHS.GetInterval(vbeg, vend);
Dmitry Bagaev's avatar
Dmitry Bagaev committed
135 136
        if (RHS.Size() != SOL.Size()) {
            if (SOL.Size() == 0) {
Dmitry Bagaev's avatar
Dmitry Bagaev committed
137 138
                SOL.SetInterval(vbeg, vend);
                for (Sparse::Vector::iterator ri = SOL.Begin(); ri != SOL.End(); ++ri) *ri = 0.0;
Dmitry Bagaev's avatar
Dmitry Bagaev committed
139 140 141 142
            } else throw InconsistentSizesInSolver;
        }
        return solver->Solve(RHS, SOL);
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
143

Dmitry Bagaev's avatar
Dmitry Bagaev committed
144
    bool Solver::Clear() {
Dmitry Bagaev's avatar
Dmitry Bagaev committed
145 146
        return solver->Clear();
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
147

Dmitry Bagaev's avatar
Dmitry Bagaev committed
148 149 150 151 152 153
    std::string Solver::GetParameter(std::string name) const {
        return solver->GetParameter(name);
    }

    void Solver::SetParameter(std::string name, std::string value) {
        return solver->SetParameter(name, value);
Dmitry Bagaev's avatar
Dmitry Bagaev committed
154
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
155

156
    INMOST_DATA_ENUM_TYPE Solver::Iterations() const {
Dmitry Bagaev's avatar
Dmitry Bagaev committed
157 158
        return solver->Iterations();
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
159

160
    INMOST_DATA_REAL_TYPE Solver::Residual() const {
Dmitry Bagaev's avatar
Dmitry Bagaev committed
161 162
        return solver->Residual();
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
163

Dmitry Bagaev's avatar
Dmitry Bagaev committed
164 165 166
    const std::string Solver::ReturnReason() const {
        return solver->ReturnReason();
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
167

Dmitry Bagaev's avatar
Dmitry Bagaev committed
168 169 170 171 172 173 174 175 176 177 178 179 180
    INMOST_DATA_REAL_TYPE Solver::Condest(INMOST_DATA_REAL_TYPE tol, unsigned int maxits) {
        if (!solver->isMatrixSet()) throw MatrixNotSetInSolver;
        return solver->Condest(tol, maxits);
    }

    bool Solver::isSolverAvailable(std::string name) {
        return SolverMaster::isSolverAvailable(name);
    }

    std::vector<std::string> Solver::getAvailableSolvers() {
        return SolverMaster::getAvailableSolvers();
    }

Dmitry Bagaev's avatar
Dmitry Bagaev committed
181 182 183 184
    Solver::~Solver() {
        solver->Finalize();
        delete solver;
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
185

Dmitry Bagaev's avatar
Dmitry Bagaev committed
186
    void Solver::parseXMLDatabase(const char *xml_database) {
187
        if (xml_database == NULL || xml_database[0] == '\0') return;
Dmitry Bagaev's avatar
Dmitry Bagaev committed
188 189 190 191 192

        std::ifstream input;
        input.open(xml_database);

        if (input.fail()) {
Kirill Terekhov's avatar
Kirill Terekhov committed
193
            std::cout << __FILE__ << ":" << __LINE__ << ": XML database file " << xml_database << " not found." << std::endl;
Dmitry Bagaev's avatar
Dmitry Bagaev committed
194 195 196 197 198 199 200 201 202
            return;
        }

        XMLReader reader(std::string(xml_database), input);

        try {
            XMLReader::XMLTree root = reader.ReadXML();

            if (root.tag.name != "SolverParameters") {
Kirill Terekhov's avatar
Kirill Terekhov committed
203
                std::cout << __FILE__ << ":" << __LINE__ <<  ": Bad XML database file " << xml_database << "!" << std::endl;
Dmitry Bagaev's avatar
Dmitry Bagaev committed
204 205 206 207 208 209 210 211 212 213 214 215
                return;
            }

            for (xml_reader_tree_iterator_t solver = root.children.begin(); solver < root.children.end(); solver++) {
                std::string solverName = string_to_lower((*solver).tag.name);
                std::string internalFile = "";

                if ((*solver).tag.attributes.size() != 0) {
                    for (xml_reader_attrib_iterator_t attr = (*solver).tag.attributes.begin(); attr < (*solver).tag.attributes.end(); attr++) {
                        if ((*attr).name == "File" || (*attr).name == "file" || (*attr).name == "FILE") {
                            internalFile = (*attr).value;
                        }
Dmitry Bagaev's avatar
Dmitry Bagaev committed
216
                    }
Dmitry Bagaev's avatar
Dmitry Bagaev committed
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248
                }

                if ((*solver).children.size() == 0) {
                    //Internal solver
                    parameters.push_back(SolverParameters(solverName, "", internalFile));
                } else {
                    //Inner solver
                    for (xml_reader_tree_iterator_t prefix = (*solver).children.begin(); prefix < (*solver).children.end(); prefix++) {
                        internalFile = "";
                        std::string solverPrefix = string_to_lower((*prefix).tag.name);

                        if ((*prefix).tag.attributes.size() != 0) {
                            for (xml_reader_attrib_iterator_t attr = (*prefix).tag.attributes.begin(); attr < (*prefix).tag.attributes.end(); attr++) {
                                if ((*attr).name == "File" || (*attr).name == "file" || (*attr).name == "FILE") {
                                    internalFile = (*attr).value;
                                }
                            }
                        }

                        SolverParameters prefix_p = SolverParameters(solverName, solverPrefix, internalFile);

                        for (xml_reader_tree_iterator_t p = (*prefix).children.begin(); p < (*prefix).children.end(); p++) {

                            if ((*p).tag.attributes.size() == 1) {
                                if ((*p).tag.attributes[0].name == "value" || (*p).tag.attributes[0].name == "Value") {
                                    prefix_p.parameters.push_back(std::make_pair((*p).tag.name, (*p).tag.attributes[0].value));
                                }
                            }
                        }

                        parameters.push_back(prefix_p);

Dmitry Bagaev's avatar
Dmitry Bagaev committed
249
                    }
Dmitry Bagaev's avatar
Dmitry Bagaev committed
250

Dmitry Bagaev's avatar
Dmitry Bagaev committed
251
                }
Dmitry Bagaev's avatar
Dmitry Bagaev committed
252

Dmitry Bagaev's avatar
Dmitry Bagaev committed
253
            }
Dmitry Bagaev's avatar
Dmitry Bagaev committed
254 255 256

        } catch (...) {
            std::cout << __FILE__ << ": Error while parsing xml database file" << std::endl;
Dmitry Bagaev's avatar
Dmitry Bagaev committed
257
        }
Dmitry Bagaev's avatar
Dmitry Bagaev committed
258

Dmitry Bagaev's avatar
Dmitry Bagaev committed
259
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
260

261 262
}

igor's avatar
igor committed
263
#endif //USE_SOLVER