steadyState                          
{                                  
    type coded;                       
    libs (utilityFunctionObjects);    
    executeControl      timeStep;
    executeInterval     1;       
                                    
    name steadyStateFO; 

                    
    codeRead
    #{
        // User settings:
        const scalar windowSize = 15;

        // FO
        Info << "Creating field to store" << endl;

        const word fieldName = "storeDiff";
        const word fieldName2 = "windowStore";

        if (!foundObject<volSymmTensorField>(fieldName))
        {
            auto tPtr = tmp<volSymmTensorField>::New
            (
                IOobject                       
                (                              
                        fieldName,                     
                        mesh().time().timeName(),    
                        mesh(),                      
                        IOobject::NO_READ,           
                        IOobject::NO_WRITE
                ),                             
                mesh(),                         
                dimensionedSymmTensor(dimless, Zero) 
            );

            mesh().objectRegistry::store(tPtr);
        }

        Info << "Creating window for steady-state definition" << endl;

        if (!foundObject<IOField<bool>>(fieldName2))
        {
            autoPtr<IOField<bool>> windowStorePtr
            (
                new IOField<bool>
                (
                    IOobject
                    (
                        fieldName2,
                        mesh().time().timeName(),  
                        mesh(),
                        IOobject::NO_READ,
                        IOobject::NO_WRITE
                    ),
                    boolList(windowSize, false)
                )
            );

            mesh().objectRegistry::store(windowStorePtr);
        }
    #};


    codeWrite                         
    #{     

        // User settings:
        const scalar absTol = 1e-6;
        const scalar numDiff = 1e-6;            

        // Calculations
        // Find A2
        const volSymmTensorField& A2_find = mesh().lookupObject<volSymmTensorField>("A2"); 

        // Initialize residual to 1
        scalar maxNumDiff{1.0};

        // Field to store the results. Later will transfer control to the mesh and work with a reference
        volSymmTensorField& store = mesh().lookupObjectRef<volSymmTensorField>("storeDiff");

        boolList& windowStore = mesh().lookupObjectRef<IOField<bool>>("windowStore");

        if (time().value() > time().startTime().value() + time().deltaT().value())
        {
            // Compute the abs difference between the current time step and the previous
            store -= A2_find ;

            // Compute the maximum value in all processors
            maxNumDiff = cmptMax(gMax(cmptMag(store))); 
        }

        // Get inital residual
        // Dictionary with the solution
        const Foam::dictionary& solverDict = mesh().solverPerformanceDict();

        // Name of the Field
        const word fieldName = "A2";

        // Create a solver Performance object
        const List<SolverPerformance<symmTensor>> sp(solverDict.lookup(fieldName));

        // Get initial residual
        const symmTensor& initialResidual = sp.first().initialResidual();
        const scalar maxInitialResidual = cmptMax(initialResidual);

        bool checkNumDiff = false;
        bool exitLoop = false;

        if (maxNumDiff < numDiff)
        {
            checkNumDiff = true;
            forAll(windowStore, i)
            {
                if ( (windowStore[i] == false) && (!exitLoop))
                {
                    windowStore[i] = true;
                    exitLoop=true;
                }
                checkNumDiff = checkNumDiff && windowStore[i];
            }
        }
        else
        {
            forAll(windowStore, i)
            {
                windowStore[i] = false;
            }
        }

        if ( checkNumDiff && (maxInitialResidual < absTol) )
        {
            Time& time = const_cast<Time&>(time_);               

            Info<< "    Stopping calculation" << nl
                << "    Writing fields"<< endl;

            A2_find.oldTime().write();

            time.writeAndEnd();
        }  
            
        // Store previous time step data
        store=A2_find;
    #};                               
}         
