Better bounding on topo change
[foam-extend-3.2.git] / src / POD / PODOrthoNormalBase / PODOrthoNormalBase.C
blobff2702d9481387974e57206dafe0dcd16b905daa
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | foam-extend: Open Source CFD
4    \\    /   O peration     | Version:     3.2
5     \\  /    A nd           | Web:         http://www.foam-extend.org
6      \\/     M anipulation  | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
8 License
9     This file is part of foam-extend.
11     foam-extend is free software: you can redistribute it and/or modify it
12     under the terms of the GNU General Public License as published by the
13     Free Software Foundation, either version 3 of the License, or (at your
14     option) any later version.
16     foam-extend is distributed in the hope that it will be useful, but
17     WITHOUT ANY WARRANTY; without even the implied warranty of
18     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19     General Public License for more details.
21     You should have received a copy of the GNU General Public License
22     along with foam-extend.  If not, see <http://www.gnu.org/licenses/>.
24 Class
25     PODOrthoNormalBase
27 Description
28     Establish POD ortho-normal base and interpolation coefficients give a list
29     of fields. Size of ortho-normal base is calculated from the desired
30     accuracy, e.g. 0.99-0.99999 (in energy terms)
32 \*---------------------------------------------------------------------------*/
34 #include "PODOrthoNormalBase.H"
35 #include "POD.H"
36 #include "PODEigenBase.H"
37 #include "IOmanip.H"
39 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
41 template<class Type>
42 void Foam::PODOrthoNormalBase<Type>::calcOrthoBase
44     const PtrList<GeometricField<Type, fvPatchField, volMesh> >& snapshots,
45     const scalar accuracy
48     // Calculate ortho-normal base for each component
49     PtrList<PODEigenBase> eigenBase(pTraits<Type>::nComponents);
51     const label nSnapshots = snapshots.size();
53     typename
54     powProduct<Vector<label>, pTraits<Type>::rank>::type validComponents
55     (
56         pow
57         (
58             snapshots[0].mesh().solutionD(),
59             pTraits
60             <
61                 typename powProduct<Vector<label>,
62                 pTraits<Type>::rank
63             >::type>::zero
64         )
65     );
67     label nValidCmpts = 0;
69     for (direction cmpt = 0; cmpt < pTraits<Type>::nComponents; cmpt++)
70     {
71         // Component not valid, skipping
72         if (validComponents[cmpt] == -1) continue;
74         // Create a list of snapshots
75         PtrList<volScalarField> sf(nSnapshots);
77         forAll (snapshots, i)
78         {
79             sf.set(i, new volScalarField(snapshots[i].component(cmpt)));
80         }
82         // Create eigen base
83         eigenBase.set(cmpt, new PODEigenBase(sf));
85         Info<< "Cumulative eigen-values for component " << cmpt
86             << ": " << setprecision(14)
87             << eigenBase[nValidCmpts].cumulativeEigenValues() << endl;
89         nValidCmpts++;
90     }
92     eigenBase.setSize(nValidCmpts);
94     Info << "Number of valid eigen components: " << nValidCmpts << endl;
96     label baseSize = 0;
97     for (label snapI = 0; snapI < nSnapshots; snapI++)
98     {
99         baseSize++;
101         // Get minimum cumulative eigen value for all valid components
102         scalar minCumEigen = 1.0;
104         nValidCmpts = 0;
106         for (direction cmpt = 0; cmpt < pTraits<Type>::nComponents; cmpt++)
107         {
108             // Skip invalid components
109             if (validComponents[cmpt] != -1)
110             {
111                 minCumEigen =
112                     Foam::min
113                     (
114                         minCumEigen,
115                         eigenBase[nValidCmpts].cumulativeEigenValues()[snapI]
116                     );
118                 nValidCmpts++;
119             }
120         }
122         if (minCumEigen > accuracy)
123         {
124             break;
125         }
126     }
128     Info << "Base size: " << baseSize << endl;
130     // Establish orthonormal base
131     orthoFields_.setSize(baseSize);
133     for (label baseI = 0; baseI < baseSize; baseI++)
134     {
135         GeometricField<Type, fvPatchField, volMesh>* onBasePtr
136         (
137             new GeometricField<Type, fvPatchField, volMesh>
138             (
139                 IOobject
140                 (
141                     snapshots[0].name() + "POD" + name(baseI),
142                     snapshots[0].time().timeName(),
143                     snapshots[0].mesh(),
144                     IOobject::NO_READ,
145                     IOobject::NO_WRITE
146                 ),
147                 snapshots[0].mesh(),
148                 dimensioned<Type>
149                 (
150                     "zero",
151                     snapshots[0].dimensions(),
152                     pTraits<Type>::zero
153                 )
154             )
155         );
156         GeometricField<Type, fvPatchField, volMesh>& onBase = *onBasePtr;
158         nValidCmpts = 0;
160         for (direction cmpt = 0; cmpt < pTraits<Type>::nComponents; cmpt++)
161         {
162             if (validComponents[cmpt] != -1)
163             {
164                 // Valid component, grab eigen-factors
166                 const scalarField& eigenVector =
167                     eigenBase[nValidCmpts].eigenVectors()[baseI];
168                 nValidCmpts++;
170                 volScalarField onBaseCmpt = onBase.component(cmpt);
172                 forAll (eigenVector, eigenI)
173                 {
174                     onBaseCmpt +=
175                         eigenVector[eigenI]*snapshots[eigenI].component(cmpt);
176                 }
178                 // Re-normalise ortho-normal vector
179                 onBaseCmpt /= Foam::sqrt(sumSqr(onBaseCmpt));
181                 onBase.replace(cmpt, onBaseCmpt);
182             }
183             else
184             {
185                 // Component invalid.  Grab first snapshot.
186                 onBase.replace
187                 (
188                     cmpt,
189                     snapshots[0].component(cmpt)
190                 );
191             }
192         }
194         orthoFields_.set(baseI, onBasePtr);
195     }
197     // Calculate interpolation coefficients
198     interpolationCoeffsPtr_ =
199         new RectangularMatrix<Type>(snapshots.size(), orthoFields_.size());
200     RectangularMatrix<Type>& coeffs = *interpolationCoeffsPtr_;
202     forAll (snapshots, snapshotI)
203     {
204         forAll (orthoFields_, baseI)
205         {
206             coeffs[snapshotI][baseI] =
207                 POD::projection
208                 (
209                     snapshots[snapshotI],
210                     orthoFields_[baseI]
211                 );
212         }
213     }
217 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
219 // given list of snapshots and accuracy
220 template<class Type>
221 Foam::PODOrthoNormalBase<Type>::PODOrthoNormalBase
223     const PtrList<GeometricField<Type, fvPatchField, volMesh> >& snapshots,
224     const scalar accuracy
227     orthoFields_(),
228     interpolationCoeffsPtr_(NULL)
230     calcOrthoBase(snapshots, accuracy);
234 // * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
236 template<class Type>
237 Foam::PODOrthoNormalBase<Type>::~PODOrthoNormalBase()
239     deleteDemandDrivenData(interpolationCoeffsPtr_);
243 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
246 // ************************************************************************* //