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
39#include <boost/format.hpp>
40
41namespace Nektar
42{
43namespace SolverUtils
44{
45
46/**
47 *
48 */
52 : Driver(pSession, pGraph)
53{
54}
55
56/**
57 *
58 */
60{
61 try
62 {
63 // Retrieve the type of evolution operator to use
65 m_session->GetSolverInfoAsEnum<EvolutionOperatorType>(
66 "EvolutionOperator");
67
68 m_nequ = 2; // Only two time levels currently implemented.
69
71
72 // Set the AdvectiveType tag and create EquationSystem objects.
73 switch (m_EvolutionOperator)
74 {
75 case eNonlinear:
77 break;
78 case eDirect:
80 break;
81 case eAdjoint:
83 break;
84 case eSkewSymmetric:
85 SetParallelInTimeEquationSystem("SkewSymmetric");
86 break;
87 default:
88 ASSERTL0(false, "Unrecognised evolution operator.");
89 }
90
91 // Set pointers.
93 std::dynamic_pointer_cast<SolverUtils::UnsteadySystem>(m_equ[0]);
95 std::dynamic_pointer_cast<SolverUtils::UnsteadySystem>(m_equ[1]);
96 }
97 catch (int e)
98 {
99 ASSERTL0(e == -1, "No such class class defined.");
100 out << "An error occurred during driver initialisation." << std::endl;
101 }
102}
103
104/**
105 *
106 */
107void DriverParallelInTime::v_Execute(std::ostream &out)
108{
109 boost::ignore_unused(out);
110
111 ASSERTL0(false, "Specific version of Parallel-in-Time not implemented");
112}
113
114/**
115 *
116 */
118{
119 ASSERTL0(false, "Specific version of Parallel-in-Time not implemented");
120 return 0.0;
121}
122
123/**
124 *
125 */
127{
128 ASSERTL0(false, "Specific version of Parallel-in-Time not implemented");
129 return 0.0;
130}
131
132/**
133 *
134 */
136{
137 ASSERTL0(false, "Specific version of Parallel-in-Time not implemented");
138 return 0.0;
139}
140
141/**
142 *
143 */
145{
146 ASSERTL0(false, "Specific version of Parallel-in-Time not implemented");
147 return 0.0;
148}
149
150/**
151 *
152 */
154{
155 ASSERTL0(false, "Specific version of Parallel-in-Time not implemented");
156 return 0.0;
157}
158
159/**
160 *
161 */
163{
164 ASSERTL0(false, "Specific version of Parallel-in-Time not implemented");
165 return 0.0;
166}
167
168/**
169 *
170 */
172{
173 ASSERTL0(false, "Specific version of Parallel-in-Time not implemented");
174 return 0.0;
175}
176
177/**
178 *
179 */
181 const size_t iter, NekDouble fineSolveTime, NekDouble coarseSolveTime,
182 NekDouble restTime, NekDouble interTime, NekDouble commTime,
183 NekDouble predictorOverheadTime, NekDouble overheadTime)
184{
185 boost::ignore_unused(iter, fineSolveTime, coarseSolveTime, restTime,
186 interTime, commTime, predictorOverheadTime,
187 overheadTime);
188 ASSERTL0(false, "Specific version of Parallel-in-Time not implemented");
189 return 0.0;
190}
191
192/**
193 * Set the ParallelInTime (coarse solver) session file
194 */
196 std::string AdvectiveType)
197{
198 // Retrieve the equation system to solve.
199 ASSERTL0(m_session->DefinesSolverInfo("EqType"),
200 "EqType SolverInfo tag must be defined.");
201 std::string vEquation = m_session->DefinesSolverInfo("SolverType")
202 ? m_session->GetSolverInfo("SolverType")
203 : m_session->GetSolverInfo("EqType");
204
205 // Check such a module exists for this equation.
206 ASSERTL0(GetEquationSystemFactory().ModuleExists(vEquation),
207 "EquationSystem '" + vEquation +
208 "' is not defined.\n"
209 "Ensure equation name is correct and module is compiled.\n");
210
211 // Set fine parallel-in-time solver.
212 m_session->SetTag("AdvectiveType", AdvectiveType);
213 m_session->SetTag("ParallelInTimeSolver", "TimeLevel0");
215 m_graph);
216
217 // Define argument for the coarse parallel-in-time solver.
218 int npx = m_session->DefinesCmdLineArgument("npx")
219 ? m_session->GetCmdLineArgument<int>("npx")
220 : 1;
221 int npy = m_session->DefinesCmdLineArgument("npy")
222 ? m_session->GetCmdLineArgument<int>("npy")
223 : 1;
224 int npz = m_session->DefinesCmdLineArgument("npz")
225 ? m_session->GetCmdLineArgument<int>("npz")
226 : 1;
227 int nsz = m_session->DefinesCmdLineArgument("nsz")
228 ? m_session->GetCmdLineArgument<int>("nsz")
229 : 1;
230 int npt = m_session->DefinesCmdLineArgument("npt")
231 ? m_session->GetCmdLineArgument<int>("npt")
232 : 1;
233
234 // Convert into string.
235 std::string npx_string = std::to_string(npx);
236 std::string npy_string = std::to_string(npy);
237 std::string npz_string = std::to_string(npz);
238 std::string nsz_string = std::to_string(nsz);
239 std::string npt_string = std::to_string(npt);
240
241 // useoptfile
242 bool useoptfile = m_session->DefinesCmdLineArgument("useoptfile");
243 std::string optfilename = useoptfile ? m_session->GetFilenames()[0] : "";
244
245 char *argv[] = {const_cast<char *>("Solver"), // this is just a place holder
246 const_cast<char *>("--npx"),
247 const_cast<char *>(npx_string.c_str()),
248 const_cast<char *>("--npy"),
249 const_cast<char *>(npy_string.c_str()),
250 const_cast<char *>("--npz"),
251 const_cast<char *>(npz_string.c_str()),
252 const_cast<char *>("--nsz"),
253 const_cast<char *>(nsz_string.c_str()),
254 const_cast<char *>("--npt"),
255 const_cast<char *>(npt_string.c_str()),
256 const_cast<char *>("--useoptfile"),
257 const_cast<char *>(optfilename.c_str()),
258 nullptr};
259
260 size_t argc = useoptfile ? 13 : 11;
261
262 // Get list of session file names.
263 std::vector<std::string> sessionFileNames;
264 for (auto &filename : m_session->GetFilenames())
265 {
266 // Remove optfile name, if necessary.
267 if (filename.substr(filename.find_last_of(".") + 1) != "opt")
268 {
269 sessionFileNames.push_back(filename);
270 }
271 }
272
273 // Set session for coarse solver.
274 for (size_t timeLevel = 1; timeLevel < m_nequ; timeLevel++)
275 {
277 argc, argv, sessionFileNames, m_session->GetComm(), timeLevel);
278
279 // Set graph for coarse solver.
282
283 // Set BndRegionOrdering (necessary for DG with periodic BC) FIXME
284 graph->SetBndRegionOrdering(m_graph->GetBndRegionOrdering());
285
286 // Set CompositeOrdering (necessary for DG with periodic BC) FIXME
287 graph->SetCompositeOrdering(m_graph->GetCompositeOrdering());
288
289 // Retrieve the equation system to solve.
290 ASSERTL0(session->DefinesSolverInfo("EqType"),
291 "EqType SolverInfo tag must be defined.");
292 auto vEquation = session->DefinesSolverInfo("SolverType")
293 ? session->GetSolverInfo("SolverType")
294 : session->GetSolverInfo("EqType");
295
296 // Check such a module exists for this equation.
297 ASSERTL0(
298 GetEquationSystemFactory().ModuleExists(vEquation),
299 "EquationSystem '" + vEquation +
300 "' is not defined.\n"
301 "Ensure equation name is correct and module is compiled.\n");
302
303 // Set coarse parallel-in-time solver.
304 session->SetTag("AdvectiveType", AdvectiveType);
305 session->SetTag("ParallelInTimeSolver",
306 "TimeLevel" + std::to_string(timeLevel));
308 vEquation, session, graph);
309 }
310}
311
312/**
313 *
314 */
316{
317 // Parallel-in-Time iteration parameters.
318 m_tolerPIT = m_session->GetParameter("PITToler");
319 m_iterMaxPIT = m_session->GetParameter("PITIterMax");
320 m_numWindowsPIT = m_session->DefinesParameter("NumWindows")
321 ? m_session->GetParameter("NumWindows")
323
324 // Time stepping parameters.
325 m_fineTimeStep = m_equ[0]->GetTimeStep();
326 m_coarseTimeStep = m_equ[1]->GetTimeStep();
327 m_fineSteps = m_equ[0]->GetSteps();
328 m_coarseSteps = m_equ[1]->GetSteps();
329
330 // I/O parameters.
331 m_infoSteps = m_fineEqSys->GetInfoSteps();
332 m_checkSteps = m_fineEqSys->GetCheckpointSteps();
333
334 // Other parameters.
335 m_exactSolution = m_session->DefinesParameter("ExactSolution")
336 ? m_session->GetParameter("ExactSolution")
338}
339
340/**
341 *
342 */
344{
345 // Initialize fine solver.
346 if (turnoff_output)
347 {
348 m_fineEqSys->SetInfoSteps(0);
349 m_fineEqSys->SetCheckpointSteps(0);
350 }
351 m_fineEqSys->DoInitialise(true);
352
353 // Initialize coarse solver.
354 m_coarseEqSys->SetInfoSteps(0);
355 m_coarseEqSys->SetCheckpointSteps(0);
356 m_coarseEqSys->DoInitialise(false);
357}
358
359/**
360 *
361 */
363{
364 // Set some member variables.
365 m_nVar = m_fineEqSys->GetNvariables();
366 m_fineNpts = m_fineEqSys->GetNpoints();
367 m_coarseNpts = m_coarseEqSys->GetNpoints();
368
369 // Allocate memory.
373 for (size_t i = 0; i < m_nVar; ++i)
374 {
378 }
381}
382
383/**
384 *
385 */
387{
390 for (size_t i = 0; i < m_nVar; ++i)
391 {
392 m_fineFields[i] =
394 m_fineEqSys->UpdateFields()[i], true, false);
395 m_coarseFields[i] =
397 m_coarseEqSys->UpdateFields()[i], true, false);
398 }
399}
400
401/**
402 *
403 */
405{
406 if (m_chunkRank == 0 && m_comm->GetSpaceComm()->GetRank() == 0)
407 {
408 std::cout << "========================================================="
409 "=============="
410 << std::endl
411 << std::flush;
412 std::cout << "======================== COARSE PROPAGATOR INFO "
413 "======================="
414 << std::endl
415 << std::flush;
416
417 m_coarseEqSys->PrintSummary(out);
418
419 std::cout << std::endl << std::flush;
420 }
421}
422
423/**
424 *
425 */
427{
428 if (m_chunkRank == 0 && m_comm->GetSpaceComm()->GetRank() == 0)
429 {
430 std::cout << "========================================================="
431 "=============="
432 << std::endl
433 << std::flush;
434 std::cout << "========================= FINE PROPAGATOR INFO "
435 "========================"
436 << std::endl
437 << std::flush;
438
439 m_fineEqSys->PrintSummary(out);
440
441 std::cout << std::endl << std::flush;
442 }
443}
444
445/**
446 *
447 */
449{
450 if (m_chunkRank == m_numChunks - 1 &&
451 m_comm->GetSpaceComm()->GetRank() == 0)
452 {
453 std::cout << std::endl;
454 std::cout << "*******************************************" << std::endl
455 << std::flush;
456 std::cout << title << std::endl << std::flush;
457 std::cout << "*******************************************" << std::endl
458 << std::flush;
459 }
460}
461
462/**
463 *
464 */
466{
467 if (m_chunkRank == m_numChunks - 1 &&
468 m_comm->GetSpaceComm()->GetRank() == 0)
469 {
470 std::cout << "-------------------------------------------" << std::endl
471 << std::flush;
472 std::cout << title << std::endl << std::flush;
473 std::cout << "-------------------------------------------" << std::endl
474 << std::flush;
475 }
476}
477
478/**
479 *
480 */
482{
483 if (m_chunkRank == m_numChunks - 1 &&
484 m_comm->GetSpaceComm()->GetRank() == 0)
485 {
486 std::cout << "Total Computation Time : " << time << "s" << std::endl
487 << std::flush;
488 }
489}
490
491/**
492 *
493 */
495 Array<OneD, Array<OneD, NekDouble>> &array, int &convergence)
496{
497 LibUtilities::CommSharedPtr tComm = m_session->GetComm()->GetTimeComm();
498
499 if (!convergence)
500 {
501 if (m_chunkRank > 0)
502 {
503 tComm->Recv(m_chunkRank - 1, convergence);
505 }
506 }
507}
508
509/**
510 *
511 */
514{
515 LibUtilities::CommSharedPtr tComm = m_session->GetComm()->GetTimeComm();
516
517 if (m_chunkRank > 0)
518 {
519 for (size_t i = 0; i < array.size(); ++i)
520 {
521 tComm->Recv(m_chunkRank - 1, array[i]);
522 }
523 }
524}
525
526/**
527 *
528 */
530 Array<OneD, Array<OneD, NekDouble>> &array, int &convergence)
531{
532 LibUtilities::CommSharedPtr tComm = m_session->GetComm()->GetTimeComm();
533
534 if (m_chunkRank < m_numChunks - 1)
535 {
536 tComm->Send(m_chunkRank + 1, convergence);
537 }
539}
540
541/**
542 *
543 */
546{
547 LibUtilities::CommSharedPtr tComm = m_session->GetComm()->GetTimeComm();
548
549 if (m_chunkRank < m_numChunks - 1)
550 {
551 for (size_t i = 0; i < array.size(); ++i)
552 {
553 tComm->Send(m_chunkRank + 1, array[i]);
554 }
555 }
556}
557
558/**
559 *
560 */
562 const Array<OneD, const Array<OneD, NekDouble>> &in,
564{
565 for (size_t i = 0; i < in.size(); ++i)
566 {
567 Vmath::Vcopy(in[i].size(), in[i], 1, out[i], 1);
568 }
569}
570
571/**
572 *
573 */
576{
577 for (size_t i = 0; i < out.size(); ++i)
578 {
579 m_fineEqSys->CopyFromPhysField(i, out[i]);
580 }
581}
582
583/**
584 *
585 */
588{
589 for (size_t i = 0; i < out.size(); ++i)
590 {
591 m_coarseEqSys->CopyFromPhysField(i, out[i]);
592 }
593}
594
595/**
596 *
597 */
599 const Array<OneD, const Array<OneD, NekDouble>> &in)
600{
601 for (size_t i = 0; i < in.size(); ++i)
602 {
603 m_fineEqSys->CopyToPhysField(i, in[i]);
604 }
605}
606
607/**
608 *
609 */
611 const Array<OneD, const Array<OneD, NekDouble>> &in)
612{
613 for (size_t i = 0; i < in.size(); ++i)
614 {
615 m_coarseEqSys->CopyToPhysField(i, in[i]);
616 }
617}
618
619/**
620 *
621 */
623 const Array<OneD, const Array<OneD, NekDouble>> &in)
624{
625 for (size_t i = 0; i < in.size(); ++i)
626 {
627 m_fineEqSys->CopyToPhysField(i, in[i]);
628 m_fineEqSys->UpdateFields()[i]->FwdTrans(
629 m_fineEqSys->UpdateFields()[i]->GetPhys(),
630 m_fineEqSys->UpdateFields()[i]->UpdateCoeffs());
631 }
632}
633
634/**
635 *
636 */
638{
639 for (size_t i = 0; i < m_exactsoln.size(); ++i)
640 {
641 m_fineEqSys->EvaluateExactSolution(i, m_exactsoln[i], time);
642 }
643}
644
645/**
646 *
647 */
649 const NekDouble &CPUtime)
650{
651 UpdateErrorNorm(true);
652 PrintErrorNorm(true);
653 PrintComputationalTime(CPUtime);
654}
655
656/**
657 *
658 */
660{
661 UpdateErrorNorm(false);
662 PrintErrorNorm(false);
663 PrintComputationalTime(CPUtime);
664}
665
666/**
667 *
668 */
669void DriverParallelInTime::UpdateErrorNorm(const bool normalized)
670{
671 for (size_t i = 0; i < m_vL2Errors.size(); ++i)
672 {
673 m_vL2Errors[i] = m_fineEqSys->L2Error(i, m_exactsoln[i], normalized);
674 m_vLinfErrors[i] = m_fineEqSys->LinfError(i, m_exactsoln[i]);
675 }
676}
677
678/**
679 *
680 */
681void DriverParallelInTime::PrintErrorNorm(const bool normalized)
682{
683 if (m_chunkRank == m_numChunks - 1 &&
684 m_comm->GetSpaceComm()->GetRank() == 0)
685 {
686 for (size_t i = 0; i < m_vL2Errors.size(); ++i)
687 {
688 if (normalized)
689 {
690 std::cout << "L2 error (variable "
691 << m_fineEqSys->GetVariable(i)
692 << ") : " << m_vL2Errors[i] << std::endl
693 << std::flush;
694 std::cout << "Linf error (variable "
695 << m_fineEqSys->GetVariable(i)
696 << ") : " << m_vLinfErrors[i] << std::endl
697 << std::flush;
698 }
699 else
700 {
701 std::cout << "L 2 error (variable "
702 << m_fineEqSys->GetVariable(i)
703 << ") : " << m_vL2Errors[i] << std::endl
704 << std::flush;
705 std::cout << "L inf error (variable "
706 << m_fineEqSys->GetVariable(i)
707 << ") : " << m_vLinfErrors[i] << std::endl
708 << std::flush;
709 }
710 }
711 }
712}
713
714/**
715 *
716 */
718{
719 NekDouble L2Error = 0.0;
720 for (size_t i = 0; i < m_vL2Errors.size(); ++i)
721 {
722 L2Error = std::max(L2Error, m_vL2Errors[i]);
723 }
724 return L2Error;
725}
726
727/**
728 *
729 */
731 const Array<OneD, const Array<OneD, NekDouble>> &inarray,
733{
734 size_t nVar = inarray.size();
735
736 // Interpolate from fine to coarse
737 if (inarray[0].size() > outarray[0].size())
738 {
739 for (size_t i = 0; i < nVar; ++i)
740 {
741 m_fineFields[i]->UpdatePhys() = inarray[i];
742 m_coarseFields[i]->UpdatePhys() = outarray[i];
743 }
745 }
746 // Interpolate from coarse to fine
747 else
748 {
749 for (size_t i = 0; i < nVar; ++i)
750 {
751 m_coarseFields[i]->UpdatePhys() = inarray[i];
752 m_fineFields[i]->UpdatePhys() = outarray[i];
753 }
755 }
756}
757
758/**
759 *
760 */
762{
763 // Print header.
764 PrintHeaderTitle1("PARAREAL SPEED-UP ANALYSIS");
765
766 // Mean communication time.
768 PrintHeaderTitle2("Mean Communication Time = " +
769 (boost::format("%1$.6e") % commTime).str() + "s");
770
771 // Mean restriction time.
773 PrintHeaderTitle2("Mean Restriction Time = " +
774 (boost::format("%1$.6f") % restTime).str() + "s");
775
776 // Mean interpolation time.
778 PrintHeaderTitle2("Mean Interpolation Time = " +
779 (boost::format("%1$.6f") % interTime).str() + "s");
780
781 // Mean coarse solver time.
782 NekDouble coarseSolveTime = v_EstimateCoarseSolverTime();
783 PrintHeaderTitle2("Mean Coarse Solve Time = " +
784 (boost::format("%1$.6f") % coarseSolveTime).str() + "s");
785
786 // Mean fine solver time.
787 NekDouble fineSolveTime = v_EstimateFineSolverTime();
788 PrintHeaderTitle2("Mean Fine Solve Time = " +
789 (boost::format("%1$.6f") % fineSolveTime).str() + "s");
790
791 // Mean predictor time.
792 NekDouble predictorTime = v_EstimatePredictorTime();
793 PrintHeaderTitle2("Mean Predictor Time = " +
794 (boost::format("%1$.6f") % predictorTime).str() + "s");
795
796 // Mean overhead time.
797 NekDouble OverheadTime = v_EstimateOverheadTime();
798 PrintHeaderTitle2("Mean Overhead Time = " +
799 (boost::format("%1$.6f") % OverheadTime).str() + "s");
800
801 // Print speedup time.
802 PrintSpeedUp(fineSolveTime, coarseSolveTime, restTime, interTime, commTime,
803 predictorTime, OverheadTime);
804}
805
806/**
807 *
808 */
810 NekDouble coarseSolveTime,
811 NekDouble restTime, NekDouble interTime,
812 NekDouble commTime,
813 NekDouble predictOverheadTime,
814 NekDouble OverheadTime)
815{
816 if (m_chunkRank == m_numChunks - 1 &&
817 m_comm->GetSpaceComm()->GetRank() == 0)
818 {
819 // Print maximum theoretical speed-up
820 PrintHeaderTitle2("Maximum Speed-up");
821 for (size_t k = 1; k <= m_numChunks; k++)
822 {
823 NekDouble speedup =
824 v_ComputeSpeedUp(k, fineSolveTime, coarseSolveTime, 0.0, 0.0,
825 0.0, predictOverheadTime, OverheadTime);
826 std::cout << "Speed-up (" << k << ") = " << speedup << std::endl
827 << std::flush;
828 }
829
830 // Print speed-up with interpolation
831 PrintHeaderTitle2("Speed-up with interp.");
832 for (size_t k = 1; k <= m_numChunks; k++)
833 {
834 NekDouble speedup = v_ComputeSpeedUp(
835 k, fineSolveTime, coarseSolveTime, restTime, interTime, 0.0,
836 predictOverheadTime, OverheadTime);
837 std::cout << "Speed-up (" << k << ") = " << speedup << std::endl
838 << std::flush;
839 }
840
841 // Print speed-up with interpolation and communication
842 PrintHeaderTitle2("Speed-up with comm. and interp.");
843 for (size_t k = 1; k <= m_numChunks; k++)
844 {
845 NekDouble speedup = v_ComputeSpeedUp(
846 k, fineSolveTime, coarseSolveTime, restTime, interTime,
847 commTime, predictOverheadTime, OverheadTime);
848 std::cout << "Speed-up (" << k << ") = " << speedup << std::endl
849 << std::flush;
850 }
851 std::cout << "-------------------------------------------" << std::endl
852 << std::flush;
853 }
854}
855
856/**
857 *
858 */
862{
863 if (m_numChunks == 1)
864 {
865 return 0.0;
866 }
867 else
868 {
869 // Average communication time over niter iteration.
870 size_t niter = 20;
872 LibUtilities::CommSharedPtr tComm = m_session->GetComm()->GetTimeComm();
873 for (size_t n = 0; n <= niter; n++)
874 {
875 if (n == 1)
876 {
877 timer.Start(); // Ignore the first iteration
878 }
879
880 if (m_chunkRank == 0)
881 {
882 for (size_t i = 0; i < buffer1.size(); ++i)
883 {
884 tComm->Send(m_numChunks - 1, buffer1[i]);
885 }
886 }
887
888 if (m_chunkRank == m_numChunks - 1)
889 {
890 for (size_t i = 0; i < buffer2.size(); ++i)
891 {
892 tComm->Recv(0, buffer2[i]);
893 }
894 }
895 }
896 timer.Stop();
897 return timer.Elapsed().count() / niter;
898 }
899}
900
901/**
902 *
903 */
906{
907
908 // Interpolation from exp1 -> exp2 assuming that exp1 and exp2 are the
909 // same explists, but at potentially different polynomial orders.
910 if (exp1.size() != exp2.size())
911 {
912 NEKERROR(ErrorUtil::efatal, "not the same mesh")
913 }
914
915 for (int n = 0; n < exp1.size(); ++n)
916 {
917 // Interpolation from exp1 -> exp2 assuming that exp1 and exp2 are the
918 // same explists, but at potentially different polynomial orders.
919 if (exp1[n]->GetExpSize() != exp2[n]->GetExpSize())
920 {
921 NEKERROR(ErrorUtil::efatal, "not the same mesh")
922 }
923
924 // If same polynomial orders, simply copy solution
925 if (exp1[n]->GetTotPoints() == exp2[n]->GetTotPoints())
926 {
927 Vmath::Vcopy(exp1[n]->GetTotPoints(), exp1[n]->GetPhys(), 1,
928 exp2[n]->UpdatePhys(), 1);
929 }
930 // If different polynomial orders, interpolate solution
931 else
932 {
933 // Transform solution from physical to coefficient space
934 exp1[n]->FwdTrans(exp1[n]->GetPhys(), exp1[n]->UpdateCoeffs());
935
936 for (int i = 0; i < exp1[n]->GetExpSize(); ++i)
937 {
938 // Get the elements
939 LocalRegions::ExpansionSharedPtr elmt1 = exp1[n]->GetExp(i),
940 elmt2 = exp2[n]->GetExp(i);
941
942 // Get the offset of elements in the storage arrays.
943 int offset1 = exp1[n]->GetCoeff_Offset(i);
944 int offset2 = exp2[n]->GetCoeff_Offset(i);
945
946 // Get number of modes
948 elmt1->GetBase();
949 std::vector<unsigned int> nummodes1(base1.size());
950 std::vector<LibUtilities::BasisType> btype1(base1.size());
951 for (int j = 0; j < nummodes1.size(); ++j)
952 {
953 nummodes1[j] = base1[j]->GetNumModes();
954 btype1[j] = base1[j]->GetBasisType();
955 }
956
957 // Extract data from exp1 -> exp2.
958 elmt2->ExtractDataToCoeffs(
959 &exp1[n]->GetCoeffs()[offset1], nummodes1, 0,
960 &exp2[n]->UpdateCoeffs()[offset2], btype1);
961 }
962
963 // Transform solution back to physical space
964 exp2[n]->BwdTrans(exp2[n]->GetCoeffs(), exp2[n]->UpdatePhys());
965 }
966 }
967}
968
969} // namespace SolverUtils
970} // namespace Nektar
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:215
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mode...
Definition: ErrorUtil.hpp:209
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
Definition: NekFactory.hpp:144
static SessionReaderSharedPtr CreateInstance(int argc, char *argv[])
Creates an instance of the SessionReader class.
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
Base class for the development of solvers.
Definition: Driver.h:67
LibUtilities::SessionReaderSharedPtr m_session
Session reader object.
Definition: Driver.h:85
LibUtilities::CommSharedPtr m_comm
Communication object.
Definition: Driver.h:82
SpatialDomains::MeshGraphSharedPtr m_graph
MeshGraph object.
Definition: Driver.h:91
enum EvolutionOperatorType m_EvolutionOperator
Evolution Operator.
Definition: Driver.h:100
Array< OneD, EquationSystemSharedPtr > m_equ
Equation system to solve.
Definition: Driver.h:94
int m_nequ
number of equations
Definition: Driver.h:97
size_t m_coarseSteps
Number of steps for the coarse solver.
void PrintSpeedUp(NekDouble fineSolveTime, NekDouble coarseSolveTime, NekDouble restTime, NekDouble interTime, NekDouble commTime, NekDouble predictorOverheadTime, NekDouble overheadTime)
void SendSolutionToNextProc(Array< OneD, Array< OneD, NekDouble > > &array, int &convergence)
size_t m_iterMaxPIT
Maximum number of parallel-in-time iteration.
size_t m_fineSteps
Number of steps for the fine solver.
void SetParallelInTimeEquationSystem(std::string AdvectiveType)
void CopyToFinePhysField(const Array< OneD, const Array< OneD, NekDouble > > &in)
NekDouble m_coarseTimeStep
Timestep for coarse solver.
void RecvInitialConditionFromPreviousProc(Array< OneD, Array< OneD, NekDouble > > &array, int &convergence)
Array< OneD, MultiRegions::ExpListSharedPtr > m_fineFields
Array< OneD, MultiRegions::ExpListSharedPtr > m_coarseFields
void CopyFromFinePhysField(Array< OneD, Array< OneD, NekDouble > > &out)
Array< OneD, Array< OneD, NekDouble > > m_tmpfine
void Interpolator(const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray)
std::shared_ptr< SolverUtils::UnsteadySystem > m_coarseEqSys
virtual SOLVER_UTILS_EXPORT void v_InitObject(std::ostream &out=std::cout) override
Virtual function for initialisation implementation.
void PrintHeaderTitle1(const std::string &title)
void PrintHeaderTitle2(const std::string &title)
NekDouble m_tolerPIT
ParallelInTime tolerance.
void PrintCoarseSolverInfo(std::ostream &out=std::cout)
NekDouble m_fineTimeStep
Timestep for fine solver.
void PrintFineSolverInfo(std::ostream &out=std::cout)
bool m_exactSolution
Using exact solution to compute error norms.
size_t m_checkSteps
Number of steps for checkpoint.
void SolutionConvergenceMonitoring(const NekDouble &time)
virtual SOLVER_UTILS_EXPORT void v_Execute(std::ostream &out=std::cout) override
Virtual function for solve implementation.
Array< OneD, Array< OneD, NekDouble > > m_tmpcoarse
std::shared_ptr< SolverUtils::UnsteadySystem > m_fineEqSys
Array< OneD, Array< OneD, NekDouble > > m_exactsoln
NekDouble EstimateCommunicationTime(Array< OneD, Array< OneD, NekDouble > > &buffer1, Array< OneD, Array< OneD, NekDouble > > &buffer2)
void SolutionConvergenceSummary(const NekDouble &time)
void CopyFromCoarsePhysField(Array< OneD, Array< OneD, NekDouble > > &out)
void UpdateSolution(const Array< OneD, const Array< OneD, NekDouble > > &in)
void CopyToCoarsePhysField(const Array< OneD, const Array< OneD, NekDouble > > &in)
void CopySolutionVector(const Array< OneD, const Array< OneD, NekDouble > > &in, Array< OneD, Array< OneD, NekDouble > > &out)
size_t m_infoSteps
Number of steps for info I/O.
virtual NekDouble v_ComputeSpeedUp(const size_t iter, NekDouble fineSolveTime, NekDouble coarseSolveTime, NekDouble restTime, NekDouble interTime, NekDouble commTime, NekDouble predictorTime, NekDouble overheadTime)
SOLVER_UTILS_EXPORT DriverParallelInTime(const LibUtilities::SessionReaderSharedPtr pSession, const SpatialDomains::MeshGraphSharedPtr pGraph)
Constructor.
static MeshGraphSharedPtr Read(const LibUtilities::SessionReaderSharedPtr pSession, LibUtilities::DomainRangeShPtr rng=LibUtilities::NullDomainRangeShPtr, bool fillGraph=true, SpatialDomains::MeshGraphSharedPtr partitionedGraph=nullptr)
Definition: MeshGraph.cpp:116
std::shared_ptr< SessionReader > SessionReaderSharedPtr
static DomainRangeShPtr NullDomainRangeShPtr
Definition: DomainRange.h:67
std::shared_ptr< Comm > CommSharedPtr
Pointer to a Communicator object.
Definition: Comm.h:57
std::shared_ptr< Expansion > ExpansionSharedPtr
Definition: Expansion.h:68
void InterpExp1ToExp2(const Array< OneD, MultiRegions::ExpListSharedPtr > exp1, Array< OneD, MultiRegions::ExpListSharedPtr > &exp2)
Interpolate from an expansion to an expansion.
EquationSystemFactory & GetEquationSystemFactory()
std::shared_ptr< MeshGraph > MeshGraphSharedPtr
Definition: MeshGraph.h:176
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:2
double NekDouble
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1191