/*--------------------------------*- C++ -*----------------------------------*\
  =========                 |
  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
   \\    /   O peration     | Website:  https://openfoam.org
    \\  /    A nd           | Version:  9
     \\/     M anipulation  |
\*---------------------------------------------------------------------------*/
FoamFile
{
    version     2.0;
    format      ascii;
    class       dictionary;
    location    "system";
    object      controlDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

application     upstreamFoam;

startFrom       latestTime;

startTime       0;

stopAt          endTime;

endTime         1e8;

deltaT          0.01;

writeControl    adjustableRunTime;

writeInterval   25;

purgeWrite      0;

writeFormat     ascii;

writePrecision  6;

writeCompression off;

timeFormat      general;

timePrecision   6;

runTimeModifiable true;

adjustTimeStep  yes;

timeStepControl Courant;

CourantCoeffs
{
    reservCtrl      no;
    maxCo           0.6;
}

maxDeltaT       50;

DebugSwitches
{
    SolverPerformance 1; //1 to infos
}


functions
{
    pressureInlet
    {
        type            surfaceFieldValue;
        libs            ("libfieldFunctionObjects.so");
        writeControl    timeStep;
        writeInterval   1;
        log             no;
        writeTotalArea  no;
        writeFields     no;
        regionType      patch;
        name            inlet;
        operation       areaAverage;
        fields
        (   
            p
        );
    }
    
    pressureOutlet
    {
        type            surfaceFieldValue;
        libs            ("libfieldFunctionObjects.so");
        writeControl    timeStep;
        writeInterval   1;
        log             no;
        writeTotalArea  no;
        writeFields     no;
        regionType      patch;
        name            outlet;
        operation       areaAverage;
        fields
        (   
            p
        );
    }

    porosityOutlet
    {
        type            surfaceFieldValue;
        libs            ("libfieldFunctionObjects.so");
        writeControl    timeStep;
        writeInterval   1;
        log             no;
        writeTotalArea  no;
        writeFields     no;
        regionType      patch;
        name            outlet;
        operation       areaAverage;
        fields
        (   
            porosityIni
            invK.rock
            Ya
        );
    }

    porosityVolume
    {
        type            volFieldValue;
        libs            ("libfieldFunctionObjects.so");

        writeControl    timeStep;
        writeInterval   1;
        writeFields     false;
        log             false;

        operation       volAverage;
        fields
        (   
            porosityIni
            invK.rock
            Ya
        );
    }

    checkDeltaP
    {
        libs            ("libutilityFunctionObjects.so");
        type coded;
        name checkDeltaP;
        writeControl timeStep;
        writeInterval 1;
        
        codeInclude
        #{
            #include "IFstream.H"
            #include "OFstream.H"
            #include <stdio.h>
            #include <stdlib.h>

            #define stopSimulation "\
            #/bin/bash \n\
            line=$(awk \"/stopAt/{ print NR; exit }\" system/controlDict) \n\
            sed -i ${line}s/\"endTime\"/\"writeNow\"/g system/controlDict "

            #define rewriteControlDict "\
            #/bin/bash \n\
            line=$(awk \"/stopAt/{ print NR; exit }\" system/controlDict) \n\
            sed -i ${line}s/\"writeNow\"/\"endTime\"/g system/controlDict "
  
        #};
        
        codeExecute
        #{
            label inletID = mesh().boundaryMesh().findPatchID("inlet");
            label outletID = mesh().boundaryMesh().findPatchID("outlet");
            const surfaceScalarField& magSf = mesh().magSf();
            const volScalarField& p_ = mesh().lookupObject<volScalarField>("p");
            scalar inletArea = gSum( magSf.boundaryField()[inletID] );
            scalar outletArea = gSum( magSf.boundaryField()[outletID] );
            scalar pInlet = gSum( p_.boundaryField()[inletID] * magSf.boundaryField()[inletID] )/inletArea;
            scalar pOutlet = gSum( p_.boundaryField()[outletID] * magSf.boundaryField()[outletID] )/outletArea;
            
            scalar deltaP0 = 99;
            scalar runNumber = 2;
            scalar totNumber = 3;

            scalar localProgress = max(1.0 - (pInlet - pOutlet) / deltaP0, 0.0);
            scalar progress = (runNumber+localProgress)/totNumber;

            Info << "deltaP(<0.01 to stop) = " << (pInlet - pOutlet) / deltaP0 << endl << endl;
                
            std::string file = "postProcessing/progress/0/progress.dat";

            std::ofstream outputFile(file.c_str(), std::ios::out);

            outputFile <<  progress << std::endl;
            
            if( (pInlet - pOutlet) / deltaP0 < 0.01 && p_.time().timeIndex() > 10 )
            {
                system(stopSimulation);
            }
        #};

        codeEnd
        #{
            system(rewriteControlDict);
        #};
    }
}

// ************************************************************************* //
