Line data Source code
1 : //* This file is part of the MOOSE framework 2 : //* https://mooseframework.inl.gov 3 : //* 4 : //* All rights reserved, see COPYRIGHT for full restrictions 5 : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT 6 : //* 7 : //* Licensed under LGPL 2.1, please see LICENSE for details 8 : //* https://www.gnu.org/licenses/lgpl-2.1.html 9 : 10 : #include "AdjointTransientSolve.h" 11 : 12 : #include "FEProblemBase.h" 13 : #include "NonlinearSystemBase.h" 14 : #include "MooseUtils.h" 15 : 16 : #include "libmesh/sparse_matrix.h" 17 : #include "libmesh/numeric_vector.h" 18 : 19 : using namespace libMesh; 20 : 21 : InputParameters 22 244 : AdjointTransientSolve::validParams() 23 : { 24 244 : InputParameters params = AdjointSolve::validParams(); 25 244 : return params; 26 : } 27 : 28 122 : AdjointTransientSolve::AdjointTransientSolve(Executioner & ex) 29 : : AdjointSolve(ex), 30 : Restartable(this, "Executioners"), 31 244 : _old_time_residual(_nl_adjoint.getResidualTimeVector()), 32 244 : _forward_solutions(declareRecoverableData<std::vector<std::string>>("forward_solutions")) 33 : { 34 122 : } 35 : 36 : bool 37 5142 : AdjointTransientSolve::solve() 38 : { 39 5142 : bool converged = AdjointSolve::solve(); 40 : 41 : // Gather the contribution of this timestep to add to the next solve's source 42 5142 : if (converged) 43 5142 : evaluateTimeResidual(_nl_adjoint.solution(), _old_time_residual); 44 : 45 5142 : return converged; 46 : } 47 : 48 : void 49 5705 : AdjointTransientSolve::insertForwardSolution(int tstep) 50 : { 51 : // Time step should not be negative 52 5705 : if (tstep < 0) 53 0 : mooseError("Negative time step occurred."); 54 5705 : auto t_step = cast_int<std::size_t>(tstep); // Avoid compiler warnings 55 : // Should not be inserting a time greater the last one inserted 56 5705 : if (t_step > _forward_solutions.size()) 57 0 : mooseError("Trying to insert a solution at a time-step greater than one past the previously " 58 : "inserted time step. Previous time step = ", 59 0 : (int)_forward_solutions.size() - 1, 60 : ", inserted time step = ", 61 : t_step, 62 : "."); 63 : 64 : // Add vector name to member variable if this time has not occurred 65 5705 : if (t_step == _forward_solutions.size()) 66 11410 : _forward_solutions.push_back(getForwardSolutionName(tstep)); 67 : 68 : // Get/add vector from/to adjoint system 69 5705 : auto & solution = _nl_adjoint.addVector(_forward_solutions[t_step], false, PARALLEL); 70 : 71 : // Set the vector to the inserted solution 72 5705 : solution = _nl_forward.solution(); 73 5705 : } 74 : 75 : void 76 5142 : AdjointTransientSolve::setForwardSolution(int tstep) 77 : { 78 : // Make sure the time step was saved 79 5142 : if (tstep < 0 || tstep >= cast_int<int>(_forward_solutions.size())) 80 0 : mooseError("Could not find forward solution at time step ", tstep, "."); 81 : auto t_step = cast_int<std::size_t>(tstep); // Avoid compiler warnings 82 : 83 : // Copy the solutions to states that exist in the system 84 : unsigned int state = 0; 85 15426 : while (_nl_forward.hasSolutionState(state)) 86 : { 87 10284 : const auto & name = t_step > state ? _forward_solutions[t_step - state] : _forward_solutions[0]; 88 10284 : _nl_forward.solutionState(state) = _nl_adjoint.getVector(name); 89 10284 : state++; 90 : } 91 : 92 5142 : _nl_forward.update(); 93 5142 : } 94 : 95 : void 96 5142 : AdjointTransientSolve::assembleAdjointSystem(SparseMatrix<Number> & matrix, 97 : const NumericVector<Number> & solution, 98 : NumericVector<Number> & rhs) 99 : { 100 : // Assemble the steady-state version of the adjoint problem 101 5142 : AdjointSolve::assembleAdjointSystem(matrix, solution, rhs); 102 : // Add the contribution from old solutions 103 5142 : rhs += _old_time_residual; 104 5142 : } 105 : 106 : void 107 5142 : AdjointTransientSolve::evaluateTimeResidual(const NumericVector<Number> & solution, 108 : NumericVector<Number> & residual) 109 : { 110 : // This tag should exist, but the matrix might not necessarily be added 111 5142 : auto time_matrix_tag = _problem.getMatrixTagID("TIME"); 112 : // Use the adjoint system matrix to hold the time Jacobian 113 5142 : auto & time_matrix = static_cast<ImplicitSystem &>(_nl_adjoint.system()).get_system_matrix(); 114 : 115 : // Make sure we tell the problem which system we are evaluating 116 5142 : _problem.setCurrentNonlinearSystem(_forward_sys_num); 117 : // Accumulate the time part of the Jacobian into the adjoint matrix 118 5142 : _problem.computeJacobianTag(*_nl_forward.currentSolution(), time_matrix, time_matrix_tag); 119 : 120 : // Perform multiplication of the adjoint solution on the transpose of the time Jacobian 121 5142 : residual.zero(); 122 5142 : residual.add_vector_transpose(solution, time_matrix); 123 5142 : }