Loading...
Searching...
No Matches
ITHACAutilities.C
Go to the documentation of this file.
1/*---------------------------------------------------------------------------*\
2 ██╗████████╗██╗ ██╗ █████╗ ██████╗ █████╗ ███████╗██╗ ██╗
3 ██║╚══██╔══╝██║ ██║██╔══██╗██╔════╝██╔══██╗ ██╔════╝██║ ██║
4 ██║ ██║ ███████║███████║██║ ███████║█████╗█████╗ ██║ ██║
5 ██║ ██║ ██╔══██║██╔══██║██║ ██╔══██║╚════╝██╔══╝ ╚██╗ ██╔╝
6 ██║ ██║ ██║ ██║██║ ██║╚██████╗██║ ██║ ██║ ╚████╔╝
7 ╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝ ╚═╝ ╚═══╝
8
9 * In real Time Highly Advanced Computational Applications for Finite Volumes
10 * Copyright (C) 2017 by the ITHACA-FV authors
11-------------------------------------------------------------------------------
12
13License
14 This file is part of ITHACA-FV
15
16 ITHACA-FV is free software: you can redistribute it and/or modify
17 it under the terms of the GNU Lesser General Public License as published by
18 the Free Software Foundation, either version 3 of the License, or
19 (at your option) any later version.
20
21 ITHACA-FV is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 GNU Lesser General Public License for more details.
25
26 You should have received a copy of the GNU Lesser General Public License
27 along with ITHACA-FV. If not, see <http://www.gnu.org/licenses/>.
28
29\*---------------------------------------------------------------------------*/
30
31#include "ITHACAutilities.H"
32#include "ITHACAstream.H"
33#include "ITHACAparameters.H"
34#include "turbulentTransportModel.H"
35
38
39// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
40
41namespace ITHACAutilities
42{
43
44Eigen::MatrixXd rand(label rows, label cols, double min,
45 double max)
46{
47 std::srand(static_cast<long unsigned int>
48 (std::chrono::high_resolution_clock::now().time_since_epoch().count()));
49 Eigen::MatrixXd matr = Eigen::MatrixXd::Random(rows, cols);
50 matr = (matr.array() + 1) / 2;
51 matr = matr.array() * (max - min);
52 matr = matr.array() + min;
53 return matr;
54}
55
56Eigen::MatrixXd rand(label rows, Eigen::MatrixXd minMax)
57{
58 std::srand(static_cast<long unsigned int>
59 (std::chrono::high_resolution_clock::now().time_since_epoch().count()));
60 label cols = minMax.rows();
61 Eigen::MatrixXd matr = Eigen::MatrixXd::Random(rows, cols);
62 matr = (matr.array() + 1) / 2;
63
64 for (label i = 0; i < cols; i++)
65 {
66 matr.col(i) = matr.col(i).array() * (minMax(i, 1) - minMax(i, 0));
67 matr.col(i) = matr.col(i).array() + (minMax(i, 0));
68 }
69
70 return matr;
71}
72
73
74bool isInteger(double ratio)
75{
76 bool checkResult = 0;
77
78 if (abs(round(ratio) - ratio) < std::sqrt(SMALL))
79 {
80 checkResult = true;
81 }
82 else
83 {
84 checkResult = false;
85 }
86
87 return checkResult;
88}
89
91{
92 bool checkTurb;
94 auto& tur =
95 para->mesh.lookupObject<incompressible::turbulenceModel>("turbulenceProperties");
96
97 if (tur.type() == "Stokes" || tur.type() == "Maxwell"
98 || tur.type() == "laminarModel")
99 {
100 checkTurb = false;
101 }
102 else
103 {
104 checkTurb = true;
105 }
106
107 return checkTurb;
108}
109
110template<typename T>
111List<T> combineList(List<List<T >> & doubleList)
112{
113 List<T> a = ListListOps::combine<List<T >> (doubleList,
114 accessOp<List<T >> ());
115#if OPENFOAM >= 1812
116 inplaceUniqueSort(a);
117#else
118 labelList order;
119 uniqueOrder(a, order);
120 List<T> b(order.size());
121
122 for (label i = 0; i < order.size(); ++i)
123 {
124 b[i] = a[order[i]];
125 }
126 a.resize(order.size());
127 a = b;
128#endif
129 return a;
130}
131
132template List<label> combineList(List<List<label >> & doubleList);
133
134
135// Using the Eigen library, using the SVD decomposition method to solve the
136// matrix pseudo-inverse, the default error er is 0
137Eigen::MatrixXd pinv_eigen_based(Eigen::MatrixXd& origin, const float er)
138{
139 // perform svd decomposition
140 Eigen::JacobiSVD<Eigen::MatrixXd> svd_holder(origin,
141 Eigen::ComputeThinU | Eigen::ComputeThinV);
142 // Build SVD decomposition results
143 Eigen::MatrixXd U = svd_holder.matrixU();
144 Eigen::MatrixXd V = svd_holder.matrixV();
145 Eigen::MatrixXd D = svd_holder.singularValues();
146 // Build the S matrix
147 Eigen::MatrixXd S(V.cols(), U.cols());
148 S.setZero();
149
150 for (unsigned int i = 0; i < D.size(); ++i)
151 {
152 if (D(i, 0) > er)
153 {
154 S(i, i) = 1 / D(i, 0);
155 }
156 else
157 {
158 S(i, i) = 0;
159 }
160 }
161
162 return V * S * U.transpose();
163}
164
165
166Eigen::MatrixXd invertMatrix(Eigen::MatrixXd& matrixToInvert,
167 const word inversionMethod)
168{
169 Info << "Inversion method : " << inversionMethod << endl;
170
171 if (inversionMethod == "pinv_eigen_based")
172 {
173 return pinv_eigen_based(matrixToInvert);
174 }
175 else if (inversionMethod == "direct")
176 {
177 return matrixToInvert.inverse();
178 }
179 else if (inversionMethod == "fullPivLu")
180 {
181 return matrixToInvert.fullPivLu().inverse();
182 }
183 else if (inversionMethod == "partialPivLu")
184 {
185 return matrixToInvert.partialPivLu().inverse();
186 }
187 else if (inversionMethod == "householderQr")
188 {
189 return matrixToInvert.householderQr().solve(Eigen::MatrixXd::Identity(
190 matrixToInvert.rows(), matrixToInvert.cols()));
191 }
192 else if (inversionMethod == "colPivHouseholderQr")
193 {
194 return matrixToInvert.colPivHouseholderQr().inverse();
195 }
196 else if (inversionMethod == "fullPivHouseholderQr")
197 {
198 return matrixToInvert.fullPivHouseholderQr().inverse();
199 }
200 else if (inversionMethod == "completeOrthogonalDecomposition")
201 {
202 return matrixToInvert.completeOrthogonalDecomposition().pseudoInverse();
203 }
204 else if (inversionMethod == "jacobiSvd")
205 {
206 return matrixToInvert.jacobiSvd(Eigen::ComputeThinU |
207 Eigen::ComputeThinV).solve(Eigen::MatrixXd::Identity(matrixToInvert.rows(),
208 matrixToInvert.cols()));
209 }
210 else if (inversionMethod == "llt")
211 {
212 return matrixToInvert.llt().solve(Eigen::MatrixXd::Identity(
213 matrixToInvert.rows(), matrixToInvert.cols()));
214 }
215 else if (inversionMethod == "ldlt")
216 {
217 Eigen::LLT<Eigen::MatrixXd> lltOfA(matrixToInvert);
218 return lltOfA.solve(Eigen::MatrixXd::Identity(matrixToInvert.rows(),
219 matrixToInvert.cols()));
220 }
221 else if (inversionMethod == "bdcSvd")
222 {
223 return matrixToInvert.bdcSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(
224 Eigen::MatrixXd::Identity(matrixToInvert.rows(), matrixToInvert.cols()));
225 }
226 else
227 {
228 Info << "Unkwown inversion method, solving with : completeOrthogonalDecomposition"
229 << endl;
230 return matrixToInvert.completeOrthogonalDecomposition().pseudoInverse();
231 }
232}
233
234
235}
Header file of the ITHACAstream class, it contains the implementation of several methods for input ou...
Header file of the ITHACAutilities namespace.
ITHACAparameters * para
Definition NLsolve.H:40
Class for the definition of some general parameters, the parameters must be defined from the file ITH...
static ITHACAparameters * getInstance()
Gets an instance of ITHACAparameters, to be used if the instance is already existing.
volScalarField & D
Namespace to implement some useful assign operation of OF fields.
bool isInteger(double ratio)
This function checks if ratio is an integer.
Eigen::MatrixXd invertMatrix(Eigen::MatrixXd &matrixToInvert, const word inversionMethod)
Invert a matrix given the method name in the ITHACAdict.
Eigen::MatrixXd pinv_eigen_based(Eigen::MatrixXd &origin, const float er)
Using the Eigen library, using the SVD decomposition method to solve the matrix pseudo-inverse,...
Eigen::MatrixXd rand(label rows, label cols, double min, double max)
Generates random matrix with random values in an interval.
bool isTurbulent()
This function checks if the case is turbulent.
List< T > combineList(List< List< T > > &doubleList)
Combine a list of list into a single list with unique elements.
volVectorField & U
label i
Definition pEqn.H:46
volScalarField S(IOobject("S", runTime.timeName(), mesh, IOobject::NO_READ, IOobject::AUTO_WRITE), T.mesh(), dimensionedScalar("zero", dimensionSet(0, 0, -1, 1, 0, 0, 0), 0))