NonlinearScheme_Picard Class
This class inherits from the base class 'NonlinearScheme' to implement the Picard nonlinear scheme for solving nonlinear systems of equations. It is based on a fully implicit time integration scheme and includes an optional relaxation mechanism to improve relaxation mechanism to improve convergence.
Reference: Li and Wei (2015). An efficient finite element procedure for analyzing three‐phase porous media based on the relaxed Picard method. Int J Numer Methods Eng, 101(11):825-846.
Contents
Authors
- Danilo Cavalcanti
Class definition
classdef NonlinearScheme_Picard < NonlinearScheme
Public properties
properties(SetAccess = public,GetAccess = public)
relax = 1.0;
applyRelaxation = false;
end
Constructor method
methods %------------------------------------------------------------------ function this = NonlinearScheme_Picard() this = this@NonlinearScheme(); end end
Public methods
methods %------------------------------------------------------------------ % Assemble the Jacobian matrix and the residual vector. function [A,b] = assembleLinearSystem(~,C,K,~,fe,dfidx,~,xOld,dt) % RHS vector b = C * xOld / dt + fe; % LHS matrix A = K + dfidx + C / dt; end %------------------------------------------------------------------ % Apply boundary conditions to the right-hand side of the system. function bf = applyBCtoRHS(~,A,b,x,doffree,doffixed) bf = b(doffree) - A(doffree,doffixed) * x(doffixed); end %------------------------------------------------------------------ % Add nodal forces to the right-hand side vector. function b = addNodalForces(~,b,fe) b = b + fe; end %------------------------------------------------------------------ % Evaluate the solution increment and updates the solution vector. function [X,dx] = eval(this,A,b,X,dxOld,freedof,iter) XOld = X; X(freedof) = A\b; if this.applyRelaxation if iter > 1 this.updateRelaxation(X,XOld,dxOld); X(freedof) = this.relax * X(freedof) + (1.0 - this.relax) * XOld(freedof); end end dx = X - XOld; end %------------------------------------------------------------------ % Check for convergence of the nonlinear scheme. function convFlg = convergence(this,X,~,dX,~, doffree,iter,echo) % Evaluate error normError = norm(dX(doffree)); if this.normalizeError normError = normError / norm(X(doffree)); end % Check convergence if (norm(normError) < this.tol) && (iter > 1) convFlg = true; else convFlg = false; end if echo fprintf("\t\t iter.: %3d , ||dX||/||X|| = %7.3e \n",iter,normError); end end %------------------------------------------------------------------ % Update the relaxation parameter based on the generalized angle % between successive increments. function updateRelaxation(this,X,XOld,dxOld) dx = X - XOld; % Compute generalized angle between successive increments gamma = acos((dx' * dxOld) / norm(dx) * norm(dxOld)); % Update relaxation parameter if (gamma < pi/4.0) this.relax = min(this.relax * 2.0, 1.0); elseif (gamma > pi/2.0) this.relax = this.relax / 2.0; end end end
end