diff --git a/src/optimisation/adjointOptimisation/adjoint/objectiveManager/objectiveManager/objectiveManager.C b/src/optimisation/adjointOptimisation/adjoint/objectiveManager/objectiveManager/objectiveManager.C
index 89c6ef89be01d14b199e68009cf9b7fe185d5ed7..cd3cdc7c0d2610360830759d9debd8e2fdbed87f 100644
--- a/src/optimisation/adjointOptimisation/adjoint/objectiveManager/objectiveManager/objectiveManager.C
+++ b/src/optimisation/adjointOptimisation/adjoint/objectiveManager/objectiveManager/objectiveManager.C
@@ -151,12 +151,16 @@ bool objectiveManager::readDict(const dictionary& dict)
     return true;
 }
 
+
 void objectiveManager::updateNormalizationFactor()
 {
     // Update normalization factors for all objectives
     for (objective& obj : objectives_)
     {
-        obj.updateNormalizationFactor();
+        if (obj.normalize())
+        {
+            obj.updateNormalizationFactor();
+        }
     }
 }
 
diff --git a/src/optimisation/adjointOptimisation/adjoint/objectives/incompressible/objectiveIncompressible/objectiveIncompressible.C b/src/optimisation/adjointOptimisation/adjoint/objectives/incompressible/objectiveIncompressible/objectiveIncompressible.C
index ac7fa6fb1f6895960253a57b626bde936f22854b..1ce8b4caa4e6576e4736f0f5c558fe390e0b2a14 100644
--- a/src/optimisation/adjointOptimisation/adjoint/objectives/incompressible/objectiveIncompressible/objectiveIncompressible.C
+++ b/src/optimisation/adjointOptimisation/adjoint/objectives/incompressible/objectiveIncompressible/objectiveIncompressible.C
@@ -128,6 +128,67 @@ autoPtr<objectiveIncompressible> objectiveIncompressible::New
 
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
+void objectiveIncompressible::doNormalization()
+{
+    if (normalize_ && normFactor_.valid())
+    {
+        const scalar oneOverNorm(1./normFactor_());
+
+        if (hasdJdv())
+        {
+            dJdvPtr_().primitiveFieldRef() *= oneOverNorm;
+        }
+        if (hasdJdp())
+        {
+            dJdpPtr_().primitiveFieldRef() *= oneOverNorm;
+        }
+        if (hasdJdT())
+        {
+            dJdTPtr_().primitiveFieldRef() *= oneOverNorm;
+        }
+        if (hasdJdTMVar1())
+        {
+            dJdTMvar1Ptr_().primitiveFieldRef() *= oneOverNorm;
+        }
+        if (hasdJdTMVar2())
+        {
+            dJdTMvar2Ptr_().primitiveFieldRef() *= oneOverNorm;
+        }
+        if (hasBoundarydJdv())
+        {
+            bdJdvPtr_() *= oneOverNorm;
+        }
+        if (hasBoundarydJdvn())
+        {
+            bdJdvnPtr_() *= oneOverNorm;
+        }
+        if (hasBoundarydJdvt())
+        {
+            bdJdvtPtr_() *= oneOverNorm;
+        }
+        if (hasBoundarydJdp())
+        {
+            bdJdpPtr_() *= oneOverNorm;
+        }
+        if (hasBoundarydJdT())
+        {
+            bdJdTPtr_() *= oneOverNorm;
+        }
+        if (hasBoundarydJdTMVar1())
+        {
+            bdJdTMvar1Ptr_() *= oneOverNorm;
+        }
+        if (hasBoundarydJdTMVar2())
+        {
+            bdJdTMvar2Ptr_() *= oneOverNorm;
+        }
+
+        // Normalize geometric fields
+        objective::doNormalization();
+    }
+}
+
+
 const volVectorField& objectiveIncompressible::dJdv()
 {
     if (dJdvPtr_.empty())
@@ -418,6 +479,9 @@ void objectiveIncompressible::update()
     update_dxdbDirectMultiplier();
     update_boundaryEdgeContribution();
     update_dJdStressMultiplier();
+
+    // Divide everything with normalization factor
+    doNormalization();
 }
 
 
diff --git a/src/optimisation/adjointOptimisation/adjoint/objectives/incompressible/objectiveIncompressible/objectiveIncompressible.H b/src/optimisation/adjointOptimisation/adjoint/objectives/incompressible/objectiveIncompressible/objectiveIncompressible.H
index 1bf89badd9675411198c7030bed5ead2eb81ab5a..19dad8107568226620cc8d1ad0e78b4d1604e4db 100644
--- a/src/optimisation/adjointOptimisation/adjoint/objectives/incompressible/objectiveIncompressible/objectiveIncompressible.H
+++ b/src/optimisation/adjointOptimisation/adjoint/objectives/incompressible/objectiveIncompressible/objectiveIncompressible.H
@@ -165,6 +165,9 @@ public:
         //- Return the objective function value
         virtual scalar J() = 0;
 
+        //- Normalize all fields allocated by the objective
+        virtual void doNormalization();
+
         //- Contribution to field adjoint momentum eqs
         const volVectorField& dJdv();
 
diff --git a/src/optimisation/adjointOptimisation/adjoint/objectives/incompressible/objectivePtLosses/objectivePtLosses.C b/src/optimisation/adjointOptimisation/adjoint/objectives/incompressible/objectivePtLosses/objectivePtLosses.C
index d4f43c7afc62d9471c3f13d58ac4eab0019ffe4d..c0e0abd2ff7830eb437f7bd49ba2ad689154e4c4 100644
--- a/src/optimisation/adjointOptimisation/adjoint/objectives/incompressible/objectivePtLosses/objectivePtLosses.C
+++ b/src/optimisation/adjointOptimisation/adjoint/objectives/incompressible/objectivePtLosses/objectivePtLosses.C
@@ -247,6 +247,7 @@ void objectivePtLosses::write() const
             setObjectiveFilePtr();
             objFunctionFilePtr_() << setw(4)     << "#"        << " ";
             objFunctionFilePtr_() << setw(width) << "ptLosses" << " ";
+            objFunctionFilePtr_() << setw(width) << "JCycle"   << " ";
             forAll(patches_, oI)
             {
                 label patchI = patches_[oI];
@@ -258,6 +259,7 @@ void objectivePtLosses::write() const
 
         objFunctionFilePtr_() << setw(4)     << mesh_.time().value() << " ";
         objFunctionFilePtr_() << setw(width) << J_ << " ";
+        objFunctionFilePtr_() << setw(width) << JCycle() << " ";
         forAll(patchPt_, pI)
         {
             objFunctionFilePtr_() << setw(width) << patchPt_[pI] << " ";
diff --git a/src/optimisation/adjointOptimisation/adjoint/objectives/incompressible/objectivePtLosses/objectivePtLosses.H b/src/optimisation/adjointOptimisation/adjoint/objectives/incompressible/objectivePtLosses/objectivePtLosses.H
index 0953add4055ae64fb8f453d478c16437c3b89409..99ce83439cc06627db9767426ab6c268a2f897c5 100644
--- a/src/optimisation/adjointOptimisation/adjoint/objectives/incompressible/objectivePtLosses/objectivePtLosses.H
+++ b/src/optimisation/adjointOptimisation/adjoint/objectives/incompressible/objectivePtLosses/objectivePtLosses.H
@@ -59,8 +59,10 @@ class objectivePtLosses
 {
     // Private data
 
+        //- Patches on which to compute losses
         labelList patches_;
 
+        //- Total pressure per patch on patches_
         scalarField patchPt_;
 
 
diff --git a/src/optimisation/adjointOptimisation/adjoint/objectives/objective/objective.C b/src/optimisation/adjointOptimisation/adjoint/objectives/objective/objective.C
index a8ee9c77e15b151a0d4b2cbf4bf861e5689de4a7..1eb423c0b8e9e3a4df1b6c8bd505be7f84c3abf8 100644
--- a/src/optimisation/adjointOptimisation/adjoint/objectives/objective/objective.C
+++ b/src/optimisation/adjointOptimisation/adjoint/objectives/objective/objective.C
@@ -129,10 +129,13 @@ objective::objective
     objectiveName_(dict.dictName()),
     computeMeanFields_(false), // is reset in derived classes
     nullified_(false),
+    normalize_(dict.getOrDefault<bool>("normalize", false)),
 
     J_(Zero),
     JMean_(this->getOrDefault<scalar>("JMean", Zero)),
     weight_(Zero),
+    normFactor_(nullptr),
+    target_(dict.getOrDefault<scalar>("target", Zero)),
 
     integrationStartTimePtr_(nullptr),
     integrationEndTimePtr_(nullptr),
@@ -174,6 +177,20 @@ objective::objective
             new scalar(dict.get<scalar>("integrationEndTime"))
         );
     }
+
+    // Set normalization factor, if present
+    if (normalize_)
+    {
+        scalar normFactor(Zero);
+        if (dict.readIfPresent("normFactor", normFactor))
+        {
+            normFactor_.reset(new scalar(normFactor));
+        }
+        else if (this->readIfPresent("normFactor", normFactor))
+        {
+            normFactor_.reset(new scalar(normFactor));
+        }
+    }
 }
 
 
@@ -234,13 +251,26 @@ scalar objective::JCycle() const
     {
         J = JMean_;
     }
+
+    // Subtract target, in case the objective is used as a constraint
+    J -= target_;
+
+    // Normalize here, in order to get the correct value for line search
+    if (normalize_ && normFactor_.valid())
+    {
+        J /= normFactor_();
+    }
+
     return J;
 }
 
 
 void objective::updateNormalizationFactor()
 {
-    // Does nothing in base
+    if (normalize_ && normFactor_.empty())
+    {
+        normFactor_.reset(new scalar(JCycle()));
+    }
 }
 
 
@@ -289,6 +319,62 @@ scalar objective::weight() const
 }
 
 
+bool objective::normalize() const
+{
+    return normalize_;
+}
+
+
+void objective::doNormalization()
+{
+    if (normalize_ && normFactor_.valid())
+    {
+        const scalar oneOverNorm(1./normFactor_());
+
+        if (hasdJdb())
+        {
+            dJdbPtr_().primitiveFieldRef() *= oneOverNorm;
+        }
+        if (hasBoundarydJdb())
+        {
+            bdJdbPtr_() *= oneOverNorm;
+        }
+        if (hasdSdbMult())
+        {
+            bdSdbMultPtr_() *= oneOverNorm;
+        }
+        if (hasdndbMult())
+        {
+            bdndbMultPtr_() *= oneOverNorm;
+        }
+        if (hasdxdbMult())
+        {
+            bdxdbMultPtr_() *= oneOverNorm;
+        }
+        if (hasdxdbDirectMult())
+        {
+            bdxdbDirectMultPtr_() *= oneOverNorm;
+        }
+        if (hasBoundaryEdgeContribution())
+        {
+            bEdgeContribution_() *= oneOverNorm;
+        }
+        if (hasDivDxDbMult())
+        {
+            divDxDbMultPtr_() *= oneOverNorm;
+        }
+        if (hasGradDxDbMult())
+        {
+            gradDxDbMultPtr_() *= oneOverNorm;
+        }
+        if (hasBoundarydJdStress())
+        {
+            bdJdStressPtr_() *= oneOverNorm;
+        }
+    }
+}
+
+
 bool objective::isWithinIntegrationTime() const
 {
     if (hasIntegrationStartTime() && hasIntegrationEndTime())
@@ -667,6 +753,10 @@ void objective::writeMeanValue() const
 bool objective::writeData(Ostream& os) const
 {
     os.writeEntry("JMean", JMean_);
+    if (normFactor_.valid())
+    {
+        os.writeEntry("normFactor", normFactor_());
+    }
     return os.good();
 }
 
diff --git a/src/optimisation/adjointOptimisation/adjoint/objectives/objective/objective.H b/src/optimisation/adjointOptimisation/adjoint/objectives/objective/objective.H
index 7fc69c3f5f9f95fd3f94313ca7f29789f2fe035b..56cf28ed46db79b33e74ec4a1a180812204d3fe2 100644
--- a/src/optimisation/adjointOptimisation/adjoint/objectives/objective/objective.H
+++ b/src/optimisation/adjointOptimisation/adjoint/objectives/objective/objective.H
@@ -72,6 +72,7 @@ protected:
         const word objectiveName_;
         bool computeMeanFields_;
         bool nullified_;
+        bool normalize_;
 
         //- Objective function value and weight
         scalar J_;
@@ -82,12 +83,21 @@ protected:
         //- Objective weight
         scalar weight_;
 
-        // Objective integration start and end times (for unsteady flows)
+        //- Normalization factor
+        autoPtr<scalar> normFactor_;
+
+        //- Target value, in case the objective is used as a constraint
+        //  Should be used in caution and with updateMethods than get affected
+        //  by the target value, without requiring a sqr (e.g. SQP, MMA)
+        scalar target_;
+
+        //- Objective integration start and end times (for unsteady flows)
         autoPtr<scalar> integrationStartTimePtr_;
         autoPtr<scalar> integrationEndTimePtr_;
 
-        // Contribution to field sensitivity derivatives
-        // Topology optimisation
+        //- Contribution to field sensitivity derivatives
+        //  Topology optimisation or other variants with
+        //  as many design variables as the mesh cells
         //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
         autoPtr<volScalarField> dJdbPtr_;
@@ -248,6 +258,12 @@ public:
         //- Return the objective function weight
         scalar weight() const;
 
+        //- Is the objective normalized
+        bool normalize() const;
+
+        //- Normalize all fields allocated by the objective
+        virtual void doNormalization();
+
         //- Check whether this is an objective integration time
         bool isWithinIntegrationTime() const;