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 // perform svd decomposition
140 Eigen::JacobiSVD<Eigen::MatrixXd> svd_holder(origin, Eigen::ComputeThinU | Eigen::ComputeThinV);
141 // Build SVD decomposition results
142 Eigen::MatrixXd U = svd_holder.matrixU();
143 Eigen::MatrixXd V = svd_holder.matrixV();
144 Eigen::MatrixXd D = svd_holder.singularValues();
145
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 S(i, i) = 1 / D(i, 0);
154 } else {
155 S(i, i) = 0;
156 }
157 }
158 return V * S * U.transpose();
159}
160
161
162Eigen::MatrixXd invertMatrix(Eigen::MatrixXd& matrixToInvert, const word inversionMethod){
163
164 Info << "Inversion method : " << inversionMethod << endl;
165 if(inversionMethod == "pinv_eigen_based"){
166 return pinv_eigen_based(matrixToInvert);
167 }
168 else if(inversionMethod == "direct"){
169 return matrixToInvert.inverse();
170 }
171 else if(inversionMethod == "fullPivLu"){
172 return matrixToInvert.fullPivLu().inverse();
173 }
174 else if(inversionMethod == "partialPivLu"){
175 return matrixToInvert.partialPivLu().inverse();
176 }
177 else if(inversionMethod == "householderQr"){
178 return matrixToInvert.householderQr().solve(Eigen::MatrixXd::Identity(matrixToInvert.rows(), matrixToInvert.cols()));
179 }
180 else if(inversionMethod == "colPivHouseholderQr"){
181 return matrixToInvert.colPivHouseholderQr().inverse();
182 }
183 else if(inversionMethod == "fullPivHouseholderQr"){
184 return matrixToInvert.fullPivHouseholderQr().inverse();
185 }
186 else if(inversionMethod == "completeOrthogonalDecomposition"){
187 return matrixToInvert.completeOrthogonalDecomposition().pseudoInverse();
188 }
189 else if(inversionMethod == "jacobiSvd")
190 {
191 return matrixToInvert.jacobiSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(Eigen::MatrixXd::Identity(matrixToInvert.rows(), matrixToInvert.cols()));
192 }
193 else if(inversionMethod == "llt")
194 {
195 return matrixToInvert.llt().solve(Eigen::MatrixXd::Identity(matrixToInvert.rows(), matrixToInvert.cols()));
196 }
197 else if(inversionMethod == "ldlt")
198 {
199 Eigen::LLT<Eigen::MatrixXd> lltOfA(matrixToInvert);
200 return lltOfA.solve(Eigen::MatrixXd::Identity(matrixToInvert.rows(), matrixToInvert.cols()));
201 }
202 else if(inversionMethod == "bdcSvd")
203 {
204 return matrixToInvert.bdcSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(Eigen::MatrixXd::Identity(matrixToInvert.rows(), matrixToInvert.cols()));
205 }
206 else{
207 Info << "Unkwown inversion method, solving with : completeOrthogonalDecomposition" << endl;
208 return matrixToInvert.completeOrthogonalDecomposition().pseudoInverse();
209 }
210}
211
212
213}
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...
fvMesh & mesh
Mesh object defined locally.
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))