Nektar++
DriverParallelInTime.cpp
Go to the documentation of this file.
1///////////////////////////////////////////////////////////////////////////////
2//
3// File DriverParallelInTime.cpp
4//
5// For more information, please see: http://www.nektar.info
6//
7// The MIT License
8//
9// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
10// Department of Aeronautics, Imperial College London (UK), and Scientific
11// Computing and Imaging Institute, University of Utah (USA).
12//
13// Permission is hereby granted, free of charge, to any person obtaining a
14// copy of this software and associated documentation files (the "Software"),
15// to deal in the Software without restriction, including without limitation
16// the rights to use, copy, modify, merge, publish, distribute, sublicense,
17// and/or sell copies of the Software, and to permit persons to whom the
18// Software is furnished to do so, subject to the following conditions:
19//
20// The above copyright notice and this permission notice shall be included
21// in all copies or substantial portions of the Software.
22//
23// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29// DEALINGS IN THE SOFTWARE.
30//
31// Description: Driver class for the parallel-in-time solver
32//
33///////////////////////////////////////////////////////////////////////////////
34
35#include <iomanip>
36
38#include <LocalRegions/HexExp.h>
40#include <LocalRegions/PyrExp.h>
42#include <LocalRegions/SegExp.h>
43#include <LocalRegions/TetExp.h>
44#include <LocalRegions/TriExp.h>
47#include <boost/format.hpp>
48
49namespace Nektar::SolverUtils
50{
51
52/**
53 *
54 */
58 : Driver(pSession, pGraph)
59{
60}
61
62/**
63 *
64 */
66{
67 try
68 {
69 // Retrieve the type of evolution operator to use
71 m_session->GetSolverInfoAsEnum<EvolutionOperatorType>(
72 "EvolutionOperator");
73
74 m_nTimeLevel = 2; // Only two time levels currently implemented.
75
77
78 // Set the AdvectiveType tag and create EquationSystem objects.
79 switch (m_EvolutionOperator)
80 {
81 case eNonlinear:
83 break;
84 case eDirect:
86 break;
87 case eAdjoint:
89 break;
90 case eSkewSymmetric:
91 SetParallelInTimeEquationSystem("SkewSymmetric");
92 break;
93 default:
94 ASSERTL0(false, "Unrecognised evolution operator.");
95 }
96
97 // Set pointers.
99 for (size_t timeLevel = 0; timeLevel < m_nTimeLevel; timeLevel++)
100 {
101 m_EqSys[timeLevel] =
102 std::dynamic_pointer_cast<SolverUtils::UnsteadySystem>(
103 m_equ[timeLevel]);
104 }
105
106 // Set time communication parameters.
107 m_numChunks = m_comm->GetTimeComm()->GetSize();
108 m_chunkRank = m_comm->GetTimeComm()->GetRank();
109 }
110 catch (int e)
111 {
112 ASSERTL0(e == -1, "No such class class defined.");
113 out << "An error occurred during driver initialisation." << std::endl;
114 }
115}
117/**
118 *
119 */
120void DriverParallelInTime::v_Execute([[maybe_unused]] std::ostream &out)
121{
122}
123
124/**
125 * Set the ParallelInTime (coarse solver) session file
126 */
128 std::string AdvectiveType)
129{
130 // Retrieve the equation system to solve.
131 ASSERTL0(m_session->DefinesSolverInfo("EqType"),
132 "EqType SolverInfo tag must be defined.");
133 std::string vEquation = m_session->DefinesSolverInfo("SolverType")
134 ? m_session->GetSolverInfo("SolverType")
135 : m_session->GetSolverInfo("EqType");
136
137 // Check such a module exists for this equation.
138 ASSERTL0(GetEquationSystemFactory().ModuleExists(vEquation),
139 "EquationSystem '" + vEquation +
140 "' is not defined.\n"
141 "Ensure equation name is correct and module is compiled.\n");
142
143 // Set fine parallel-in-time solver.
144 m_session->SetTag("AdvectiveType", AdvectiveType);
145 m_session->SetTag("ParallelInTimeSolver", "TimeLevel0");
147 m_graph);
148
149 // Define argument for the coarse parallel-in-time solver.
150 int npx = m_session->DefinesCmdLineArgument("npx")
151 ? m_session->GetCmdLineArgument<int>("npx")
152 : 1;
153 int npy = m_session->DefinesCmdLineArgument("npy")
154 ? m_session->GetCmdLineArgument<int>("npy")
155 : 1;
156 int npz = m_session->DefinesCmdLineArgument("npz")
157 ? m_session->GetCmdLineArgument<int>("npz")
158 : 1;
159 int nsz = m_session->DefinesCmdLineArgument("nsz")
160 ? m_session->GetCmdLineArgument<int>("nsz")
161 : 1;
162 int npt = m_session->DefinesCmdLineArgument("npt")
163 ? m_session->GetCmdLineArgument<int>("npt")
164 : 1;
165
166 // Convert into string.
167 std::string npx_string = std::to_string(npx);
168 std::string npy_string = std::to_string(npy);
169 std::string npz_string = std::to_string(npz);
170 std::string nsz_string = std::to_string(nsz);
171 std::string npt_string = std::to_string(npt);
172 std::string driver_string = "Driver=" + m_session->GetSolverInfo("Driver");
173
174 // use-opt-file
175 bool useOptFile = m_session->DefinesCmdLineArgument("use-opt-file");
176 std::string optfilename = useOptFile ? m_session->GetFilenames()[0] : "";
177
178 char *argv[] = {const_cast<char *>("Solver"), // this is just a place holder
179 const_cast<char *>("--solverinfo"),
180 const_cast<char *>(driver_string.c_str()),
181 const_cast<char *>("--npx"),
182 const_cast<char *>(npx_string.c_str()),
183 const_cast<char *>("--npy"),
184 const_cast<char *>(npy_string.c_str()),
185 const_cast<char *>("--npz"),
186 const_cast<char *>(npz_string.c_str()),
187 const_cast<char *>("--nsz"),
188 const_cast<char *>(nsz_string.c_str()),
189 const_cast<char *>("--npt"),
190 const_cast<char *>(npt_string.c_str()),
191 const_cast<char *>("-f"),
192 const_cast<char *>("--use-opt-file"),
193 const_cast<char *>(optfilename.c_str()),
194 nullptr};
195
196 size_t argc = useOptFile ? 16 : 14;
197
198 // Get list of session file names.
199 std::vector<std::string> sessionFileNames;
200 for (auto &filename : m_session->GetFilenames())
201 {
202 // Remove optfile name, if necessary.
203 if (filename.substr(filename.find_last_of(".") + 1) != "opt")
204 {
205 sessionFileNames.push_back(filename);
206 }
207 }
208
209 // Set session for coarse solver.
210 for (size_t timeLevel = 1; timeLevel < m_nTimeLevel; timeLevel++)
211 {
213 argc, argv, sessionFileNames, m_session->GetComm(), timeLevel);
214
215 // Set graph for coarse solver.
218
219 // Set BndRegionOrdering (necessary for DG with periodic BC) FIXME
220 graph->SetBndRegionOrdering(m_graph->GetBndRegionOrdering());
221
222 // Set CompositeOrdering (necessary for DG with periodic BC) FIXME
223 graph->SetCompositeOrdering(m_graph->GetCompositeOrdering());
224
225 // Retrieve the equation system to solve.
226 ASSERTL0(session->DefinesSolverInfo("EqType"),
227 "EqType SolverInfo tag must be defined.");
228 auto vEquation = session->DefinesSolverInfo("SolverType")
229 ? session->GetSolverInfo("SolverType")
230 : session->GetSolverInfo("EqType");
231
232 // Check such a module exists for this equation.
233 ASSERTL0(
234 GetEquationSystemFactory().ModuleExists(vEquation),
235 "EquationSystem '" + vEquation +
236 "' is not defined.\n"
237 "Ensure equation name is correct and module is compiled.\n");
238
239 // Set coarse parallel-in-time solver.
240 session->SetTag("AdvectiveType", AdvectiveType);
241 session->SetTag("ParallelInTimeSolver",
242 "TimeLevel" + std::to_string(timeLevel));
244 vEquation, session, graph);
245 }
246}
247
248/**
249 *
250 */
252{
253 // Parallel-in-Time iteration parameters.
254 m_tolerPIT = m_session->DefinesParameter("PITToler")
255 ? m_session->GetParameter("PITToler")
256 : 1.0E-16;
257 m_iterMaxPIT = m_session->DefinesParameter("PITIterMax")
258 ? m_session->GetParameter("PITIterMax")
259 : m_numChunks;
260 m_numWindowsPIT = m_session->DefinesParameter("NumWindows")
261 ? m_session->GetParameter("NumWindows")
262 : 1;
263
264 // Other parameters.
265 m_exactSolution = m_session->DefinesParameter("ExactSolution")
266 ? m_session->GetParameter("ExactSolution")
267 : 0;
268}
269
270/**
271 *
272 */
274{
275 m_nVar = m_EqSys[0]->GetNvariables();
276
277 // Initialize fine solver.
278 if (turnoff_output)
279 {
280 for (size_t timeLevel = 0; timeLevel < m_nTimeLevel; timeLevel++)
281 {
282 m_EqSys[timeLevel]->SetInfoSteps(0);
283 m_EqSys[timeLevel]->SetCheckpointSteps(0);
284 }
285 }
286 m_EqSys[0]->DoInitialise(true);
287
288 // Initialize coarse solver(s).
289 for (size_t timeLevel = 1; timeLevel < m_nTimeLevel; timeLevel++)
290 {
291 m_EqSys[timeLevel]->DoInitialise(false);
292 }
293
294 // Initialize time stepping parameters.
298 for (size_t timeLevel = 0; timeLevel < m_nTimeLevel; timeLevel++)
299 {
300 m_timestep[timeLevel] =
301 m_EqSys[timeLevel]->EquationSystem::GetTimeStep();
302 m_nsteps[timeLevel] = m_EqSys[timeLevel]->EquationSystem::GetSteps();
303 m_npts[timeLevel] = m_EqSys[timeLevel]->EquationSystem::GetNpoints();
304 }
305
306 // Initialize errors.
308 for (size_t i = 0; i < m_nVar; ++i)
309 {
311 }
314}
315
316/**
317 *
318 */
320{
321 if (m_chunkRank == 0 && m_comm->GetSpaceComm()->GetRank() == 0)
322 {
323 for (size_t timeLevel = 0; timeLevel < m_nTimeLevel; timeLevel++)
324 {
325 std::cout << std::string(71, '=') << std::endl << std::flush;
326 std::cout << "=========================== TIME LEVEL " +
327 std::to_string(timeLevel) +
328 " INFO "
329 "========================="
330 << std::endl
331 << std::flush;
332
333 m_EqSys[timeLevel]->PrintSummary(out);
334
335 std::cout << std::endl << std::flush;
336 }
337 }
338}
339
340/**
341 *
342 */
343void DriverParallelInTime::PrintHeader(const std::string &title, const char c)
344{
345 if (m_chunkRank == m_numChunks - 1 &&
346 m_comm->GetSpaceComm()->GetRank() == 0)
347 {
348 std::cout << std::endl;
349 std::cout << std::string(43, c) << std::endl << std::flush;
350 std::cout << title << std::endl << std::flush;
351 std::cout << std::string(43, c) << std::endl << std::flush;
352 }
353}
354
355/**
356 *
357 */
359 Array<OneD, Array<OneD, NekDouble>> &array, int &convergence)
360{
361 if (m_chunkRank > 0)
362 {
363 if (!convergence)
364 {
365 m_comm->GetTimeComm()->Recv(m_chunkRank - 1, convergence);
366 for (size_t i = 0; i < m_nVar; ++i)
367 {
368 m_comm->GetTimeComm()->Recv(m_chunkRank - 1, array[i]);
369 }
370 }
371 }
372}
373
374/**
375 *
376 */
378{
379 if (m_chunkRank > 0)
380 {
381 m_comm->GetTimeComm()->Recv(m_chunkRank - 1, array);
382 }
383}
384
385/**
386 *
387 */
389 Array<OneD, Array<OneD, NekDouble>> &array, int &convergence)
390{
391 if (m_chunkRank < m_numChunks - 1)
392 {
393 m_comm->GetTimeComm()->Send(m_chunkRank + 1, convergence);
394 for (size_t i = 0; i < m_nVar; ++i)
395 {
396 m_comm->GetTimeComm()->Send(m_chunkRank + 1, array[i]);
397 }
398 }
399}
400
401/**
402 *
403 */
405{
406 if (m_chunkRank < m_numChunks - 1)
407 {
408 m_comm->GetTimeComm()->Send(m_chunkRank + 1, array);
409 }
410}
411
412/**
413 *
414 */
416 const Array<OneD, const Array<OneD, NekDouble>> &in,
418{
419 for (size_t i = 0; i < m_nVar; ++i)
420 {
421 Vmath::Vcopy(in[i].size(), in[i], 1, out[i], 1);
422 }
423}
424
425/**
426 *
427 */
429 const size_t timeLevel, Array<OneD, Array<OneD, NekDouble>> &out)
430{
431 for (size_t i = 0; i < m_nVar; ++i)
432 {
433 m_EqSys[timeLevel]->CopyFromPhysField(i, out[i]);
434 }
435}
436
437/**
438 *
439 */
441 const size_t timeLevel, const Array<OneD, const Array<OneD, NekDouble>> &in)
442{
443 for (size_t i = 0; i < m_nVar; ++i)
444 {
445 m_EqSys[timeLevel]->CopyToPhysField(i, in[i]);
446 m_EqSys[timeLevel]->UpdateFields()[i]->SetPhysState(true);
447 }
448}
449
450/**
451 *
452 */
454 const size_t timeLevel, const Array<OneD, const Array<OneD, NekDouble>> &in)
455{
456 for (size_t i = 0; i < m_nVar; ++i)
457 {
459 {
460 m_EqSys[timeLevel]->CopyToPhysField(i, in[i]);
461 }
462 m_EqSys[timeLevel]->UpdateFields()[i]->FwdTrans(
463 m_EqSys[timeLevel]->UpdateFields()[i]->GetPhys(),
464 m_EqSys[timeLevel]->UpdateFields()[i]->UpdateCoeffs());
465 }
466}
467
468/**
469 *
470 */
472 const NekDouble &time)
473{
474 for (size_t i = 0; i < m_nVar; ++i)
475 {
476 m_EqSys[timeLevel]->EvaluateExactSolution(i, m_exactsoln[i], time);
477 }
478}
479
480/**
481 *
482 */
484 const size_t iter)
485{
486 PrintHeader((boost::format("ITERATION %1%") % iter).str(), '-');
487 UpdateErrorNorm(timeLevel, true);
488 PrintErrorNorm(timeLevel, true);
489}
490
491/**
492 *
493 */
495{
496 UpdateErrorNorm(timeLevel, false);
497 PrintErrorNorm(timeLevel, false);
498}
499
500/**
501 *
502 */
503void DriverParallelInTime::UpdateErrorNorm(const size_t timeLevel,
504 const bool normalized)
505{
506 for (size_t i = 0; i < m_nVar; ++i)
507 {
508 m_vL2Errors[i] =
509 m_EqSys[timeLevel]->L2Error(i, m_exactsoln[i], normalized);
510 m_vLinfErrors[i] = m_EqSys[timeLevel]->LinfError(i, m_exactsoln[i]);
511 }
512}
513
514/**
515 *
516 */
517void DriverParallelInTime::PrintErrorNorm(const size_t timeLevel,
518 const bool normalized)
519{
520 if (m_chunkRank == m_numChunks - 1 &&
521 m_comm->GetSpaceComm()->GetRank() == 0)
522 {
523 for (size_t i = 0; i < m_nVar; ++i)
524 {
525 if (normalized)
526 {
527 std::cout << "L2 error (variable "
528 << m_EqSys[timeLevel]->GetVariable(i)
529 << ") : " << m_vL2Errors[i] << std::endl
530 << std::flush;
531 std::cout << "Linf error (variable "
532 << m_EqSys[timeLevel]->GetVariable(i)
533 << ") : " << m_vLinfErrors[i] << std::endl
534 << std::flush;
535 }
536 else
537 {
538 std::cout << "L 2 error (variable "
539 << m_EqSys[timeLevel]->GetVariable(i)
540 << ") : " << m_vL2Errors[i] << std::endl
541 << std::flush;
542 std::cout << "L inf error (variable "
543 << m_EqSys[timeLevel]->GetVariable(i)
544 << ") : " << m_vLinfErrors[i] << std::endl
545 << std::flush;
546 }
547 }
548 }
549}
550
551/**
552 *
553 */
555{
556 NekDouble L2Error = 0.0;
557 for (size_t i = 0; i < m_nVar; ++i)
558 {
559 L2Error = std::max(L2Error, m_vL2Errors[i]);
560 }
561 return L2Error;
562}
563
564/**
565 *
566 */
570{
571 if (m_numChunks == 1)
572 {
573 return 0.0;
574 }
575 else
576 {
577 // Average communication time over niter iteration.
578 size_t niter = 20;
580 for (size_t n = 0; n <= niter; n++)
581 {
582 if (n == 1)
583 {
584 timer.Start(); // Ignore the first iteration
585 }
586
587 if (m_chunkRank == 0)
588 {
589 for (size_t i = 0; i < buffer1.size(); ++i)
590 {
591 m_comm->GetTimeComm()->Send(m_numChunks - 1, buffer1[i]);
592 }
593 }
594
595 if (m_chunkRank == m_numChunks - 1)
596 {
597 for (size_t i = 0; i < buffer2.size(); ++i)
598 {
599 m_comm->GetTimeComm()->Recv(0, buffer2[i]);
600 }
601 }
602 }
603 timer.Stop();
604 return timer.Elapsed().count() / niter;
605 }
606}
607
608/**
609 *
610 */
614 const Array<OneD, Array<OneD, NekDouble>> &inarray,
616{
617 if (infield.size() != outfield.size())
618 {
619 NEKERROR(ErrorUtil::efatal, "not the same number of variables")
620 }
621
622 for (size_t n = 0; n < infield.size(); ++n)
623 {
624 // Interpolation from infield -> outfield assuming that infield and
625 // outfield are the same explists, but at potentially different
626 // polynomial orders.
627 if (infield[n]->GetExpSize() != outfield[n]->GetExpSize())
628 {
629 NEKERROR(ErrorUtil::efatal, "not the same mesh")
630 }
631
632 // Assign input/output array.
633 auto inphys = (inarray == NullNekDoubleArrayOfArray)
634 ? infield[n]->UpdatePhys()
635 : inarray[n];
636 auto outphys = (outarray == NullNekDoubleArrayOfArray)
637 ? outfield[n]->UpdatePhys()
638 : outarray[n];
639
640 // If same polynomial orders, simply copy solution.
641 if (infield[n]->GetTotPoints() == outfield[n]->GetTotPoints())
642 {
643 Vmath::Vcopy(infield[n]->GetTotPoints(), inphys, 1, outphys, 1);
644 }
645 // If different polynomial orders, interpolate solution.
646 else
647 {
648 for (size_t i = 0; i < infield[n]->GetExpSize(); ++i)
649 {
650 // Get the elements.
651 auto inElmt = infield[n]->GetExp(i);
652 auto outElmt = outfield[n]->GetExp(i);
653
654 // Get the offset of elements in the storage arrays.
655 size_t inoffset = infield[n]->GetPhys_Offset(i);
656 size_t outoffset = outfield[n]->GetPhys_Offset(i);
657
658 // Transform solution from physical to coefficient space.
659 Array<OneD, NekDouble> incoeff(inElmt->GetNcoeffs());
660 inElmt->FwdTrans(inphys + inoffset, incoeff);
661
662 // Interpolate elements.
664 if (inElmt->DetShapeType() == LibUtilities::Seg)
665 {
666 expPtr = std::make_shared<StdRegions::StdSegExp>(
668 inElmt->GetBasis(0)->GetBasisType(),
669 inElmt->GetBasis(0)->GetNumModes(),
670 outElmt->GetBasis(0)->GetPointsKey()));
671 }
672 else if (inElmt->DetShapeType() == LibUtilities::Quad)
673 {
674 expPtr = std::make_shared<StdRegions::StdQuadExp>(
676 inElmt->GetBasis(0)->GetBasisType(),
677 inElmt->GetBasis(0)->GetNumModes(),
678 outElmt->GetBasis(0)->GetPointsKey()),
680 inElmt->GetBasis(1)->GetBasisType(),
681 inElmt->GetBasis(1)->GetNumModes(),
682 outElmt->GetBasis(1)->GetPointsKey()));
683 }
684 else if (inElmt->DetShapeType() == LibUtilities::Tri)
685 {
686 expPtr = std::make_shared<StdRegions::StdTriExp>(
688 inElmt->GetBasis(0)->GetBasisType(),
689 inElmt->GetBasis(0)->GetNumModes(),
690 outElmt->GetBasis(0)->GetPointsKey()),
692 inElmt->GetBasis(1)->GetBasisType(),
693 inElmt->GetBasis(1)->GetNumModes(),
694 outElmt->GetBasis(1)->GetPointsKey()));
695 }
696 else if (inElmt->DetShapeType() == LibUtilities::Hex)
697 {
698 expPtr = std::make_shared<StdRegions::StdHexExp>(
700 inElmt->GetBasis(0)->GetBasisType(),
701 inElmt->GetBasis(0)->GetNumModes(),
702 outElmt->GetBasis(0)->GetPointsKey()),
704 inElmt->GetBasis(1)->GetBasisType(),
705 inElmt->GetBasis(1)->GetNumModes(),
706 outElmt->GetBasis(1)->GetPointsKey()),
708 inElmt->GetBasis(2)->GetBasisType(),
709 inElmt->GetBasis(2)->GetNumModes(),
710 outElmt->GetBasis(2)->GetPointsKey()));
711 }
712 else if (inElmt->DetShapeType() == LibUtilities::Prism)
713 {
714 expPtr = std::make_shared<StdRegions::StdPrismExp>(
716 inElmt->GetBasis(0)->GetBasisType(),
717 inElmt->GetBasis(0)->GetNumModes(),
718 outElmt->GetBasis(0)->GetPointsKey()),
720 inElmt->GetBasis(1)->GetBasisType(),
721 inElmt->GetBasis(1)->GetNumModes(),
722 outElmt->GetBasis(1)->GetPointsKey()),
724 inElmt->GetBasis(2)->GetBasisType(),
725 inElmt->GetBasis(2)->GetNumModes(),
726 outElmt->GetBasis(2)->GetPointsKey()));
727 }
728 else if (inElmt->DetShapeType() == LibUtilities::Pyr)
729 {
730 expPtr = std::make_shared<StdRegions::StdPyrExp>(
732 inElmt->GetBasis(0)->GetBasisType(),
733 inElmt->GetBasis(0)->GetNumModes(),
734 outElmt->GetBasis(0)->GetPointsKey()),
736 inElmt->GetBasis(1)->GetBasisType(),
737 inElmt->GetBasis(1)->GetNumModes(),
738 outElmt->GetBasis(1)->GetPointsKey()),
740 inElmt->GetBasis(2)->GetBasisType(),
741 inElmt->GetBasis(2)->GetNumModes(),
742 outElmt->GetBasis(2)->GetPointsKey()));
743 }
744 else if (inElmt->DetShapeType() == LibUtilities::Tet)
745 {
746 expPtr = std::make_shared<StdRegions::StdTetExp>(
748 inElmt->GetBasis(0)->GetBasisType(),
749 inElmt->GetBasis(0)->GetNumModes(),
750 outElmt->GetBasis(0)->GetPointsKey()),
752 inElmt->GetBasis(1)->GetBasisType(),
753 inElmt->GetBasis(1)->GetNumModes(),
754 outElmt->GetBasis(1)->GetPointsKey()),
756 inElmt->GetBasis(2)->GetBasisType(),
757 inElmt->GetBasis(2)->GetNumModes(),
758 outElmt->GetBasis(2)->GetPointsKey()));
759 }
760
761 // Transform solution from coefficient to physical space.
762 Array<OneD, NekDouble> tmp = outphys + outoffset;
763 expPtr->BwdTrans(incoeff, tmp);
764 }
765 }
766 }
767}
768
769} // namespace Nektar::SolverUtils
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:208
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mode...
Definition: ErrorUtil.hpp:202
Describes the specification for a Basis.
Definition: Basis.h:45
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
static SessionReaderSharedPtr CreateInstance(int argc, char *argv[])
Creates an instance of the SessionReader class.
Base class for the development of solvers.
Definition: Driver.h:65
LibUtilities::SessionReaderSharedPtr m_session
Session reader object.
Definition: Driver.h:83
LibUtilities::CommSharedPtr m_comm
Communication object.
Definition: Driver.h:80
SpatialDomains::MeshGraphSharedPtr m_graph
MeshGraph object.
Definition: Driver.h:89
enum EvolutionOperatorType m_EvolutionOperator
Evolution Operator.
Definition: Driver.h:98
Array< OneD, EquationSystemSharedPtr > m_equ
Equation system to solve.
Definition: Driver.h:92
Array< OneD, NekDouble > m_vL2Errors
Storage for parallel-in-time iteration.
void UpdateFieldCoeffs(const size_t timeLevel, const Array< OneD, const Array< OneD, NekDouble > > &in=NullNekDoubleArrayOfArray)
void SendToNextProc(Array< OneD, Array< OneD, NekDouble > > &array, int &convergence)
size_t m_iterMaxPIT
Maximum number of parallel-in-time iteration.
void PrintErrorNorm(const size_t timeLevel, const bool normalized)
void SetParallelInTimeEquationSystem(std::string AdvectiveType)
Array< OneD, size_t > m_nsteps
Number of time steps for each time level.
SOLVER_UTILS_EXPORT void v_InitObject(std::ostream &out=std::cout) override
Virtual function for initialisation implementation.
void EvaluateExactSolution(const size_t timeLevel, const NekDouble &time)
void RecvFromPreviousProc(Array< OneD, Array< OneD, NekDouble > > &array, int &convergence)
Array< OneD, std::shared_ptr< UnsteadySystem > > m_EqSys
Equation system to solve.
void PrintHeader(const std::string &title, const char c)
NekDouble m_tolerPIT
ParallelInTime tolerance.
void PrintSolverInfo(std::ostream &out=std::cout)
bool m_exactSolution
Using exact solution to compute error norms.
void CopyFromPhysField(const size_t timeLevel, Array< OneD, Array< OneD, NekDouble > > &out)
void CopyToPhysField(const size_t timeLevel, const Array< OneD, const Array< OneD, NekDouble > > &in)
SOLVER_UTILS_EXPORT void v_Execute(std::ostream &out=std::cout) override
Virtual function for solve implementation.
Array< OneD, size_t > m_npts
Number of dof for each time level.
Array< OneD, Array< OneD, NekDouble > > m_exactsoln
NekDouble EstimateCommunicationTime(Array< OneD, Array< OneD, NekDouble > > &buffer1, Array< OneD, Array< OneD, NekDouble > > &buffer2)
void SolutionConvergenceSummary(const size_t timeLevel)
Array< OneD, NekDouble > m_timestep
Time step for each time level.
void CopySolutionVector(const Array< OneD, const Array< OneD, NekDouble > > &in, Array< OneD, Array< OneD, NekDouble > > &out)
void UpdateErrorNorm(const size_t timeLevel, const bool normalized)
void SolutionConvergenceMonitoring(const size_t timeLevel, const size_t iter)
SOLVER_UTILS_EXPORT DriverParallelInTime(const LibUtilities::SessionReaderSharedPtr pSession, const SpatialDomains::MeshGraphSharedPtr pGraph)
Constructor.
void Interpolate(const Array< OneD, MultiRegions::ExpListSharedPtr > &infield, const Array< OneD, MultiRegions::ExpListSharedPtr > &outfield, const Array< OneD, Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray)
static MeshGraphSharedPtr Read(const LibUtilities::SessionReaderSharedPtr pSession, LibUtilities::DomainRangeShPtr rng=LibUtilities::NullDomainRangeShPtr, bool fillGraph=true, SpatialDomains::MeshGraphSharedPtr partitionedGraph=nullptr)
Definition: MeshGraphIO.cpp:53
std::shared_ptr< SessionReader > SessionReaderSharedPtr
static DomainRangeShPtr NullDomainRangeShPtr
Definition: DomainRange.h:65
EquationSystemFactory & GetEquationSystemFactory()
std::shared_ptr< MeshGraph > MeshGraphSharedPtr
Definition: MeshGraph.h:174
std::shared_ptr< StdExpansion > StdExpansionSharedPtr
static Array< OneD, Array< OneD, NekDouble > > NullNekDoubleArrayOfArray
double NekDouble
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.hpp:825