Loading...
Searching...
No Matches
27Offline.C
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-------------------------------------------------------------------------------
12License
13 This file is part of ITHACA-FV
14 ITHACA-FV is free software: you can redistribute it and/or modify
15 it under the terms of the GNU Lesser General Public License as published by
16 the Free Software Foundation, either version 3 of the License, or
17 (at your option) any later version.
18 ITHACA-FV is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU Lesser General Public License for more details.
22 You should have received a copy of the GNU Lesser General Public License
23 along with ITHACA-FV. If not, see <http://www.gnu.org/licenses/>.
24Description
25 Example of the hyperreduction of the Smagorinsky term in a ROM
26SourceFiles
27 27SmagorinskyHyperreduction.C
28\*---------------------------------------------------------------------------*/
29
30#include "27Offline.H"
31
32
33tutorial27_offline::tutorial27_offline(int argc, char* argv[]):
34 m_parameters(new StoredParameters(argc, argv)),
35 m_UnsteadyNSTurb(new UnsteadyNSTurb(m_parameters)),
36 nModesU(m_parameters->get_nModes()["U"]),
37 interpolatedField(m_parameters->get_DEIMInterpolatedField()),
38 nModesHR(m_parameters->get_nModes()[interpolatedField]),
39 nMagicPoints(m_parameters->get_nMagicPoints()),
40 magicPoints(m_parameters->get_magicPoints())
41{
42 if (!ITHACAutilities::containsSubstring(interpolatedField, "reduced"))
43 {
44 Info << "Error: Hyperreduction InterpolatedField not valid: " << interpolatedField << endl;
45 Info << "Expects reducedFullStressFunction or reducedNut" << endl;
46 abort();
47 }
48}
49
50
51void tutorial27_offline::decompose()
52{
53 ITHACAPOD::PODTemplate<volVectorField> podU(m_parameters, "U");
54
55 // compute spatial modes, temporal modes and cov matrix for U
56 podU.getModes(spatialModesU, temporalModesU, temporalModesUSimulation, covMatrixU);
57
58 // get mean of U field computed when getModes was used
59 meanU = new volVectorField(podU.get_mean());
60 m_parameters->set_meanU(*meanU);
61
62 volVectorField template_HRInterpField(interpolatedField, m_UnsteadyNSTurb->initSmagFunction());
63 m_parameters->set_template_field_fullStressFunction(template_HRInterpField);
64
65 if (ITHACAutilities::containsSubstring(interpolatedField, "fullStressFunction"))
66 {
67 bool mgPoints_0_Neighborhoods_1 = true;
68
69 if (m_parameters->get_HRMethod() == "DEIM")
70 {
71 TurbDiffusionHyperreduction<volVectorField,volVectorField,volVectorField>*
72 turbDiffHR_fullStressFunction = new TurbDiffusionHyperreduction<volVectorField,volVectorField,volVectorField>
73 (m_parameters, mgPoints_0_Neighborhoods_1, template_HRInterpField, template_HRInterpField, meanU, spatialModesU);
74
75 turbDiffHR_fullStressFunction->computeTurbDiffusionHyperreduction();
76 }
77 else if (m_parameters->get_HRMethod() == "ECP")
78 {
79 volScalarField template_HRSnapshotsField(m_parameters->get_HRSnapshotsField(),
80 m_UnsteadyNSTurb->initProjSmagFunction());
81 TurbDiffusionHyperreduction<volVectorField,volVectorField,volScalarField>*
82 turbDiffHR_projFullStressFunction = new TurbDiffusionHyperreduction<volVectorField,volVectorField,volScalarField>
83 (m_parameters, mgPoints_0_Neighborhoods_1, template_HRInterpField, template_HRSnapshotsField, meanU, spatialModesU);
84
85 turbDiffHR_projFullStressFunction->computeTurbDiffusionHyperreduction();
86 }
87 }
88 else if (ITHACAutilities::containsSubstring(interpolatedField, "nut"))
89 {
90 bool mgPoints_0_Neighborhoods_1 = false;
91 volScalarField template_HRInterpField(interpolatedField, m_UnsteadyNSTurb->initNutFunction());
92 volScalarField template_HRSnapshotsField(m_UnsteadyNSTurb->initProjSmagFromNutFunction());
93 TurbDiffusionHyperreduction<volVectorField,volScalarField,volScalarField>*
94 turbDiffHR_nut = new TurbDiffusionHyperreduction<volVectorField,volScalarField,volScalarField>
95 (m_parameters, mgPoints_0_Neighborhoods_1, template_HRInterpField, template_HRSnapshotsField, meanU, spatialModesU);
96
97 turbDiffHR_nut->computeTurbDiffusionHyperreduction();
98 }
99 else
100 {
101 Info << "Error: Hyperreduction InterpolatedField not valid: " << interpolatedField << endl;
102 Info << "Expects reducedFullStressFunction or reducedNut" << endl;
103 abort();
104 }
105}
106
107
108void tutorial27_offline::project()
109{
110 word folder_DEIM = m_parameters->get_folder_DEIM();
111
112 int d = 3;
113 Eigen::MatrixXd K_proj(nModesU, d*(nMagicPoints+1));
114 Eigen::MatrixXd K_DEIM = m_parameters->get_K_DEIM();
115
116 if (ITHACAutilities::containsSubstring(interpolatedField, "fullStressFunction"))
117 {
118
119 word file_projK_DEIM = folder_DEIM + "projected_K_DEIM_" + std::to_string(nModesU) + ".npy";
120 bool exist_projK_DEIM = ITHACAutilities::check_file(file_projK_DEIM);
121
122 if (!exist_projK_DEIM)
123 {
124
125 const volScalarField weight = sqrt(m_parameters->get_volume());
126 volVectorField meanSmag(m_parameters->get_meanVectorDEIM());
127
128 for (int i = 0 ; i < nModesU ; i++)
129 {
130 Eigen::VectorXd K_proj_line_i(d*nMagicPoints);
131 if (m_parameters->get_HRMethod() == "DEIM")
132 {
133 volVectorField weightedSpatialModesU_OF = weight * spatialModesU[i];
134 Eigen::VectorXd weightedSpatialModesU = Foam2Eigen::field2Eigen(weightedSpatialModesU_OF);
135 K_proj_line_i = K_DEIM.transpose() * weightedSpatialModesU;
136 }
137 else if (m_parameters->get_HRMethod() == "ECP")
138 {
139 K_proj_line_i = K_DEIM.row(i);
140 }
141
142 K_proj.row(i).head(d*nMagicPoints) = K_proj_line_i;
143 K_proj(i, d*nMagicPoints) = ITHACAutilities::dot_product_L2(spatialModesU[i], meanSmag);
144 K_proj(i, d*nMagicPoints + 1) = 0.0;
145 K_proj(i, d*nMagicPoints + 2) = 0.0;
146 }
147
148 cnpy::save(K_proj, file_projK_DEIM);
149 m_parameters->set_projected_K_DEIM(K_proj);
150 }
151 else
152 {
153 cnpy::load(K_proj, file_projK_DEIM);
154 m_parameters->set_projected_K_DEIM(K_proj);
155 }
156 }
157 else if (ITHACAutilities::containsSubstring(interpolatedField, "nut"))
158 {
159 Eigen::Tensor<double, 3> xi_onMagicPts(nModesU + 1, nMagicPoints + 1, nModesU);
160 word xi_onMagicPts_file("xi_onMagicPts.npy");
161 bool exist_xi_onMagicPts = ITHACAutilities::check_file(folder_DEIM + xi_onMagicPts_file);
162
163 if (!exist_xi_onMagicPts)
164 {
165 volScalarField meanNut = m_parameters->get_meanScalarDEIM();
166
167 if (m_parameters->get_HRMethod() == "DEIM")
168 {
169 K_DEIM.array().colwise() /= Foam2Eigen::field2Eigen(m_parameters->get_volume()).array().sqrt();
170 for (label i = 0; i < nModesU; i++)
171 {
172 for (label q = 0; q < nModesU+1; q++)
173 {
174 for (label j = 0; j < nMagicPoints; j++)
175 {
176 Eigen::VectorXd K_DEIM_col_j = K_DEIM.col(j);
177 if (q == 0)
178 {
179 xi_onMagicPts(q,j,i) = ITHACAutilities::dot_product_L2(spatialModesU[i],
180 m_UnsteadyNSTurb->diffusion(Foam2Eigen::Eigen2field(meanNut,K_DEIM_col_j),*meanU));
181 }
182 else
183 {
184 xi_onMagicPts(q,j,i) = ITHACAutilities::dot_product_L2(spatialModesU[i],
185 m_UnsteadyNSTurb->diffusion(Foam2Eigen::Eigen2field(meanNut,K_DEIM_col_j),spatialModesU[q-1]));
186 }
187 }
188 if (q == 0)
189 {
190 xi_onMagicPts(q,nMagicPoints,i) = ITHACAutilities::dot_product_L2(spatialModesU[i],
191 m_UnsteadyNSTurb->diffusion(meanNut,*meanU));
192 }
193 else
194 {
195 xi_onMagicPts(q,nMagicPoints,i) = ITHACAutilities::dot_product_L2(spatialModesU[i],
196 m_UnsteadyNSTurb->diffusion(meanNut,spatialModesU[q-1]));
197 }
198 }
199 }
200 }
201 else if (m_parameters->get_HRMethod() == "ECP")
202 {
203 PtrList<volTensorField> defTensorModesOnMgPts = m_parameters->get_deformationTensorOfModesOnMagicPoints();
204 labelList localMagicPoints(m_parameters->get_localMagicPoints());
205
206 for (label i = 0; i < nModesU; i++)
207 {
208 for (label q = 0; q < nModesU+1; q++)
209 {
210 for (label j = 0; j < nMagicPoints; j++)
211 {
212 label row_id = ((pow(max(i,q-1),2)+3*max(i,q-1))/2 + min(i+1,q)) * (m_parameters->get_ECPAlgo()!="Global");
213 xi_onMagicPts(q,j,i) = -2*K_DEIM(row_id,j)*(dev(defTensorModesOnMgPts[i+1][localMagicPoints[j]])
214 && dev(defTensorModesOnMgPts[q][localMagicPoints[j]]));
215 }
216
217 if (q == 0)
218 {
219 xi_onMagicPts(q,nMagicPoints,i) = -fvc::domainIntegrate(m_UnsteadyNSTurb->
220 projDiffusionIBP(meanNut, *meanU, spatialModesU[i])).value();
221 }
222 else
223 {
224 xi_onMagicPts(q,nMagicPoints,i) = -fvc::domainIntegrate(m_UnsteadyNSTurb->
225 projDiffusionIBP(meanNut, spatialModesU[q-1], spatialModesU[i])).value();
226 }
227 }
228 }
229 }
230 cnpy::save(xi_onMagicPts, folder_DEIM + xi_onMagicPts_file);
231 m_parameters->set_xi_onMagicPts(xi_onMagicPts);
232 }
233 else
234 {
235 cnpy::load(xi_onMagicPts, folder_DEIM + xi_onMagicPts_file);
236 m_parameters->set_xi_onMagicPts(xi_onMagicPts);
237 }
238 }
239}
240
static GeometricField< scalar, PatchField, GeoMesh > Eigen2field(GeometricField< scalar, PatchField, GeoMesh > &field, Eigen::VectorXd &eigen_vector, bool correctBC=true)
Convert a vector in Eigen format into an OpenFOAM scalar GeometricField.
Definition Foam2Eigen.C:533
static Eigen::MatrixXd field2Eigen(GeometricField< Type, PatchField, GeoMesh > &field)
Convert a vector OpenFOAM field into an Eigen Vector.
Class that contains all parameters of the stochastic POD.
void computeTurbDiffusionHyperreduction()
Compute the hyperreduction by callng other methods.
Implementation of a parametrized full order unsteady NS problem and preparation of the reduced matr...
T max(Eigen::SparseMatrix< T > &mat, label &ind_row, label &ind_col)
Find the maximum of a sparse Matrix (Useful for DEIM).
T min(Eigen::SparseMatrix< T > &mat, label &ind_row, label &ind_col)
Find the minimum of a sparse Matrix (Useful for DEIM).
bool containsSubstring(std::string contain, std::string contained)
Returns true if contained is a substring of contain, false otherwise.
double dot_product_L2(const volVectorField &v, const volVectorField &w)
Perform the L2 dot product of v and w.
Definition ITHACAnorm.C:182
bool check_file(std::string fileName)
Function that returns true if a file exists.