Loading...
Searching...
No Matches
POD_example_00002.cpp
1/*---------------------------------------------------------------------------*\
2 *
3 * bitpit
4 *
5 * Copyright (C) 2015-2021 OPTIMAD engineering Srl
6 *
7 * -------------------------------------------------------------------------
8 * License
9 * This file is part of bitpit.
10 *
11 * bitpit is free software: you can redistribute it and/or modify it
12 * under the terms of the GNU Lesser General Public License v3 (LGPL)
13 * as published by the Free Software Foundation.
14 *
15 * bitpit is distributed in the hope that it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
18 * License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with bitpit. If not, see <http://www.gnu.org/licenses/>.
22 *
23\*---------------------------------------------------------------------------*/
24
39#include <array>
40#if BITPIT_ENABLE_MPI
41#include <mpi.h>
42#endif
43
44#include "pod.hpp"
45#include "bitpit_patchkernel.hpp"
46#include "bitpit_voloctree.hpp"
47
48using namespace bitpit;
49
53void run(int rank, int nProcs)
54{
55 if (rank==0)
56 std::cout<< "0. Compute POD ..." << std::endl;
58 POD pod;
59
61 for (int i=1; i<11; i++)
62 pod.addSnapshot("./data", "test."+std::to_string(i));
63
65 pod.setMeshType(POD::MeshType::VOLOCTREE);
66 pod.setStaticMesh(true);
67 pod.setWriteMode(POD::WriteMode::DEBUG);
68 pod.setMemoryMode(POD::MemoryMode::MEMORY_NORMAL);
69 pod.setModeCount(9);
70
71 pod.setDirectory("pod");
72 pod.setName("pod.test.solver");
73
75 pod.run();
76
77 if (rank==0)
78 std::cout<< "1. Restore POD ..." << std::endl;
79
81 POD podr;
82
84 podr.setDirectory("pod");
85 podr.setName("pod.test.solver");
86 podr.restore();
87
88 if (rank==0)
89 std::cout<< "2. Read snapshot for reconstruction ..." << std::endl;
90
91#if BITPIT_ENABLE_MPI
92 VolumeKernel* meshr = new VolOctree(MPI_COMM_NULL);
93#else
94 VolumeKernel* meshr = new VolOctree();
95#endif
96 {
97 int dumpBlock = (nProcs > 1) ? rank : -1;
98 std::string filename = "./data/test.0.mesh";
99 IBinaryArchive binaryReader(filename, dumpBlock);
100 meshr->restore(binaryReader.getStream());
101 binaryReader.close();
102 }
103
104 pod::PODField fieldr, reconr;
105 std::size_t nf;
106
107 int dumpBlock = (nProcs > 1) ? rank : -1;
108 std::string filename = "./data/test.0.data";
109 IBinaryArchive binaryReader(filename, dumpBlock);
110 std::istream &dataStream = binaryReader.getStream();
111
113 fieldr.mask = std::unique_ptr<PiercedStorage<bool>>(new PiercedStorage<bool>(1, &meshr->getCells()));
114 fieldr.mask->restore(dataStream);
115
117 std::size_t nsf;
118 utils::binary::read(dataStream, nsf);
119 std::vector<std::string> namesf;
120 namesf.resize(nsf);
121 for (std::size_t i = 0; i <nsf; ++i){
122 utils::binary::read(dataStream, namesf[i]);
123 }
124
125 fieldr.scalar = std::unique_ptr<pod::ScalarStorage>(new pod::ScalarStorage(nsf, &meshr->getCells()));
126 fieldr.scalar->restore(dataStream);
127
129 std::size_t nvf;
130 utils::binary::read(dataStream, nvf);
131 std::vector<std::array<std::string,3>> namevf;
132 namevf.resize(nvf);
133 for (std::size_t i = 0; i < nvf; ++i){
134 utils::binary::read(dataStream, namevf[i]);
135 }
136
137 fieldr.vector = std::unique_ptr<pod::VectorStorage>(new pod::VectorStorage(nvf, &meshr->getCells()));
138 fieldr.vector->restore(dataStream);
139 binaryReader.close();
140
141 nf=nsf+nvf;
142
144 pod.setSensorMask(*(fieldr.mask));
145
147 pod.reconstructFields(fieldr,reconr);
148
149 if (rank==0){
150 std::cout<< ">> N modes:" << pod.getModeCount() << std::endl;
151
152 std::cout<< ">> Reconstruction coeffs:" << std::endl;
153 for (std::size_t i = 0; i < nf; ++i)
154 std::cout<< pod.getReconstructionCoeffs()[i] << std::endl;
155 }
156
157
159 PiercedStorage<double> gfield0(nsf+3*nvf+1, &meshr->getCells(), PiercedSyncMaster::SyncMode::SYNC_MODE_JOURNALED);
160 PiercedStorage<double> gfieldAdapt(nsf+3*nvf+1, &meshr->getCells(), PiercedSyncMaster::SyncMode::SYNC_MODE_JOURNALED);
161 std::unordered_set<long> targetCells;
162
163 std::map<std::string, std::size_t> fields;
164
165 for (Cell & cell : meshr->getCells()){
166 long id = cell.getId();
167 for (std::size_t ifield=0; ifield<nsf; ifield++){
168 gfield0.at(id, ifield) = fieldr.scalar->at(id, ifield);
169 gfieldAdapt.at(id, ifield) = fieldr.scalar->at(id, ifield);
170 }
171
172 for (std::size_t ifield=0; ifield<nvf; ifield++){
173 for (std::size_t j=0; j<3; j++){
174 gfield0.at(id, ifield*3+nsf+j) = fieldr.vector->at(id, ifield)[j];
175 gfieldAdapt.at(id, ifield*3+nsf+j) = fieldr.vector->at(id, ifield)[j];
176 }
177
178 }
179 if (fieldr.mask->at(id)){
180 targetCells.insert(id);
181 gfield0.at(id, nsf+3*nvf) = fieldr.mask->at(id);
182 gfieldAdapt.at(id, nsf+3*nvf) = fieldr.mask->at(id);
183 }
184 }
185
186 for (std::size_t ifield=0; ifield<nsf; ifield++){
187 fields[namesf[ifield]] = ifield;
188 }
189 for (std::size_t ifield=0; ifield<nvf; ifield++){
190 for (std::size_t j=0; j<3; j++){
191 fields[namevf[ifield][j]] = ifield*3+nsf+j;
192 }
193 }
194
195 pod.reconstructFields(gfield0, meshr, fields, &targetCells);
196
197 if (rank==0){
198 std::cout<< " " << std::endl;
199 std::cout<< ">> Reconstruction coeffs hybrid interface:" << std::endl;
200 for (std::size_t i = 0; i < nf; ++i)
201 std::cout<< pod.getReconstructionCoeffs()[i] << std::endl;
202
203 std::cout<< " " << std::endl;
204 std::cout<< ">> Reconstruction error hybrid interface" << std::endl;
205 double maxerr = 0.0;
206 for (Cell & cell : meshr->getCells()){
207 long id = cell.getId();
208 for (std::size_t i = 0; i < nsf; ++i)
209 maxerr = std::max(maxerr, std::abs(gfield0.at(id, i) - fieldr.scalar->at(id, i)));
210 for (std::size_t i = 0; i < nvf; ++i){
211 for (std::size_t j=0; j<3; j++)
212 maxerr = std::max(maxerr, std::abs(gfield0.at(id, nsf+3*i+j) - fieldr.vector->at(id, i)[j]));
213 }
214 }
215 std::cout<< ">> Max error :" << maxerr << std::endl;
216
217 }
218
219
222 long nCells = meshr->getCellCount();
223 log::cout() << std::endl;
224 log::cout() << ">> Marking the cells to adapt... " << std::endl;
225
226 for (int i = 0; i < 100; ++i) {
227 long cellId = rand() % nCells * 2;
228 if (!meshr->getCells().exists(cellId)) {
229 continue;
230 }
231
232 for (auto neighId : meshr->findCellNeighs(cellId)) {
233 meshr->markCellForRefinement(neighId);
234 }
235 }
236
237 for (int i = 0; i < 50; ++i) {
238 long cellId = rand() % nCells * 2;
239 if (!meshr->getCells().exists(cellId)) {
240 continue;
241 }
242
243 if (fieldr.mask->at(cellId)){
244 meshr->markCellForCoarsening(cellId);
245 for (auto neighId : meshr->findCellNeighs(cellId)) {
246 if (fieldr.mask->at(neighId))
247 meshr->markCellForCoarsening(neighId);
248 }
249 }
250 }
251
252 log::cout() << std::endl;
253 log::cout() << ">> Initial number of cells... " << nCells << std::endl;
254
256 {
257
258 std::vector<adaption::Info> preadaptInfo = meshr->adaptionPrepare(true);
259
261 for (adaption::Info & info : preadaptInfo){
262 for (long & id : info.previous){
263 oldData.insert(id, std::vector<double>(nsf+3*nvf+1, 0.0));
264 for (std::size_t i=0; i<nsf+3*nvf+1; i++)
265 oldData[id][i] = gfield0.at(id,i);
266 }
267 }
268
269 std::vector<adaption::Info> adaptInfo = meshr->adaptionAlter(true);
270
271 nCells = meshr->getCellCount();
272 log::cout() << ">> Final number of cells... " << nCells << std::endl;
273
274 for (adaption::Info & info : adaptInfo){
275 if (info.type == adaption::Type::TYPE_RENUMBERING){
276 for (std::size_t i=0; i<nsf+3*nvf+1; i++){
277 gfield0.at(info.current[0],i) = oldData[info.previous[0]][i];
278 gfieldAdapt.at(info.current[0],i) = oldData[info.previous[0]][i];
279 }
280 }
281 if (info.type == adaption::Type::TYPE_REFINEMENT){
282 for (long & id : info.current){
283 for (std::size_t i=0; i<nsf+3*nvf+1; i++){
284 gfield0.at(id,i) = oldData[info.previous[0]][i];
285 gfieldAdapt.at(id,i) = oldData[info.previous[0]][i];
286 }
287 }
288 }
289 if (info.type == adaption::Type::TYPE_COARSENING){
290 for (std::size_t i=0; i<nsf+3*nvf+1; i++){
291 gfield0.at(info.current[0], i) = 0.0;
292 gfieldAdapt.at(info.current[0], i) = 0.0;
293 }
294 for (long & id : info.previous){
295 for (std::size_t i=0; i<nsf+3*nvf; i++){
296 gfield0.at(info.current[0],i) += oldData[id][i] / info.previous.size();
297 gfieldAdapt.at(info.current[0],i) += oldData[id][i] / info.previous.size();
298 }
299 gfield0.at(info.current[0], nsf+3*nvf) = std::max(gfield0.at(info.current[0], nsf+3*nvf), oldData[id][nsf+3*nvf]);
300 gfieldAdapt.at(info.current[0], nsf+3*nvf) = std::max(gfieldAdapt.at(info.current[0], nsf+3*nvf), oldData[id][nsf+3*nvf]);
301 }
302 }
303 }
304
305 meshr->adaptionCleanup();
306
307 }
308
312 targetCells.clear();
313 for (Cell & cell : meshr->getCells()){
314 long id = cell.getId();
315 if (gfield0.at(id, nsf+3*nvf))
316 targetCells.insert(id);
317 }
318
321 pod.setStaticMesh(false);
322 pod.reconstructFields(gfield0, meshr, fields, &targetCells);
323
324 if (rank==0){
325 std::cout<< " " << std::endl;
326 std::cout<< ">> Reconstruction coeffs hybrid interface:" << std::endl;
327 for (std::size_t i = 0; i < nf; ++i)
328 std::cout<< pod.getReconstructionCoeffs()[i] << std::endl;
329
330 std::cout<< " " << std::endl;
331 std::cout<< ">> Reconstruction error hybrid interface" << std::endl;
332 double maxerr = 0.0;
333 for (Cell & cell : meshr->getCells()){
334 long id = cell.getId();
335 for (std::size_t i = 0; i < nsf+3*nvf; ++i)
336 maxerr = std::max(maxerr, std::abs(gfield0.at(id, i) - gfieldAdapt.at(id, i)));
337 }
338 std::cout<< ">> Max error :" << maxerr << std::endl;
339
340 }
341
342}
343
348int main(int argc, char *argv[])
349{
350#if BITPIT_ENABLE_MPI
351 MPI_Init(&argc,&argv);
352#endif
353
354 int nProcs;
355 int rank;
356
357#if BITPIT_ENABLE_MPI
358 MPI_Comm_size(MPI_COMM_WORLD, &nProcs);
359 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
360#else
361 nProcs = 1;
362 rank = 0;
363#endif
364
366 try {
367 run(rank, nProcs);
368 } catch (const std::exception &exception) {
369 log::cout() << exception.what();
370 exit(1);
371 }
372
373#if BITPIT_ENABLE_MPI
374 MPI_Finalize();
375#endif
376
377}
The Cell class defines the cells.
Definition cell.hpp:42
Input binary archive.
The POD (Proper Orthogonal Decomposition) class provides an interface for defining POD object.
Definition pod.hpp:41
std::size_t getModeCount()
Definition pod.cpp:315
void run()
Definition pod.cpp:836
void setMeshType(MeshType type)
Definition pod.cpp:390
void setStaticMesh(bool flag)
Definition pod.cpp:483
void setSensorMask(const PiercedStorage< bool > &mask, VolumeKernel *mesh=nullptr)
Definition pod.cpp:672
void setMemoryMode(MemoryMode mode)
Definition pod.cpp:505
void setDirectory(const std::string &directory)
Definition pod.cpp:180
void reconstructFields(pod::PODField &field, pod::PODField &recon)
Definition pod.cpp:1631
void setWriteMode(WriteMode mode)
Definition pod.cpp:576
void restore()
Definition pod.cpp:864
void setModeCount(std::size_t nmodes)
Definition pod.cpp:304
void setName(const std::string &name)
Definition pod.cpp:160
std::vector< std::vector< double > > getReconstructionCoeffs()
Definition pod.cpp:800
void addSnapshot(const std::string &directory, const std::string &name)
Definition pod.cpp:208
void markCellForRefinement(long id)
PiercedVector< Cell > & getCells()
std::vector< adaption::Info > adaptionPrepare(bool trackAdaption=true)
void markCellForCoarsening(long id)
void restore(std::istream &stream, bool reregister=false)
virtual long getCellCount() const
std::vector< adaption::Info > adaptionAlter(bool trackAdaption=true, bool squeezeStorage=false)
Metafunction for generating a pierced storage.
Metafunction for generating a pierced vector.
The VolOctree defines a Octree patch.
Definition voloctree.hpp:37
The VolumeKernel class provides an interface for defining volume patches.
void read(std::istream &stream, std::vector< bool > &container)
Logger & cout(log::Level defaultSeverity, log::Visibility defaultVisibility)
Definition logger.cpp:1705
Logger & info(log::Visibility defaultVisibility)
Definition logger.cpp:1847
The Info struct defines the information associated to an adaption.
Definition adaption.hpp:63
The PODfield structure is used to store the fields inside POD classes.
std::unique_ptr< pod::ScalarStorage > scalar
std::unique_ptr< PiercedStorage< bool > > mask
std::unique_ptr< pod::VectorStorage > vector
--- layout: doxygen_footer ---