diff --git a/NumLib/ODESolver/NonlinearSolver.cpp b/NumLib/ODESolver/NonlinearSolver.cpp index cf1d3202ceba566957b2f74dd1635d15ba75c251..c3216b1cc56db1714c0b3ab62148e3a73840d122 100644 --- a/NumLib/ODESolver/NonlinearSolver.cpp +++ b/NumLib/ODESolver/NonlinearSolver.cpp @@ -22,13 +22,13 @@ namespace NumLib { void NonlinearSolver<NonlinearSolverTag::Picard>::assemble( - GlobalVector const& x, int const process_id) const + std::vector<GlobalVector*> const& x, int const process_id) const { _equation_system->assemble(x, process_id); } NonlinearSolverStatus NonlinearSolver<NonlinearSolverTag::Picard>::solve( - GlobalVector& x, + std::vector<GlobalVector*>& x, std::function<void(int, GlobalVector const&)> const& postIterationCallback, int const process_id) { @@ -39,11 +39,13 @@ NonlinearSolverStatus NonlinearSolver<NonlinearSolverTag::Picard>::solve( NumLib::GlobalMatrixProvider::provider.getMatrix(_A_id); auto& rhs = NumLib::GlobalVectorProvider::provider.getVector( _rhs_id); - auto& x_new = NumLib::GlobalVectorProvider::provider.getVector(_x_new_id); - bool error_norms_met = false; + std::vector<GlobalVector*> x_new{x}; + x_new[process_id] = + &NumLib::GlobalVectorProvider::provider.getVector(_x_new_id); + LinAlg::copy(*x[process_id], *x_new[process_id]); // set initial guess - LinAlg::copy(x, x_new); // set initial guess + bool error_norms_met = false; _convergence_criterion->preFirstIteration(); @@ -58,11 +60,11 @@ NonlinearSolverStatus NonlinearSolver<NonlinearSolverTag::Picard>::solve( time_iteration.start(); timer_dirichlet.start(); - sys.computeKnownSolutions(x_new, process_id); - sys.applyKnownSolutions(x_new); + sys.computeKnownSolutions(*x_new[process_id], process_id); + sys.applyKnownSolutions(*x_new[process_id]); time_dirichlet += timer_dirichlet.elapsed(); - sys.preIteration(iteration, x_new); + sys.preIteration(iteration, *x_new[process_id]); BaseLib::RunTime time_assembly; time_assembly.start(); @@ -72,20 +74,21 @@ NonlinearSolverStatus NonlinearSolver<NonlinearSolverTag::Picard>::solve( INFO("[time] Assembly took %g s.", time_assembly.elapsed()); timer_dirichlet.start(); - sys.applyKnownSolutionsPicard(A, rhs, x_new); + sys.applyKnownSolutionsPicard(A, rhs, *x_new[process_id]); time_dirichlet += timer_dirichlet.elapsed(); INFO("[time] Applying Dirichlet BCs took %g s.", time_dirichlet); if (!sys.isLinear() && _convergence_criterion->hasResidualCheck()) { GlobalVector res; - LinAlg::matMult(A, x_new, res); // res = A * x_new + LinAlg::matMult(A, *x_new[process_id], res); // res = A * x_new LinAlg::axpy(res, -1.0, rhs); // res -= rhs _convergence_criterion->checkResidual(res); } BaseLib::RunTime time_linear_solver; time_linear_solver.start(); - bool iteration_succeeded = _linear_solver.solve(A, rhs, x_new); + bool iteration_succeeded = + _linear_solver.solve(A, rhs, *x_new[process_id]); INFO("[time] Linear solver took %g s.", time_linear_solver.elapsed()); if (!iteration_succeeded) @@ -96,10 +99,10 @@ NonlinearSolverStatus NonlinearSolver<NonlinearSolverTag::Picard>::solve( { if (postIterationCallback) { - postIterationCallback(iteration, x_new); + postIterationCallback(iteration, *x_new[process_id]); } - switch (sys.postIteration(x_new)) + switch (sys.postIteration(*x_new[process_id])) { case IterationResult::SUCCESS: // Don't copy here. The old x might still be used further @@ -112,13 +115,15 @@ NonlinearSolverStatus NonlinearSolver<NonlinearSolverTag::Picard>::solve( // Copy new solution to x. // Thereby the failed solution can be used by the caller for // debugging purposes. - LinAlg::copy(x_new, x); + LinAlg::copy(*x_new[process_id], *x[process_id]); break; case IterationResult::REPEAT_ITERATION: INFO( "Picard: The postIteration() hook decided that this " "iteration has to be repeated."); - LinAlg::copy(x, x_new); // throw the iteration result away + LinAlg::copy( + *x[process_id], + *x_new[process_id]); // throw the iteration result away continue; } } @@ -134,17 +139,18 @@ NonlinearSolverStatus NonlinearSolver<NonlinearSolverTag::Picard>::solve( error_norms_met = true; } else { if (_convergence_criterion->hasDeltaXCheck()) { - GlobalVector minus_delta_x(x); + GlobalVector minus_delta_x(*x[process_id]); LinAlg::axpy(minus_delta_x, -1.0, - x_new); // minus_delta_x = x - x_new - _convergence_criterion->checkDeltaX(minus_delta_x, x_new); + *x_new[process_id]); // minus_delta_x = x - x_new + _convergence_criterion->checkDeltaX(minus_delta_x, + *x_new[process_id]); } error_norms_met = _convergence_criterion->isSatisfied(); } // Update x s.t. in the next iteration we will compute the right delta x - LinAlg::copy(x_new, x); + LinAlg::copy(*x_new[process_id], *x[process_id]); INFO("[time] Iteration #%u took %g s.", iteration, time_iteration.elapsed()); @@ -171,13 +177,13 @@ NonlinearSolverStatus NonlinearSolver<NonlinearSolverTag::Picard>::solve( NumLib::GlobalMatrixProvider::provider.releaseMatrix(A); NumLib::GlobalVectorProvider::provider.releaseVector(rhs); - NumLib::GlobalVectorProvider::provider.releaseVector(x_new); + NumLib::GlobalVectorProvider::provider.releaseVector(*x_new[process_id]); return {error_norms_met, iteration}; } void NonlinearSolver<NonlinearSolverTag::Newton>::assemble( - GlobalVector const& x, int const process_id) const + std::vector<GlobalVector*> const& x, int const process_id) const { _equation_system->assemble(x, process_id); // TODO if the equation system would be reset to nullptr after each @@ -186,7 +192,7 @@ void NonlinearSolver<NonlinearSolverTag::Newton>::assemble( } NonlinearSolverStatus NonlinearSolver<NonlinearSolverTag::Newton>::solve( - GlobalVector& x, + std::vector<GlobalVector*>& x, std::function<void(int, GlobalVector const&)> const& postIterationCallback, int const process_id) { @@ -205,7 +211,7 @@ NonlinearSolverStatus NonlinearSolver<NonlinearSolverTag::Newton>::solve( // TODO be more efficient // init minus_delta_x to the right size - LinAlg::copy(x, minus_delta_x); + LinAlg::copy(*x[process_id], minus_delta_x); _convergence_criterion->preFirstIteration(); @@ -220,16 +226,16 @@ NonlinearSolverStatus NonlinearSolver<NonlinearSolverTag::Newton>::solve( time_iteration.start(); timer_dirichlet.start(); - sys.computeKnownSolutions(x, process_id); - sys.applyKnownSolutions(x); + sys.computeKnownSolutions(*x[process_id], process_id); + sys.applyKnownSolutions(*x[process_id]); time_dirichlet += timer_dirichlet.elapsed(); - sys.preIteration(iteration, x); + sys.preIteration(iteration, *x[process_id]); BaseLib::RunTime time_assembly; time_assembly.start(); sys.assemble(x, process_id); - sys.getResidual(x, res); + sys.getResidual(*x[process_id], res); sys.getJacobian(J); INFO("[time] Assembly took %g s.", time_assembly.elapsed()); @@ -259,8 +265,8 @@ NonlinearSolverStatus NonlinearSolver<NonlinearSolverTag::Newton>::solve( // TODO could be solved in a better way // cf. // http://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/Vec/VecWAXPY.html - auto& x_new = - NumLib::GlobalVectorProvider::provider.getVector(x, _x_new_id); + auto& x_new = NumLib::GlobalVectorProvider::provider.getVector( + *x[process_id], _x_new_id); LinAlg::axpy(x_new, -_damping, minus_delta_x); if (postIterationCallback) @@ -287,7 +293,7 @@ NonlinearSolverStatus NonlinearSolver<NonlinearSolverTag::Newton>::solve( continue; // That throws the iteration result away. } - LinAlg::copy(x_new, x); // copy new solution to x + LinAlg::copy(x_new, *x[process_id]); // copy new solution to x NumLib::GlobalVectorProvider::provider.releaseVector(x_new); } @@ -303,7 +309,8 @@ NonlinearSolverStatus NonlinearSolver<NonlinearSolverTag::Newton>::solve( } else { if (_convergence_criterion->hasDeltaXCheck()) { // Note: x contains the new solution! - _convergence_criterion->checkDeltaX(minus_delta_x, x); + _convergence_criterion->checkDeltaX(minus_delta_x, + *x[process_id]); } error_norms_met = _convergence_criterion->isSatisfied(); diff --git a/NumLib/ODESolver/NonlinearSolver.h b/NumLib/ODESolver/NonlinearSolver.h index 4ec739bbcc01e09c87a57691d271114e2b83638d..bcffe0a4a476e2cbd6a2b108d461396ec2847c57 100644 --- a/NumLib/ODESolver/NonlinearSolver.h +++ b/NumLib/ODESolver/NonlinearSolver.h @@ -46,7 +46,7 @@ public: * assembled. * \param process_id the process' id which will be assembled. */ - virtual void assemble(GlobalVector const& x, + virtual void assemble(std::vector<GlobalVector*> const& x, int const process_id) const = 0; /*! Assemble and solve the equation system. @@ -59,7 +59,7 @@ public: * \retval false otherwise */ virtual NonlinearSolverStatus solve( - GlobalVector& x, + std::vector<GlobalVector*>& x, std::function<void(int, GlobalVector const&)> const& postIterationCallback, int const process_id) = 0; @@ -110,10 +110,11 @@ public: _convergence_criterion = &conv_crit; } - void assemble(GlobalVector const& x, int const process_id) const override; + void assemble(std::vector<GlobalVector*> const& x, + int const process_id) const override; NonlinearSolverStatus solve( - GlobalVector& x, + std::vector<GlobalVector*>& x, std::function<void(int, GlobalVector const&)> const& postIterationCallback, int const process_id) override; @@ -171,10 +172,11 @@ public: _convergence_criterion = &conv_crit; } - void assemble(GlobalVector const& x, int const process_id) const override; + void assemble(std::vector<GlobalVector*> const& x, + int const process_id) const override; NonlinearSolverStatus solve( - GlobalVector& x, + std::vector<GlobalVector*>& x, std::function<void(int, GlobalVector const&)> const& postIterationCallback, int const process_id) override; diff --git a/NumLib/ODESolver/NonlinearSystem.h b/NumLib/ODESolver/NonlinearSystem.h index d5367eae3cd81075e24b247a6af0031983de2cc7..196b00b7def03abb79e32ea6d9e3d81f67e35828 100644 --- a/NumLib/ODESolver/NonlinearSystem.h +++ b/NumLib/ODESolver/NonlinearSystem.h @@ -37,7 +37,8 @@ public: //! Assembles the linearized equation system at the point \c x. //! The linearized system is \f$A(x) \cdot x = b(x)\f$. Here the matrix //! \f$A(x)\f$ and the vector \f$b(x)\f$ are assembled. - virtual void assemble(GlobalVector const& x, int const process_id) = 0; + virtual void assemble(std::vector<GlobalVector*> const& x, + int const process_id) = 0; /*! Writes the residual at point \c x to \c res. * @@ -83,7 +84,8 @@ public: //! Assembles the linearized equation system at the point \c x. //! The linearized system is \f$J(x) \cdot \Delta x = (x)\f$. Here the //! residual vector \f$r(x)\f$ and its Jacobian \f$J(x)\f$ are assembled. - virtual void assemble(GlobalVector const& x, int const process_id) = 0; + virtual void assemble(std::vector<GlobalVector*> const& x, + int const process_id) = 0; //! Writes the linearized equation system matrix to \c A. //! \pre assemble() must have been called before. diff --git a/NumLib/ODESolver/TimeDiscretizedODESystem.cpp b/NumLib/ODESolver/TimeDiscretizedODESystem.cpp index d57c682f41219d6809c587f72a682ec3fb388506..dd45a353b0bd2af70967df9387d2abfcb560f919 100644 --- a/NumLib/ODESolver/TimeDiscretizedODESystem.cpp +++ b/NumLib/ODESolver/TimeDiscretizedODESystem.cpp @@ -69,21 +69,21 @@ TimeDiscretizedODESystem< NumLib::GlobalVectorProvider::provider.releaseVector(*_b); } -void TimeDiscretizedODESystem< - ODESystemTag::FirstOrderImplicitQuasilinear, - NonlinearSolverTag::Newton>::assemble(const GlobalVector& x_new_timestep, - int const process_id) +void TimeDiscretizedODESystem<ODESystemTag::FirstOrderImplicitQuasilinear, + NonlinearSolverTag::Newton>:: + assemble(std::vector<GlobalVector*> const& x_new_timestep, + int const process_id) { namespace LinAlg = MathLib::LinAlg; auto const t = _time_disc.getCurrentTime(); auto const dt = _time_disc.getCurrentTimeIncrement(); - auto const& x_curr = _time_disc.getCurrentX(x_new_timestep); + auto const& x_curr = _time_disc.getCurrentX(*x_new_timestep[process_id]); auto const dxdot_dx = _time_disc.getNewXWeight(); auto const dx_dx = _time_disc.getDxDx(); auto& xdot = NumLib::GlobalVectorProvider::provider.getVector(_xdot_id); - _time_disc.getXdot(x_new_timestep, xdot); + _time_disc.getXdot(*x_new_timestep[process_id], xdot); _M->setZero(); _K->setZero(); @@ -188,16 +188,16 @@ TimeDiscretizedODESystem< NumLib::GlobalVectorProvider::provider.releaseVector(*_b); } -void TimeDiscretizedODESystem< - ODESystemTag::FirstOrderImplicitQuasilinear, - NonlinearSolverTag::Picard>::assemble(const GlobalVector& x_new_timestep, - int const process_id) +void TimeDiscretizedODESystem<ODESystemTag::FirstOrderImplicitQuasilinear, + NonlinearSolverTag::Picard>:: + assemble(std::vector<GlobalVector*> const& x_new_timestep, + int const process_id) { namespace LinAlg = MathLib::LinAlg; auto const t = _time_disc.getCurrentTime(); auto const dt = _time_disc.getCurrentTimeIncrement(); - auto const& x_curr = _time_disc.getCurrentX(x_new_timestep); + auto const& x_curr = _time_disc.getCurrentX(*x_new_timestep[process_id]); _M->setZero(); _K->setZero(); diff --git a/NumLib/ODESolver/TimeDiscretizedODESystem.h b/NumLib/ODESolver/TimeDiscretizedODESystem.h index 9fa14e095fe7000f4ed7cb3e990b2de79317c573..3c533b04adca4c623ff0c858a59141babe2dccd1 100644 --- a/NumLib/ODESolver/TimeDiscretizedODESystem.h +++ b/NumLib/ODESolver/TimeDiscretizedODESystem.h @@ -83,7 +83,7 @@ public: ~TimeDiscretizedODESystem() override; - void assemble(const GlobalVector& x_new_timestep, + void assemble(std::vector<GlobalVector*> const& x_new_timestep, int const process_id) override; void getResidual(GlobalVector const& x_new_timestep, @@ -181,7 +181,7 @@ public: ~TimeDiscretizedODESystem() override; - void assemble(const GlobalVector& x_new_timestep, + void assemble(std::vector<GlobalVector*> const& x_new_timestep, int const process_id) override; void getA(GlobalMatrix& A) const override diff --git a/ProcessLib/TimeLoop.cpp b/ProcessLib/TimeLoop.cpp index 96e35a35b795db881f8bef16e7d8fb78aca353e9..f0753cf8a5f6cd4a7c950e5a7cd1c0d213881802 100644 --- a/ProcessLib/TimeLoop.cpp +++ b/ProcessLib/TimeLoop.cpp @@ -157,7 +157,7 @@ std::vector<GlobalVector*> setInitialConditions( auto const nl_tag = process_data->nonlinear_solver_tag; setEquationSystem(nonlinear_solver, ode_sys, conv_crit, nl_tag); - nonlinear_solver.assemble(x0, process_id); + nonlinear_solver.assemble(process_solutions, process_id); time_disc.pushState( t0, x0, mat_strg); // TODO: that might do duplicate work @@ -168,7 +168,7 @@ std::vector<GlobalVector*> setInitialConditions( } NumLib::NonlinearSolverStatus solveOneTimeStepOneProcess( - GlobalVector& x, std::size_t const timestep, double const t, + std::vector<GlobalVector*>& x, std::size_t const timestep, double const t, double const delta_t, ProcessData const& process_data, Output& output_control) { @@ -200,7 +200,7 @@ NumLib::NonlinearSolverStatus solveOneTimeStepOneProcess( if (nonlinear_solver_status.error_norms_met) { - process.postNonLinearSolver(x, t, delta_t, process_id); + process.postNonLinearSolver(*x[process_id], t, delta_t, process_id); } return nonlinear_solver_status; @@ -535,7 +535,8 @@ void preTimestepForAllProcesses( static NumLib::NonlinearSolverStatus solveMonolithicProcess( const double t, const double dt, const std::size_t timestep_id, - ProcessData const& process_data, GlobalVector& x, Output& output) + ProcessData const& process_data, std::vector<GlobalVector*>& x, + Output& output) { BaseLib::RunTime time_timestep_process; time_timestep_process.start(); @@ -588,9 +589,8 @@ NumLib::NonlinearSolverStatus TimeLoop::solveUncoupledEquationSystems( for (auto& process_data : _per_process_data) { auto const process_id = process_data->process_id; - nonlinear_solver_status = - solveMonolithicProcess(t, dt, timestep_id, *process_data, - *_process_solutions[process_id], *_output); + nonlinear_solver_status = solveMonolithicProcess( + t, dt, timestep_id, *process_data, _process_solutions, *_output); process_data->nonlinear_solver_status = nonlinear_solver_status; if (!nonlinear_solver_status.error_norms_met) @@ -662,8 +662,9 @@ TimeLoop::solveCoupledEquationSystemsByStaggeredScheme( process_data->process.setCoupledSolutionsForStaggeredScheme( &coupled_solutions); - nonlinear_solver_status = solveOneTimeStepOneProcess( - x, timestep_id, t, dt, *process_data, *_output); + nonlinear_solver_status = + solveOneTimeStepOneProcess(_process_solutions, timestep_id, t, + dt, *process_data, *_output); process_data->nonlinear_solver_status = nonlinear_solver_status; INFO(