diff --git a/src/petsc4Foam/solvers/petscSolver.C b/src/petsc4Foam/solvers/petscSolver.C
index 6718ff6deb026573c3e276bd26809c2563e347a9..690d45a4405f5f421744af83182795a23e2784bc 100644
--- a/src/petsc4Foam/solvers/petscSolver.C
+++ b/src/petsc4Foam/solvers/petscSolver.C
@@ -157,14 +157,11 @@ Foam::solverPerformance Foam::petscSolver::scalarSolve
     List<label>& lowNonZero = ctx.lowNonZero;
     label& maxLowNonZeroPerRow = ctx.maxLowNonZeroPerRow;
 
-    bool needsCacheUpdate = true;
-
     if (!ctx.initialized())
     {
         DebugInfo<< "Initializing PETSc Linear Solver " << eqName_ << nl;
 
         ctx.initialized() = true;
-        needsCacheUpdate = false;
 
         PetscLogStageRegister
         (
@@ -172,20 +169,30 @@ Foam::solverPerformance Foam::petscSolver::scalarSolve
             &ctx.matstage
         );
         PetscLogStageRegister
+        (
+            ("foam_" + eqName_ + "_pc").c_str(),
+            &ctx.pcstage
+        );
+        PetscLogStageRegister
         (
             ("foam_" + eqName_ + "_ksp").c_str(),
             &ctx.kspstage
         );
-        computeMatAllocation(Amat, lowNonZero, maxLowNonZeroPerRow);
-        buildMat(Amat, lowNonZero, maxLowNonZeroPerRow, ctx.matstage);
+        PetscLogStagePush(ctx.matstage);
+        buildMat(Amat, lowNonZero, maxLowNonZeroPerRow);
+        PetscLogStagePop();
         buildKsp(Amat, ksp);
     }
 
-    if (ctx.caching.needsMatrixUpdate() && needsCacheUpdate)
+    bool matup = ctx.caching.needsMatrixUpdate();
+    bool pcup = ctx.caching.needsPrecondUpdate();
+    if (matup)
     {
-        buildMat(Amat, lowNonZero, maxLowNonZeroPerRow, ctx.matstage);
-        updateKsp(ksp, Amat, !ctx.caching.needsPrecondUpdate());
+        PetscLogStagePush(ctx.matstage);
+        updateMat(Amat, lowNonZero, maxLowNonZeroPerRow);
+        PetscLogStagePop();
     }
+    updateKsp(ksp, Amat, !pcup);
 
     // Use built-in residual norm computation
     const bool usePetscResidualNorm
@@ -273,24 +280,24 @@ Foam::solverPerformance Foam::petscSolver::scalarSolve
     // Monitoring (print to stdout) residual reduction in OpenFOAM norm
     if (monitorFoamResidualNorm)
     {
-       KSPMonitorSet
-       (
-           ksp,
-           PetscUtils::foamKSPMonitorFoam,
-           &ctx,
-           NULL
-       );
+        KSPMonitorSet
+        (
+            ksp,
+            PetscUtils::foamKSPMonitorFoam,
+            &ctx,
+            NULL
+        );
     }
 
-    PetscLogStagePush(ctx.kspstage);
-
     // Setup KSP (this is not explicitly needed, but we call it to separate
     // PCSetUp from KSPSolve timings when requesting -log_view from PETSc)
+    PetscLogStagePush(ctx.pcstage);
     KSPSetUp(ksp);
+    PetscLogStagePop();
 
     // Solve A x = b
+    PetscLogStagePush(ctx.kspstage);
     KSPSolve(ksp, petsc_source, petsc_psi);
-
     PetscLogStagePop();
 
     // Set nIterations and final residual
@@ -336,15 +343,15 @@ void Foam::petscSolver::updateKsp
     const bool reuse
 ) const
 {
-    DebugInfo<< "Cache-Hit: updating PETSc Amat " << eqName_ << nl;
-
     if (reuse)
     {
+        DebugInfo<< "Cache-Hit: reuse preconditioner " << eqName_ << nl;
+
         KSPSetReusePreconditioner(ksp, PETSC_TRUE);
     }
     else
     {
-        DebugInfo<< "Cache-Hit: updating PETSc Pmat " << eqName_ << nl;
+        DebugInfo<< "Cache-Hit: rebuild preconditioner " << eqName_ << nl;
 
         KSPSetReusePreconditioner(ksp, PETSC_FALSE);
     }
@@ -393,7 +400,7 @@ void Foam::petscSolver::buildKsp
 }
 
 
-void Foam::petscSolver::computeMatAllocation
+void Foam::petscSolver::buildMat
 (
     Mat& Amat,
     List<label>& lowNonZero,
@@ -505,7 +512,7 @@ void Foam::petscSolver::computeMatAllocation
         nonZeroNeigh_.data()
     );
 
-    // The general AIJ preallocator do not handle SELL
+    // The general AIJ preallocator does not handle SELL
     MatSeqSELLSetPreallocation
     (
         Amat,
@@ -537,16 +544,13 @@ void Foam::petscSolver::computeMatAllocation
 }
 
 
-void Foam::petscSolver::buildMat
+void Foam::petscSolver::updateMat
 (
     Mat& Amat,
     List<label>& lowNonZero,
-    label& maxLowNonZeroPerRow,
-    PetscLogStage stage
+    label& maxLowNonZeroPerRow
 ) const
 {
-    PetscLogStagePush(stage);
-
     const lduAddressing& lduAddr = matrix_.mesh().lduAddr();
     const lduInterfacePtrsList interfaces(matrix_.mesh().interfaces());
 
@@ -727,7 +731,6 @@ void Foam::petscSolver::buildMat
 
     MatAssemblyBegin(Amat, MAT_FINAL_ASSEMBLY);
     MatAssemblyEnd(Amat, MAT_FINAL_ASSEMBLY);
-    PetscLogStagePop();
 }
 
 
diff --git a/src/petsc4Foam/solvers/petscSolver.H b/src/petsc4Foam/solvers/petscSolver.H
index d0287a55c4e463661fa72e2aa1c099238bc088fa..983ba27b452a152d87315e0701b743c8fb44c1ac 100644
--- a/src/petsc4Foam/solvers/petscSolver.H
+++ b/src/petsc4Foam/solvers/petscSolver.H
@@ -93,20 +93,19 @@ class petscSolver
 
         //- Compute allocation (proc and off-proc)
         //- for the petsc matrix Amat_
-        void computeMatAllocation
+        void buildMat
         (
             Mat& Amat,
             List<label>& lowNonZero,
             label& maxLowNonZeroPerRow
         ) const;
 
-        //- Build Amat_ matrix by inserting new values
-        void buildMat
+        //- Update Amat_ matrix by inserting new values
+        void updateMat
         (
             Mat& Amat,
             List<label>& lowNonZero,
-            label& maxLowNonZeroPerRow,
-            PetscLogStage stage
+            label& maxLowNonZeroPerRow
         ) const;
 
         //- Build the ksp_ krylov solver context
diff --git a/src/petsc4Foam/utils/petscCacheManager.H b/src/petsc4Foam/utils/petscCacheManager.H
index 701562822db3eea81bdad4048be4bf10fc30cfa4..f6d5cdd05305c023d3c4225b09328d35a76debb7 100644
--- a/src/petsc4Foam/utils/petscCacheManager.H
+++ b/src/petsc4Foam/utils/petscCacheManager.H
@@ -162,8 +162,9 @@ class petscCacheManager
 {
     // Private Data
 
-        //- The current (relative) iteration
-        label iter;
+        //- The current (relative) iterations for matrix and preconditioner
+        label miter;
+        label piter;
 
         PetscUtils::Caching matrixCaching;
         PetscUtils::Caching precondCaching;
@@ -176,7 +177,8 @@ public:
         //- Default construct
         petscCacheManager()
         :
-            iter{0}
+            miter{0},
+            piter{0}
         {}
 
 
@@ -195,12 +197,12 @@ public:
 
     bool needsMatrixUpdate()
     {
-        return needsUpdate(matrixCaching, iter);
+        return needsUpdate(matrixCaching, miter);
     }
 
     bool needsPrecondUpdate()
     {
-        return needsUpdate(precondCaching, iter);
+        return needsUpdate(precondCaching, piter);
     }
 
     void eventBegin()
@@ -219,11 +221,11 @@ public:
             // Elapsed timing interval (s)
             precondCaching.timeIter = precondCaching.timer_.elapsed();
 
-            if (iter == 0)
+            if (piter == 0)
             {
                 precondCaching.time0 = precondCaching.timeIter;
             }
-            else if (iter == 1)
+            else if (piter == 1)
             {
                 precondCaching.time1 = precondCaching.timeIter;
             }
@@ -235,8 +237,16 @@ public:
          || precondCaching.updateType_ == PetscUtils::Caching::Adaptive
         )
         {
-            ++iter;
+            ++piter;
         }
+        if
+        (
+            matrixCaching.updateType_ == PetscUtils::Caching::Periodic
+        )
+        {
+            ++miter;
+        }
+
     }
 
 
@@ -276,14 +286,14 @@ private:
 
             case PetscUtils::Caching::Adaptive:
             {
-                need = false;
                 if (iter > 3) // we need at least three times
                 {
+                    need = false;
                     const double ratio0 =
-                        precondCaching.time0 / precondCaching.timeIter;
+                        caching.time0 / caching.timeIter;
 
                     const double ratio1 =
-                        precondCaching.time1 / precondCaching.timeIter;
+                        caching.time1 / caching.timeIter;
 
                     const int nsteps =
                         min(1e5, ratio0 * (1. / mag(1. - ratio1 + 1e-6)));
diff --git a/src/petsc4Foam/utils/petscLinearSolverContext.H b/src/petsc4Foam/utils/petscLinearSolverContext.H
index 7eb25b7e040e244509f701d7f3c36883241ca5fa..21b4873ebe85d82277923da8861daf13e761c35d 100644
--- a/src/petsc4Foam/utils/petscLinearSolverContext.H
+++ b/src/petsc4Foam/utils/petscLinearSolverContext.H
@@ -70,6 +70,7 @@ public:
         KSP ksp;
 
         PetscLogStage matstage;
+        PetscLogStage pcstage;
         PetscLogStage kspstage;
 
         solverPerformance performance;
@@ -92,23 +93,21 @@ public:
         :
             init_(false),
             init_aux_vectors_(false)
-        {}
+        {
+            Amat = NULL;
+            ksp = NULL;
+            ArowsSum = NULL;
+            res_l1_w = NULL;
+        }
 
 
     //- Destructor
     virtual ~petscLinearSolverContext()
     {
-        if (init_)
-        {
-            MatDestroy(&Amat);
-            KSPDestroy(&ksp);
-        }
-
-        if (init_aux_vectors_)
-        {
-            VecDestroy(&ArowsSum);
-            VecDestroyVecs(2,&res_l1_w);
-        }
+        MatDestroy(&Amat);
+        KSPDestroy(&ksp);
+        VecDestroy(&ArowsSum);
+        if (res_l1_w) VecDestroyVecs(2,&res_l1_w);
     }