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
127 a.resize(order.size());
128 a = b;
129#endif
130 return a;
131}
132
133template List<label> combineList(List<List<label >>& doubleList);
134
135
136// Using the Eigen library, using the SVD decomposition method to solve the
137// matrix pseudo-inverse, the default error er is 0
138Eigen::MatrixXd pinv_eigen_based(Eigen::MatrixXd& origin, const float er)
139{
140 // perform svd decomposition
141 Eigen::JacobiSVD<Eigen::MatrixXd> svd_holder(origin,
142 Eigen::ComputeThinU | Eigen::ComputeThinV);
143 // Build SVD decomposition results
144 Eigen::MatrixXd U = svd_holder.matrixU();
145 Eigen::MatrixXd V = svd_holder.matrixV();
146 Eigen::MatrixXd D = svd_holder.singularValues();
147 // Build the S matrix
148 Eigen::MatrixXd S(V.cols(), U.cols());
149 S.setZero();
150
151 for (unsigned int i = 0; i < D.size(); ++i)
152 {
153 if (D(i, 0) > er)
154 {
155 S(i, i) = 1 / D(i, 0);
156 }
157 else
158 {
159 S(i, i) = 0;
160 }
161 }
162
163 return V * S * U.transpose();
164}
165
166
167Eigen::MatrixXd invertMatrix(Eigen::MatrixXd& matrixToInvert,
168 const word inversionMethod)
169{
170 Info << "Inversion method : " << inversionMethod << endl;
171
172 if (inversionMethod == "pinv_eigen_based")
173 {
174 return pinv_eigen_based(matrixToInvert);
175 }
176 else if (inversionMethod == "direct")
177 {
178 return matrixToInvert.inverse();
179 }
180 else if (inversionMethod == "fullPivLu")
181 {
182 return matrixToInvert.fullPivLu().inverse();
183 }
184 else if (inversionMethod == "partialPivLu")
185 {
186 return matrixToInvert.partialPivLu().inverse();
187 }
188 else if (inversionMethod == "householderQr")
189 {
190 return matrixToInvert.householderQr().solve(Eigen::MatrixXd::Identity(
191 matrixToInvert.rows(), matrixToInvert.cols()));
192 }
193 else if (inversionMethod == "colPivHouseholderQr")
194 {
195 return matrixToInvert.colPivHouseholderQr().inverse();
196 }
197 else if (inversionMethod == "fullPivHouseholderQr")
198 {
199 return matrixToInvert.fullPivHouseholderQr().inverse();
200 }
201 else if (inversionMethod == "completeOrthogonalDecomposition")
202 {
203 return matrixToInvert.completeOrthogonalDecomposition().pseudoInverse();
204 }
205 else if (inversionMethod == "jacobiSvd")
206 {
207 return matrixToInvert.jacobiSvd(Eigen::ComputeThinU |
208 Eigen::ComputeThinV).solve(Eigen::MatrixXd::Identity(matrixToInvert.rows(),
209 matrixToInvert.cols()));
210 }
211 else if (inversionMethod == "llt")
212 {
213 return matrixToInvert.llt().solve(Eigen::MatrixXd::Identity(
214 matrixToInvert.rows(), matrixToInvert.cols()));
215 }
216 else if (inversionMethod == "ldlt")
217 {
218 Eigen::LLT<Eigen::MatrixXd> lltOfA(matrixToInvert);
219 return lltOfA.solve(Eigen::MatrixXd::Identity(matrixToInvert.rows(),
220 matrixToInvert.cols()));
221 }
222 else if (inversionMethod == "bdcSvd")
223 {
224 return matrixToInvert.bdcSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(
225 Eigen::MatrixXd::Identity(matrixToInvert.rows(), matrixToInvert.cols()));
226 }
227 else
228 {
229 Info << "Unkwown inversion method, solving with : completeOrthogonalDecomposition"
230 << endl;
231 return matrixToInvert.completeOrthogonalDecomposition().pseudoInverse();
232 }
233}
234
235
236}
Header file of the ITHACAstream class, it contains the implementation of several methods for input ou...
Header file of the ITHACAutilities namespace.
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.
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.