Foam::ReactingMultiphaseLookupTableInjection<CloudType>::
ReactingMultiphaseLookupTableInjection
(
    const dictionary& dict,
    CloudType& owner,
    const word& modelName
)
:
    InjectionModel<CloudType>(dict, owner, modelName, typeName),
    inputFileName_(this->coeffDict().lookup("inputFile")),
    duration_(readScalar(this->coeffDict().lookup("duration"))),
    parcelsPerSecond_
    (
        readScalar(this->coeffDict().lookup("parcelsPerSecond"))
    ),
    injectors_
    (
        IOobject
        (
            inputFileName_,
            owner.db().time().constant(),
            owner.db(),
            IOobject::MUST_READ,
            IOobject::NO_WRITE
        )
    ),
    injectorCells_(0),
    injectorTetFaces_(0),
    injectorTetPts_(0)
{
    duration_ = owner.db().time().userTimeToTime(duration_);

    // Set/cache the injector cells
    injectorCells_.setSize(injectors_.size());
    injectorTetFaces_.setSize(injectors_.size());
    injectorTetPts_.setSize(injectors_.size());

    updateMesh();

    // Determine volume of particles to inject
    this->volumeTotal_ = 0.0;
    forAll(injectors_, i)
    {
        this->volumeTotal_ += injectors_[i].mDot()/injectors_[i].rho();
    }
    this->volumeTotal_ *= duration_;
}
Foam::ThermoLookupTableInjection<CloudType>::ThermoLookupTableInjection
(
    const dictionary& dict,
    CloudType& owner
)
:
    InjectionModel<CloudType>(dict, owner, typeName),
    inputFileName_(this->coeffDict().lookup("inputFile")),
    duration_(readScalar(this->coeffDict().lookup("duration"))),
    parcelsPerSecond_
    (
        readScalar(this->coeffDict().lookup("parcelsPerSecond"))
    ),
    injectors_
    (
        IOobject
        (
            inputFileName_,
            owner.db().time().constant(),
            owner.db(),
            IOobject::MUST_READ,
            IOobject::NO_WRITE
        )
    ),
    injectorCells_(0),
    injectorTetFaces_(0),
    injectorTetPts_(0)
{
    duration_ = owner.db().time().userTimeToTime(duration_);

    // Set/cache the injector cells
    injectorCells_.setSize(injectors_.size());
    injectorTetFaces_.setSize(injectors_.size());
    injectorTetPts_.setSize(injectors_.size());

    forAll(injectors_, i)
    {
        this->findCellAtPosition
        (
            injectorCells_[i],
            injectorTetFaces_[i],
            injectorTetPts_[i],
            injectors_[i].x()
        );
    }
Foam::ManualInjectionWet<CloudType>::ManualInjectionWet
(
    const dictionary& dict,
    CloudType& owner,
    const word& modelName
)
:
    InjectionModel<CloudType>(dict, owner, modelName, typeName),
    positionsFile_(this->coeffDict().lookup("positionsFile")),
    positions_
    (
        IOobject
        (
            positionsFile_,
            owner.db().time().constant(),
            owner.mesh(),
            IOobject::MUST_READ,
            IOobject::NO_WRITE
        )
    ),
    diameters_(positions_.size()),
    injectorCells_(positions_.size(), -1),
    injectorTetFaces_(positions_.size(), -1),
    injectorTetPts_(positions_.size(), -1),
    U0_(this->coeffDict().lookup("U0")),
    sizeDistribution_
    (
        distributionModels::distributionModel::New
        (
            this->coeffDict().subDict("sizeDistribution"),
            owner.rndGen()
        )
    ),
    ignoreOutOfBounds_
    (
        this->coeffDict().lookupOrDefault("ignoreOutOfBounds", false)
    ),
    iniVliq_
    (
        readScalar
        (
            this->coeffDict().lookup("initialLiquidVolumePerParticle")
        )
    )
{
    updateMesh();

    // Construct parcel diameters
    forAll(diameters_, i)
    {
        diameters_[i] = sizeDistribution_->sample();
    }

    // Determine volume of particles to inject
    this->volumeTotal_ = sum(pow3(diameters_))*pi/6.0;
}
Foam::InjectionModel<CloudType>::InjectionModel
(
    const dictionary& dict,
    CloudType& owner,
    const word& type
)
:
    dict_(dict),
    owner_(owner),
    coeffDict_(dict.subDict(type + "Coeffs")),
    SOI_(readScalar(coeffDict_.lookup("SOI"))),
    volumeTotal_(0.0),
    massTotal_(dimensionedScalar(coeffDict_.lookup("massTotal")).value()),
    massInjected_(0.0),
    nInjections_(0),
    parcelsAddedTotal_(0),
    parcelBasis_(pbNumber),
    time0_(owner.db().time().value()),
    timeStep0_(0.0)
{
    // Provide some info
    // - also serves to initialise mesh dimensions - needed for parallel runs
    //   due to lazy evaluation of valid mesh dimensions
    Info<< "    Constructing " << owner.mesh().nGeometricD() << "-D injection"
        << endl;

    word parcelBasisType = coeffDict_.lookup("parcelBasisType");
    if (parcelBasisType == "mass")
    {
        parcelBasis_ = pbMass;
    }
    else if (parcelBasisType == "number")
    {
        parcelBasis_ = pbNumber;
    }
    else
    {
        FatalErrorIn
        (
            "Foam::InjectionModel<CloudType>::InjectionModel"
            "("
                "const dictionary&, "
                "CloudType&, "
                "const word&"
            ")"
        )<< "parcelBasisType must be either 'number' or 'mass'" << nl
         << exit(FatalError);
    }

    readProps();
}
Foam::ManualInjection<CloudType>::ManualInjection
(
    const dictionary& dict,
    CloudType& owner
)
:
    InjectionModel<CloudType>(dict, owner, typeName),
    positionsFile_(this->coeffDict().lookup("positionsFile")),
    positions_
    (
        IOobject
        (
            positionsFile_,
            owner.db().time().constant(),
            owner.mesh(),
            IOobject::MUST_READ,
            IOobject::NO_WRITE
        )
    ),
    diameters_(positions_.size()),
    U0_(this->coeffDict().lookup("U0")),
    parcelPDF_
    (
        pdfs::pdf::New
        (
            this->coeffDict().subDict("parcelPDF"),
            owner.rndGen()
        )
    )
{
    // Construct parcel diameters
    forAll(diameters_, i)
    {
        diameters_[i] = parcelPDF_->sample();
    }

    // Determine volume of particles to inject
    this->volumeTotal_ = sum(pow3(diameters_))*mathematicalConstant::pi/6.0;
}
Foam::FieldActivatedInjection<CloudType>::FieldActivatedInjection
(
    const dictionary& dict,
    CloudType& owner,
    const word& modelName
)
:
    InjectionModel<CloudType>(dict, owner, modelName, typeName),
    factor_(readScalar(this->coeffDict().lookup("factor"))),
    referenceField_
    (
        owner.db().objectRegistry::template lookupObject<volScalarField>
        (
            this->coeffDict().lookup("referenceField")
        )
    ),
    thresholdField_
    (
        owner.db().objectRegistry::template lookupObject<volScalarField>
        (
            this->coeffDict().lookup("thresholdField")
        )
    ),
    positionsFile_(this->coeffDict().lookup("positionsFile")),
    positions_
    (
        IOobject
        (
            positionsFile_,
            owner.db().time().constant(),
            owner.mesh(),
            IOobject::MUST_READ,
            IOobject::NO_WRITE
        )
    ),
    injectorCells_(positions_.size()),
    injectorTetFaces_(positions_.size()),
    injectorTetPts_(positions_.size()),
    nParcelsPerInjector_
    (
        readLabel(this->coeffDict().lookup("parcelsPerInjector"))
    ),
    nParcelsInjected_(positions_.size(), 0),
    U0_(this->coeffDict().lookup("U0")),
    diameters_(positions_.size()),
    sizeDistribution_
    (
        distributionModels::distributionModel::New
        (
            this->coeffDict().subDict("sizeDistribution"),
            owner.rndGen()
        )
    )
{
    // Construct parcel diameters - one per injector cell
    forAll(diameters_, i)
    {
        diameters_[i] = sizeDistribution_->sample();
    }

    // Determine total volume of particles to inject
    this->volumeTotal_ =
        nParcelsPerInjector_*sum(pow3(diameters_))*pi/6.0;

    updateMesh();
}
Foam::MultiSprinklerInjection<CloudType>::MultiSprinklerInjection
(
    const dictionary& dict,
    CloudType& owner,
    const word& modelName
    )
    :
    InjectionModel<CloudType>(dict, owner, modelName, typeName),
    duration_(readScalar(this->coeffDict().lookup("duration"))),
    operatingPressure_(readScalar(this->coeffDict().lookup("operatingPressure"))),
    cellEleAngle1_(this->coeffDict().lookup("cellEleAngle1")),
    cellEleAngle2_(this->coeffDict().lookup("cellEleAngle2")),
    cellAziAngle1_(this->coeffDict().lookup("cellAziAngle1")),
    cellAziAngle2_(this->coeffDict().lookup("cellAziAngle2")),
    radiusToSprinkler_(readScalar(this->coeffDict().lookup("radiusToSprinkler"))),
    nParcelsCell_(cellAziAngle1_.size()),
    volFCell_(cellAziAngle1_.size()),
    positionList_(this->coeffDict().lookup("positionList")),
    nSprinklers_(positionList_.size()),
    nActivatedSprinklers_(0),
    injectorCellList_(nSprinklers_),
    tetFaceI_(-1),
    tetPtI_(-1),
    parcelsCell_(0),
    totalParcels_(0),
    multipleParcelsPerCell_(this->coeffDict().lookup("multipleParcelsPerCell")),
    direction_(this->coeffDict().lookup("direction")),
    armDirection_(this->coeffDict().lookup("armDirection")),
    parcelDirVec_(direction_),
    parcelDv50_(0.000617),
    parcelSigma_(0.784),
    parcelGamma_(0),
    parcelVelocity_(0),
    parcelsPerSecond_
    (
        readScalar(this->coeffDict().lookup("parcelsPerSecond"))
        ),
    flowRateProfile_
    (
        TimeFunction1<scalar>
        (
            owner.db().time(),
            "flowRateProfile",
            this->coeffDict()

            )
        ),
    kFactor_
    (
        readScalar(this->coeffDict().lookup("kFactor"))
        ),
    fitPressures_(this->coeffDict().lookup("fitPressureRange")),
    fitVelocityStdev_(this->coeffDict().lookup("fitVelocityStdevRange")),
    fitAziAngles_(this->coeffDict().lookup("fitAzimuthalAngle")),
    fitCoeFluxLowPres_(this->coeffDict().lookup("fitCoeFluxLowPres")),
    fitCoeFluxHighPres_(this->coeffDict().lookup("fitCoeFluxHighPres")),
    fitCoeFlux_(20*(fitAziAngles_.size()-1)+5),
    fitCoeDv50LowPres_(this->coeffDict().lookup("fitCoeDv50LowPres")),
    fitCoeDv50HighPres_(this->coeffDict().lookup("fitCoeDv50HighPres")),
    fitCoeDv50_(20*(fitAziAngles_.size()-1)+5),
    fitCoeSigmaLowPres_(this->coeffDict().lookup("fitCoeSigmaLowPres")),
    fitCoeSigmaHighPres_(this->coeffDict().lookup("fitCoeSigmaHighPres")),
    fitCoeSigma_(20*(fitAziAngles_.size()-1)+5),
    fitCoeGammaLowPres_(this->coeffDict().lookup("fitCoeGammaLowPres")),
    fitCoeGammaHighPres_(this->coeffDict().lookup("fitCoeGammaHighPres")),
    fitCoeGamma_(20*(fitAziAngles_.size()-1)+5),
    fitCoeVelocityLowPres_(this->coeffDict().lookup("fitCoeVelocityLowPres")),
    fitCoeVelocityHighPres_(this->coeffDict().lookup("fitCoeVelocityHighPres")),
    fitCoeVelocity_(20*(fitAziAngles_.size()-1)+5),
    cellCoeFlux_(5*cellEleAngle1_.size()),
    cellCoeDv50_(5*cellEleAngle1_.size()),
    cellCoeSigma_(5*cellEleAngle1_.size()),
    cellCoeGamma_(5*cellEleAngle1_.size()),
    cellCoeVelocity_(5*cellEleAngle1_.size()),
    tanVec1_(vector::zero),
    tanVec2_(vector::zero),
    Tgas_
    (
        owner.db().objectRegistry::template lookupObject<volScalarField>
        (
            "T"
            )
        ),
    Ugas_
    (
        owner.db().objectRegistry::template lookupObject<volVectorField>
        (
            "U"
            )
        ),
	activeLinks_(this->coeffDict().subDict("rtiCoeffs"). template lookupOrDefault<Switch>("active",false)),
    RTI_(this->coeffDict().subDict("rtiCoeffs").template lookupOrDefault<scalar>("RTI",200.0)),
    C_(this->coeffDict().subDict("rtiCoeffs").template lookupOrDefault<scalar>("C",0.0)),
    initialTemperatureList_(nSprinklers_,298.15),
    activationTemperature_(this->coeffDict().subDict("rtiCoeffs").template lookupOrDefault<scalar>("activationTemperature",432.0)),
	// have Andy implement this for Switch in SubModelBase.C
    // activated_(this->template getBaseProperty<Switch>("activated")),
    activatedList_(nSprinklers_,false),
    linkTemperatureList_(nSprinklers_,298.15),
    activationTimeList_(nSprinklers_,GREAT),
    filePtr_()
{
    
	if(activeLinks_){
        //sprinkler to be activated via RTI calculation
		this->SOI_=GREAT;
        scalar currentTime = this->owner().time().value();

        // read restart properties from <time>/uniform/lagrangian/reactingCloud1/reactingCloud1OutputProperties
        Switch atLeastOneActivated=false;
        for(label i=0;i<nSprinklers_;i++)
        {
            std::ostringstream buf;
            buf.precision(2);
            buf << i;
            
            activatedList_[i] = this->template getBaseProperty<  bool  >
                (word("activated")+buf.str());
            if(activatedList_[i] == true){
                atLeastOneActivated=true;
            }
            activationTimeList_[i] = this->template getBaseProperty< scalar >
                (word("activationTime")+buf.str());
            linkTemperatureList_[i] = this->template getBaseProperty< scalar >
                (word("linkTemperature")+buf.str());
            initialTemperatureList_[i]=linkTemperatureList_[i];
        }

        if(atLeastOneActivated && min(activationTimeList_) < currentTime)
        {
            this->SOI_ = min(activationTimeList_);
        }
        
        for(label i=0;i<nSprinklers_;i++){
            if(initialTemperatureList_[i]==0e0){
                // if linkTemperature not found in reactingCloud1OutputProperties then read from controlDict
                initialTemperatureList_[i] = this->coeffDict().subDict("rtiCoeffs").template lookupOrDefault<scalar>("initialTemperature",298.0);
                activatedList_[i]=false;
                linkTemperatureList_[i] = initialTemperatureList_[i];
                activationTimeList_[i] = GREAT;
            }
        }
	}
    else{
        for(label i=0;i<nSprinklers_;i++){
            activatedList_[i] = true;
        }
    }
    // Normalise direction vector
    direction_ /= mag(direction_);

    // determine fitting coefficients at operating pressure
    for (label iCell=0; iCell<fitCoeFluxLowPres_.size();iCell++)
    {
        scalar gradCoe;
        gradCoe = (fitCoeFluxHighPres_[iCell]-fitCoeFluxLowPres_[iCell])/(pow(fitPressures_[1],0.5)-pow(fitPressures_[0],0.5));
        fitCoeFlux_[iCell] = fitCoeFluxLowPres_[iCell]+(pow(operatingPressure_,0.5) - pow(fitPressures_[0],0.5))*gradCoe;
        gradCoe = (fitCoeDv50HighPres_[iCell]-fitCoeDv50LowPres_[iCell])/(pow(fitPressures_[1],-1./3.)-pow(fitPressures_[0],-1./3.));
        fitCoeDv50_[iCell] = fitCoeDv50LowPres_[iCell]+(pow(operatingPressure_,-1./3.) - pow(fitPressures_[0],-1./3.))*gradCoe;
        gradCoe = (fitCoeSigmaHighPres_[iCell]-fitCoeSigmaLowPres_[iCell])/(pow(fitPressures_[1],-1./3.)-pow(fitPressures_[0],-1./3.));
        fitCoeSigma_[iCell] = fitCoeSigmaLowPres_[iCell]+(pow(operatingPressure_,-1./3.) - pow(fitPressures_[0],-1./3.))*gradCoe;
        if(kFactor_ == 162){
            gradCoe = (fitCoeGammaHighPres_[iCell]-fitCoeGammaLowPres_[iCell])/(pow(fitPressures_[1],-1./3.)-pow(fitPressures_[0],-1./3.));
            fitCoeGamma_[iCell] = fitCoeGammaLowPres_[iCell]+(pow(operatingPressure_,-1./3.) - pow(fitPressures_[0],-1./3.))*gradCoe;
        }
        gradCoe = (fitCoeVelocityHighPres_[iCell]-fitCoeVelocityLowPres_[iCell])/(pow(fitPressures_[1],0.5)-pow(fitPressures_[0],0.5));
        fitCoeVelocity_[iCell] = fitCoeVelocityLowPres_[iCell]+(pow(operatingPressure_,0.5) - pow(fitPressures_[0],0.5))*gradCoe;
        gradCoe = (fitVelocityStdev_[1]-fitVelocityStdev_[0])/(pow(fitPressures_[1],0.5)-pow(fitPressures_[0],0.5));
        fitVelocityStdev_[0] = fitVelocityStdev_[0]+(pow(operatingPressure_,0.5) - pow(fitPressures_[0],0.5))*gradCoe;
    }

    scalarList fitAllAziAngles(4*(fitAziAngles_.size()-1)+1);

    for(label j=0;j<fitAziAngles_.size();j++){
        fitAllAziAngles[j]=fitAziAngles_[j];
    }
    for (label iQuart=1; iQuart<4;iQuart++)
    {
        for (label jjj=1;jjj<fitAziAngles_.size();jjj++)
        {
            label j = iQuart*(fitAziAngles_.size()-1)+jjj;
            label js = iQuart*(fitAziAngles_.size()-1)-jjj;
            fitAllAziAngles[j]= iQuart*180-fitAllAziAngles[js];
            for (label i=0;i<5;i++)
            {
                label iCellp = j*5+i; label iCelln = js*5+i;
                fitCoeFlux_[iCellp]=fitCoeFlux_[iCelln];
                fitCoeDv50_[iCellp]=fitCoeDv50_[iCelln];
                fitCoeSigma_[iCellp]=fitCoeSigma_[iCelln];
                if(kFactor_ == 162){
                    fitCoeGamma_[iCellp]=fitCoeGamma_[iCelln];
                }
                fitCoeVelocity_[iCellp]=fitCoeVelocity_[iCelln];
            }
        }
    }

    if(!(cellAziAngle1_.size()==cellAziAngle2_.size() && 
         cellAziAngle1_.size()==cellEleAngle1_.size() && 
         cellAziAngle1_.size()==cellEleAngle2_.size()
           )
        )
    {
        Info << nl << "MultiSprinklerInjection cells angle dimension not right" << nl
             << exit(FatalError);
    }
 
    label numberCells = cellAziAngle1_.size();
    scalar totalArea = 0.0;
    scalarList areaEachCell(cellAziAngle1_.size());
    for(label iCell = 0; iCell < numberCells; iCell++)
    {
        scalar theta1 = twoPi*cellEleAngle1_[iCell]/360.0;
        scalar theta2 = twoPi*cellEleAngle2_[iCell]/360.0;
        scalar phi1 = twoPi*cellAziAngle1_[iCell]/360.0;
        scalar phi2 = twoPi*cellAziAngle2_[iCell]/360.0;
        areaEachCell[iCell] = radiusToSprinkler_*radiusToSprinkler_*
            (sin(theta2)-sin(theta1))*(phi2-phi1);
        if(areaEachCell[iCell] < 0.0){
            areaEachCell[iCell] = -areaEachCell[iCell];
        }
        totalArea = totalArea+areaEachCell[iCell];
    }
    for(label i=0;i<5*cellEleAngle1_.size();i++)
    {
        cellCoeFlux_[i]=0.0;
        cellCoeDv50_[i]=0;
        cellCoeSigma_[i]=0;
        cellCoeGamma_[i]=0;
        cellCoeVelocity_[i]=0;
    }

    for(label iCell=0; iCell<numberCells; iCell++)
    {
        scalar iNumCoe(0);
        for (label fitang=0; fitang < (4*(fitAziAngles_.size()-1)+1); fitang ++)
        {
            if(fitAllAziAngles[fitang]>=cellAziAngle1_[iCell] && fitAllAziAngles[fitang]<cellAziAngle2_[iCell])
            {
                iNumCoe++;
                for(label i = 0; i < 5; i++)
                {
                    cellCoeFlux_[i+5*iCell]+=fitCoeFlux_[i+fitang*5];
                    cellCoeDv50_[i+5*iCell]+=fitCoeDv50_[i+fitang*5];
                    cellCoeSigma_[i+5*iCell]+=fitCoeSigma_[i+fitang*5];
                    cellCoeGamma_[i+5*iCell]+=fitCoeGamma_[i+fitang*5];
                    cellCoeVelocity_[i+5*iCell]+=fitCoeVelocity_[i+fitang*5];
                }
            }
        }       
        if(iNumCoe>0){
            for(label i = 0; i < 5; i++)
            {
                cellCoeFlux_[i+5*iCell]/=iNumCoe;
                //Info<<" cell "<<iCell<<" coe flux = "<< cellCoeFlux_[i+5*iCell]<<nl;
                cellCoeDv50_[i+5*iCell]/=iNumCoe;
                cellCoeSigma_[i+5*iCell]/=iNumCoe;
                cellCoeGamma_[i+5*iCell]/=iNumCoe;
                cellCoeVelocity_[i+5*iCell]/=iNumCoe;
            } 
        }
        else{Info<<" No cell coefficients were found !!!!!!!!!!!!!!!!!"<<nl;}
    }    

    scalar totalFlowRate = 0.0; 
    scalarList flowRateCell(cellAziAngle1_.size()); // lpm
    for(label iCell=0; iCell<numberCells; iCell++)
    {
        scalar volumeflux  (0);
        //TODO:  why are eleAngle and j made into integers here?
        scalar eleAngle=int(0.5*(cellEleAngle1_[iCell]+cellEleAngle2_[iCell]));
        scalar aziAngle=int(0.5*(cellAziAngle1_[iCell]+cellAziAngle2_[iCell]));
        if(cellEleAngle2_[iCell] == 90) eleAngle=90;
        if(kFactor_ == 205){
            volumeflux = cellCoeFlux_[5*iCell]+
                cellCoeFlux_[1+5*iCell]*exp(-sqr((eleAngle-15)/7))+
                cellCoeFlux_[2+5*iCell]*exp(-sqr((eleAngle-35)/15))+
                cellCoeFlux_[3+5*iCell]*exp(-sqr((eleAngle-55)/15))+
                cellCoeFlux_[4+5*iCell]*exp(-sqr((eleAngle-90)/10));
        }
        if(kFactor_ == 162){
            volumeflux = cellCoeFlux_[5*iCell]+
                cellCoeFlux_[1+5*iCell]*exp(-sqr((eleAngle-30)/15))+
                cellCoeFlux_[2+5*iCell]*exp(-sqr((eleAngle-45)/15))+
                cellCoeFlux_[3+5*iCell]*exp(-sqr((eleAngle-60)/15))+
                cellCoeFlux_[4+5*iCell]*exp(-sqr((eleAngle-90)/5));
        }
        Info << "cell " << iCell 
             << " a_ang " 
             << aziAngle 
             << " e_ang " << eleAngle;
        Info << " volumeflux " 
             << volumeflux << " flowrate " 
             << areaEachCell[iCell]*volumeflux 
             << nl;
        flowRateCell[iCell] = areaEachCell[iCell]*volumeflux/60/1000.0;  //m^3/s
        if(flowRateCell[iCell] < 0.0){ 
            flowRateCell[iCell] = 0.0;
        }
        totalFlowRate += flowRateCell[iCell]; //m^3/s
    }
    scalar ratioFlowRate = flowRateProfile_.value(1); 
    ratioFlowRate /=totalFlowRate;
    Info << " total flow rate (kg/min) =" << totalFlowRate*1000*60 //kg/min
         << " given rate (kg/min) " << flowRateProfile_.value(1)*1000*60  //kg/min
         << " ratio "<< ratioFlowRate
         << nl;

    scalar minFlowRate = totalFlowRate;
    totalFlowRate = 0.0; 
    for(label iCell=0; iCell<numberCells; iCell++)
    {
        flowRateCell[iCell]*= ratioFlowRate;
        minFlowRate = min(minFlowRate, flowRateCell[iCell]);
        totalFlowRate += flowRateCell[iCell];
    }
    Info << "Correcting flow rates to match theoretical\n";
    ratioFlowRate = flowRateProfile_.value(1); 
    ratioFlowRate /=totalFlowRate;
    Info << " total flow rate (kg/min) =" << totalFlowRate*1000*60 //kg/min
         << " given rate (kg/min) " << flowRateProfile_.value(1)*1000*60  //kg/min
         << " ratio "<< ratioFlowRate
         << nl;

    scalar avgFlowRate =totalFlowRate/(numberCells-1);
    scalar ratioAvgToMin(1);
    ratioAvgToMin= (avgFlowRate-minFlowRate)/6;
    totalParcels_ = 0;
    for(label iCell=0; iCell<numberCells; iCell++)
    {
        nParcelsCell_[iCell]=  int( flowRateCell[iCell]/ratioAvgToMin );
        if(nParcelsCell_[iCell] < 1){
            nParcelsCell_[iCell] = 1;
        }
        if(nParcelsCell_[iCell] > 12){
            nParcelsCell_[iCell] = 12;
        }
        if( ! multipleParcelsPerCell_ ){
            nParcelsCell_[iCell] = 1;
        }
        totalParcels_ += nParcelsCell_[iCell];
        Info << " iCell " << iCell << "  numpcell= " << nParcelsCell_[iCell] << " total= " << totalParcels_ << nl;
    }
    for(label iCell = 0; iCell < numberCells; iCell++)
    {
        volFCell_[iCell] = flowRateCell[iCell]/totalFlowRate ;
    }

    OFstream osP("sprinklerInjectionProfile");
    
    osP << "#cell " << "\t";
    osP << "e1 "    << "\t";
    osP << "e2 "    << "\t";
    osP << "a1 "    << "\t";
    osP << "a2 "    << "\t";
    osP << "area "  << "\t";
    osP << "fr "    << "\t";
    osP << "vfr "   << "\t";
    osP << "npc "   << "\t";
    osP << endl;
    for(label iCell = 0; iCell < numberCells; iCell++){
        osP << iCell << "\t";
        osP << cellEleAngle1_[iCell] << "\t";
        osP << cellEleAngle2_[iCell] << "\t";
        osP << cellAziAngle1_[iCell] << "\t";
        osP << cellAziAngle2_[iCell] << "\t";
        osP << areaEachCell[iCell]  << "\t";
        osP << flowRateCell[iCell]*1000 << "\t"; // kg/s
        osP << volFCell_[iCell] << "\t";
        osP << nParcelsCell_[iCell] << "\t";
        osP << endl;
    }


    tanVec1_ = armDirection_;

    tanVec2_ = direction_^tanVec1_;
    // Set total volume to inject, gets overwritten later
    this->volumeTotal_ = flowRateProfile_.integrate(0.0, duration_);

    // Set/cache the injector cell
    // this is the location used for the rti calculation
    forAll(positionList_,index){

        this->findCellAtPosition
            (
                injectorCellList_[index],
                tetFaceI_,
                tetPtI_,
                positionList_[index],
                true
                );

    }
Foam::ConeInjection<CloudType>::ConeInjection
(
    const dictionary& dict,
    CloudType& owner,
    const word& modelName
)
:
    InjectionModel<CloudType>(dict, owner, modelName, typeName),
    positionAxis_(this->coeffDict().lookup("positionAxis")),
    injectorCells_(positionAxis_.size()),
    injectorTetFaces_(positionAxis_.size()),
    injectorTetPts_(positionAxis_.size()),
    duration_(readScalar(this->coeffDict().lookup("duration"))),
    parcelsPerInjector_
    (
        readScalar(this->coeffDict().lookup("parcelsPerInjector"))
    ),
    flowRateProfile_
    (
        TimeDataEntry<scalar>
        (
            owner.db().time(),
            "flowRateProfile",
            this->coeffDict()
        )
    ),
    Umag_
    (
        TimeDataEntry<scalar>
        (
            owner.db().time(),
            "Umag",
            this->coeffDict()
        )
    ),
    thetaInner_
    (
        TimeDataEntry<scalar>
        (
            owner.db().time(),
            "thetaInner",
            this->coeffDict()
        )
    ),
    thetaOuter_
    (
        TimeDataEntry<scalar>
        (
            owner.db().time(),
            "thetaOuter",
            this->coeffDict()
        )
    ),
    sizeDistribution_
    (
        distributionModels::distributionModel::New
        (
            this->coeffDict().subDict("sizeDistribution"), owner.rndGen()
        )
    ),
    nInjected_(this->parcelsAddedTotal()),
    tanVec1_(positionAxis_.size()),
    tanVec2_(positionAxis_.size())
{
    duration_ = owner.db().time().userTimeToTime(duration_);

    // Normalise direction vector and determine direction vectors
    // tangential to injector axis direction
    forAll(positionAxis_, i)
    {
        vector& axis = positionAxis_[i].second();

        axis /= mag(axis);

        vector tangent = vector::zero;
        scalar magTangent = 0.0;

        cachedRandom& rnd = this->owner().rndGen();
        while (magTangent < SMALL)
        {
            vector v = rnd.sample01<vector>();

            tangent = v - (v & axis)*axis;
            magTangent = mag(tangent);
        }

        tanVec1_[i] = tangent/magTangent;
        tanVec2_[i] = axis^tanVec1_[i];
    }
Foam::InflationInjection<CloudType>::InflationInjection
(
    const dictionary& dict,
    CloudType& owner,
    const word& modelName
)
:
    InjectionModel<CloudType>(dict, owner, modelName, typeName),
    generationSetName_(this->coeffDict().lookup("generationCellSet")),
    inflationSetName_(this->coeffDict().lookup("inflationCellSet")),
    generationCells_(),
    inflationCells_(),
    duration_(readScalar(this->coeffDict().lookup("duration"))),
    flowRateProfile_
    (
        TimeFunction1<scalar>
        (
            owner.db().time(),
            "flowRateProfile",
            this->coeffDict()
        )
    ),
    growthRate_
    (
        TimeFunction1<scalar>
        (
            owner.db().time(),
            "growthRate",
            this->coeffDict()
        )
    ),
    newParticles_(),
    volumeAccumulator_(0.0),
    fraction_(1.0),
    selfSeed_(this->coeffDict().lookupOrDefault("selfSeed", false)),
    dSeed_(small),
    sizeDistribution_
    (
        distributionModel::New
        (
            this->coeffDict().subDict("sizeDistribution"),
            owner.rndGen()
        )
    )
{
    duration_ = owner.db().time().userTimeToTime(duration_);

    if (selfSeed_)
    {
        dSeed_ = readScalar(this->coeffDict().lookup("dSeed"));
    }

    cellSet generationCells(this->owner().mesh(), generationSetName_);

    generationCells_ = generationCells.toc();

    cellSet inflationCells(this->owner().mesh(), inflationSetName_);

    // Union of cellSets
    inflationCells |= generationCells;

    inflationCells_ = inflationCells.toc();

    if (Pstream::parRun())
    {
        scalar generationVolume = 0.0;

        forAll(generationCells_, gCI)
        {
            label cI = generationCells_[gCI];

            generationVolume += this->owner().mesh().cellVolumes()[cI];
        }

        scalar totalGenerationVolume = generationVolume;

        reduce(totalGenerationVolume, sumOp<scalar>());

        fraction_ = generationVolume/totalGenerationVolume;
    }
示例#10
0
Foam::ConeInjectionMP<CloudType>::ConeInjectionMP
(
    const dictionary& dict,
    CloudType& owner
)
:
    InjectionModel<CloudType>(dict, owner, typeName),
    positionsFile_(this->coeffDict().lookup("positionsFile")),
    positions_
    (
        IOobject
        (
            positionsFile_,
            owner.db().time().constant(),
            owner.mesh(),
            IOobject::MUST_READ,
            IOobject::NO_WRITE
        )
    ),
    injectorCells_(positions_.size()),
    axesFile_(this->coeffDict().lookup("axesFile")),
    axes_
    (
        IOobject
        (
            axesFile_,
            owner.db().time().constant(),
            owner.mesh(),
            IOobject::MUST_READ,
            IOobject::NO_WRITE
        )
    ),
    duration_(readScalar(this->coeffDict().lookup("duration"))),
    parcelsPerInjector_
    (
        readScalar(this->coeffDict().lookup("parcelsPerInjector"))
    ),
    volumeFlowRate_
    (
        DataEntry<scalar>::New
        (
            "volumeFlowRate",
            this->coeffDict()
        )
    ),
    Umag_
    (
        DataEntry<scalar>::New
        (
            "Umag",
            this->coeffDict()
        )
    ),
    thetaInner_
    (
        DataEntry<scalar>::New
        (
            "thetaInner",
            this->coeffDict()
        )
    ),
    thetaOuter_
    (
        DataEntry<scalar>::New
        (
            "thetaOuter",
            this->coeffDict()
        )
    ),
    parcelPDF_
    (
        pdfs::pdf::New
        (
            this->coeffDict().subDict("parcelPDF"),
            owner.rndGen()
        )
    ),
    nInjected_(this->parcelsAddedTotal()),
    tanVec1_(positions_.size()),
    tanVec2_(positions_.size())
{
    // Normalise direction vector and determine direction vectors
    // tangential to direction
    forAll(axes_, i)
    {
        axes_[i] /= mag(axes_[i]);

        vector tangent = vector::zero;
        scalar magTangent = 0.0;

        while (magTangent < SMALL)
        {
            vector v = this->owner().rndGen().vector01();

            tangent = v - (v & axes_[i])*axes_[i];
            magTangent = mag(tangent);
        }

        tanVec1_[i] = tangent/magTangent;
        tanVec2_[i] = axes_[i]^tanVec1_[i];
    }
Foam::FieldActivatedInjection<CloudType>::FieldActivatedInjection
(
    const dictionary& dict,
    CloudType& owner
)
    :
    InjectionModel<CloudType>(dict, owner, typeName),
    factor_(readScalar(this->coeffDict().lookup("factor"))),
    referenceField_
    (
       owner.db().objectRegistry::lookupObject<volScalarField>
       (
           this->coeffDict().lookup("referenceField")
       )
    ),
    thresholdField_
    (
       owner.db().objectRegistry::lookupObject<volScalarField>
       (
           this->coeffDict().lookup("thresholdField")
       )
    ),
    positionsFile_(this->coeffDict().lookup("positionsFile")),
    positions_
    (
       IOobject
       (
           positionsFile_,
           owner.db().time().constant(),
           owner.mesh(),
           IOobject::MUST_READ,
           IOobject::NO_WRITE
       )
    ),
    injectorCells_(positions_.size()),
    nParcelsPerInjector_
    (
       readLabel(this->coeffDict().lookup("parcelsPerInjector"))
    ),
    nParcelsInjected_(positions_.size(), 0),
    U0_(this->coeffDict().lookup("U0")),
    diameters_(positions_.size()),
    parcelPDF_
    (
       pdfs::pdf::New
       (
           this->coeffDict().subDict("parcelPDF"),
           owner.rndGen()
       )
    )
{
    // Construct parcel diameters - one per injector cell
    forAll(diameters_, i)
    {
        diameters_[i] = parcelPDF_->sample();
    }

    // Determine total volume of particles to inject
    this->volumeTotal_ =
        nParcelsPerInjector_*sum(pow3(diameters_))*mathematicalConstant::pi/6.0;

    // Set/cache the injector cells
    forAll(positions_, i)
    {
        this->findCellAtPosition
        (
            injectorCells_[i],
            positions_[i]
        );
    }