From bf8c1c2cfb653edeede2de053522f4cc3bbb1511 Mon Sep 17 00:00:00 2001 From: Matteo Cusini Date: Fri, 26 Jul 2024 16:29:49 -0700 Subject: [PATCH 001/104] Add ImmiscibleMultiphaseFlow physics package. --- .../immiscible_2phaseFlow_1d.xml | 145 +++ .../fluidFlow/ImmiscibleMultiphaseFlow.cpp | 1152 +++++++++++++++++ .../fluidFlow/ImmiscibleMultiphaseFlow.hpp | 389 ++++++ 3 files changed, 1686 insertions(+) create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscible_2phaseFlow_1d.xml create mode 100644 src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp create mode 100644 src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscible_2phaseFlow_1d.xml b/inputFiles/immiscibleMultiphaseFlow/immiscible_2phaseFlow_1d.xml new file mode 100644 index 00000000000..0c928a15e2b --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscible_2phaseFlow_1d.xml @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp new file mode 100644 index 00000000000..db3a431bcd0 --- /dev/null +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -0,0 +1,1152 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 Total, S.A + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2018-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/** + * @file ImmiscibleMultiphaseFlow.cpp + */ + +#include "ImmiscibleMultiphaseFlow.hpp" + +#include "constitutive/ConstitutiveManager.hpp" +#include "constitutive/capillaryPressure/CapillaryPressureFields.hpp" +#include "constitutive/capillaryPressure/capillaryPressureSelector.hpp" +#include "constitutive/ConstitutivePassThru.hpp" + +#if defined( __INTEL_COMPILER ) +#pragma GCC optimize "O0" +#endif + +namespace geos +{ + +using namespace dataRepository; +using namespace constitutive; + +ImmiscibleMultiphaseFlow::ImmiscibleMultiphaseFlow( const string & name, + Group * const parent ) + : + FlowSolverBase( name, parent ), + m_numPhases( 2 ), + m_hasCapPressure( 0 ) +{ + this->registerWrapper( viewKeyStruct::inputTemperatureString(), &m_inputTemperature ). + setInputFlag( InputFlags::REQUIRED ). + setDescription( "Temperature" ); +} + +void ImmiscibleMultiphaseFlow::postInputInitialization() +{ + FlowSolverBase::postInputInitialization(); +} + +void ImmiscibleMultiphaseFlow::registerDataOnMesh( Group & meshBodies ) +{ + using namespace fields::flow; + + FlowSolverBase::registerDataOnMesh( meshBodies ); + + DomainPartition const & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" ); + ConstitutiveManager const & cm = domain.getConstitutiveManager(); + + // 0. Find a "reference" fluid model name (at this point, models are already attached to subregions) + forDiscretizationOnMeshTargets( meshBodies, [&]( string const &, + MeshLevel & mesh, + arrayView1d< string const > const & regionNames ) + { + mesh.getElemManager().forElementSubRegions( regionNames, + [&]( localIndex const, + ElementSubRegionBase & subRegion ) + { + // If at least one region has a capillary pressure model, consider it enabled for all + string const capPresName = getConstitutiveName< CapillaryPressureBase >( subRegion ); + if( !capPresName.empty() ) + { + m_hasCapPressure = true; + } + } ); + } ); + + m_numDofPerCell = m_numPhases; + + // 2. Register and resize all fields as necessary + forDiscretizationOnMeshTargets( meshBodies, [&]( string const &, + MeshLevel & mesh, + arrayView1d< string const > const & regionNames ) + { + mesh.getElemManager().forElementSubRegions( regionNames, + [&]( localIndex const, + ElementSubRegionBase & subRegion ) + { + if( m_hasCapPressure ) + { + subRegion.registerWrapper< string >( viewKeyStruct::capPressureNamesString() ). + setPlotLevel( PlotLevel::NOPLOT ). + setRestartFlags( RestartFlags::NO_WRITE ). + setSizedFromParent( 0 ). + setDescription( "Name of the capillary pressure constitutive model to use" ). + reference(); + + string & capPresName = subRegion.getReference< string >( viewKeyStruct::capPressureNamesString() ); + capPresName = getConstitutiveName< CapillaryPressureBase >( subRegion ); + GEOS_THROW_IF( capPresName.empty(), + GEOS_FMT( "{}: Capillary pressure model not found on subregion {}", + getDataContext(), subRegion.getDataContext() ), + InputError ); + } + + + string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); + MultiFluidBase const & fluid = getConstitutiveModel< MultiFluidBase >( subRegion, fluidName ); + + // The resizing of the arrays needs to happen here, before the call to initializePreSubGroups, + // to make sure that the dimensions are properly set before the timeHistoryOutput starts its initialization. + subRegion.registerField< phaseVolumeFraction >( getName() ). + setDimLabels( 1, fluid.phaseNames() ). + reference().resizeDimension< 1 >( m_numPhases ); + + subRegion.registerField< phaseMobility >( getName() ). + setDimLabels( 1, fluid.phaseNames() ). + reference().resizeDimension< 1 >( m_numPhases ); + + subRegion.registerField< dPhaseMobility >( getName() ). + reference().resizeDimension< 1, 2 >( m_numPhases, m_numPhases ); // dP, dT, dC + + subRegion.registerField< phaseVolumeFraction_n >( getName() ). + reference().resizeDimension< 1 >( m_numPhases ); + } ); + + FaceManager & faceManager = mesh.getFaceManager(); + { + faceManager.registerField< totalMassFlux >( getName() ); + // TODO: add conditional registration later, this is only needed when there is a face-based Dirichlet BC + faceManager.registerField< facePressure >( getName() ); + faceManager.registerField< faceTemperature >( getName() ); + } + } ); +} + +void ImmiscibleMultiphaseFlow::setConstitutiveNames( ElementSubRegionBase & subRegion ) const +{ + string & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); + fluidName = getConstitutiveName< MultiFluidBase >( subRegion ); + GEOS_THROW_IF( fluidName.empty(), + GEOS_FMT( "{}: Fluid model not found on subregion {}", + getDataContext(), subRegion.getDataContext() ), + InputError ); + + string & relPermName = subRegion.registerWrapper< string >( viewKeyStruct::relPermNamesString() ). + setPlotLevel( PlotLevel::NOPLOT ). + setRestartFlags( RestartFlags::NO_WRITE ). + setSizedFromParent( 0 ). + setDescription( "Name of the relative permeability constitutive model to use" ). + reference(); + + relPermName = getConstitutiveName< RelativePermeabilityBase >( subRegion ); + + GEOS_THROW_IF( relPermName.empty(), + GEOS_FMT( "{}: Relative permeability model not found on subregion {}", + getDataContext(), subRegion.getDataContext() ), + InputError ); +} + +void ImmiscibleMultiphaseFlow::initializePreSubGroups() +{ + FlowSolverBase::initializePreSubGroups(); + + DomainPartition & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" ); + ConstitutiveManager const & cm = domain.getConstitutiveManager(); + + // 1. Validate various models against each other (must have same phases and components) + validateConstitutiveModels( domain ); + + // 2. Set the value of temperature + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + arrayView1d< string const > const & regionNames ) + + { + mesh.getElemManager().forElementSubRegions( regionNames, + [&]( localIndex const, + ElementSubRegionBase & subRegion ) + { + arrayView1d< real64 > const temp = subRegion.getField< fields::flow::temperature >(); + temp.setValues< parallelHostPolicy >( m_inputTemperature ); + } ); + } ); +} + +void ImmiscibleMultiphaseFlow::validateConstitutiveModels( DomainPartition const & domain ) const +{ + GEOS_MARK_FUNCTION; + + ConstitutiveManager const & cm = domain.getConstitutiveManager(); + MultiFluidBase const & referenceFluid = cm.getConstitutiveRelation< MultiFluidBase >( m_referenceFluidModelName ); + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel const & mesh, + arrayView1d< string const > const & regionNames ) + + { + mesh.getElemManager().forElementSubRegions( regionNames, + [&]( localIndex const, + ElementSubRegionBase const & subRegion ) + { + + string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); + MultiFluidBase const & fluid = getConstitutiveModel< MultiFluidBase >( subRegion, fluidName ); + compareMultiphaseModels( fluid, referenceFluid ); + compareMulticomponentModels( fluid, referenceFluid ); + + string const & relpermName = subRegion.getReference< string >( viewKeyStruct::relPermNamesString() ); + RelativePermeabilityBase const & relPerm = getConstitutiveModel< RelativePermeabilityBase >( subRegion, relpermName ); + compareMultiphaseModels( relPerm, referenceFluid ); + + } ); + } ); +} + +void ImmiscibleMultiphaseFlow::updateFluidModel( ObjectManagerBase & dataGroup ) const +{ + GEOS_MARK_FUNCTION; + + arrayView1d< real64 const > const pres = dataGroup.getField< fields::flow::pressure >(); + arrayView1d< real64 const > const temp = dataGroup.getField< fields::flow::temperature >(); + + string const & fluidName = dataGroup.getReference< string >( viewKeyStruct::fluidNamesString() ); + MultiFluidBase & fluid = getConstitutiveModel< MultiFluidBase >( dataGroup, fluidName ); +} + +void ImmiscibleMultiphaseFlow::updateRelPermModel( ObjectManagerBase & dataGroup ) const +{ + GEOS_MARK_FUNCTION; + + arrayView2d< real64 const, compflow::USD_PHASE > const phaseVolFrac = + dataGroup.getField< fields::flow::phaseVolumeFraction >(); + + string const & relPermName = dataGroup.getReference< string >( viewKeyStruct::relPermNamesString() ); + RelativePermeabilityBase & relPerm = getConstitutiveModel< RelativePermeabilityBase >( dataGroup, relPermName ); + + constitutive::constitutiveUpdatePassThru( relPerm, [&] ( auto & castedRelPerm ) + { + typename TYPEOFREF( castedRelPerm ) ::KernelWrapper relPermWrapper = castedRelPerm.createKernelWrapper(); + + isothermalImmiscibleMultiphaseFlowKernels:: + RelativePermeabilityUpdateKernel:: + launch< parallelDevicePolicy<> >( dataGroup.size(), + relPermWrapper, + phaseVolFrac ); + } ); +} + +void ImmiscibleMultiphaseFlow::updateCapPressureModel( ObjectManagerBase & dataGroup ) const +{ + GEOS_MARK_FUNCTION; + + if( m_hasCapPressure ) + { + arrayView2d< real64 const, compflow::USD_PHASE > const phaseVolFrac = + dataGroup.getField< fields::flow::phaseVolumeFraction >(); + + string const & cappresName = dataGroup.getReference< string >( viewKeyStruct::capPressureNamesString() ); + CapillaryPressureBase & capPressure = getConstitutiveModel< CapillaryPressureBase >( dataGroup, cappresName ); + + constitutive::constitutiveUpdatePassThru( capPressure, [&] ( auto & castedCapPres ) + { + typename TYPEOFREF( castedCapPres ) ::KernelWrapper capPresWrapper = castedCapPres.createKernelWrapper(); + + isothermalImmiscibleMultiphaseFlowKernels:: + CapillaryPressureUpdateKernel:: + launch< parallelDevicePolicy<> >( dataGroup.size(), + capPresWrapper, + phaseVolFrac ); + } ); + } +} + +real64 ImmiscibleMultiphaseFlow::updateFluidState( ElementSubRegionBase & subRegion ) const +{ + GEOS_MARK_FUNCTION; + + updateFluidModel( subRegion ); + updateRelPermModel( subRegion ); + updatePhaseMobility( subRegion ); + updateCapPressureModel( subRegion ); + + return maxDeltaPhaseVolFrac; +} + +void ImmiscibleMultiphaseFlow::initializeFluidState( MeshLevel & mesh, + DomainPartition & domain, + arrayView1d< string const > const & regionNames ) +{ + GEOS_MARK_FUNCTION; + + mesh.getElemManager().forElementSubRegions( regionNames, + [&]( localIndex const, + ElementSubRegionBase & subRegion ) + { + // 2. Assume global component fractions have been prescribed. + // Initialize constitutive state to get fluid density. + updateFluidModel( subRegion ); + + // 3. Back-calculate global component densities from fractions and total fluid density + // in order to initialize the primary solution variables + string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); + MultiFluidBase const & fluid = getConstitutiveModel< MultiFluidBase >( subRegion, fluidName ); + arrayView2d< real64 const, multifluid::USD_FLUID > const totalDens = fluid.totalDensity(); + + arrayView2d< real64 const, compflow::USD_COMP > const compFrac = + subRegion.getField< fields::flow::globalCompFraction >(); + arrayView2d< real64, compflow::USD_COMP > const compDens = + subRegion.getField< fields::flow::globalCompDensity >(); + + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const ei ) + { + for( integer ic = 0; ic < numComp; ++ic ) + { + compDens[ei][ic] = totalDens[ei][0] * compFrac[ei][ic]; + } + } ); + } ); + + // with initial component densities defined - check if they need to be corrected to avoid zero diags etc + chopNegativeDensities( domain ); + + // for some reason CUDA does not want the host_device lambda to be defined inside the generic lambda + // I need the exact type of the subRegion for updateSolidflowProperties to work well. + mesh.getElemManager().forElementSubRegions< CellElementSubRegion, + SurfaceElementSubRegion >( regionNames, [&]( localIndex const, + auto & subRegion ) + { + // 4. Initialize/update dependent state quantities + + // 4.1 Update the constitutive models that only depend on + // - the primary variables + // - the fluid constitutive quantities (as they have already been updated) + // We postpone the other constitutive models for now + // In addition, to avoid multiplying permeability/porosity bay netToGross in the assembly kernel, we do it once and for all here + arrayView1d< real64 const > const netToGross = subRegion.template getField< fields::flow::netToGross >(); + CoupledSolidBase const & porousSolid = + getConstitutiveModel< CoupledSolidBase >( subRegion, subRegion.template getReference< string >( viewKeyStruct::solidNamesString() ) ); + PermeabilityBase const & permeabilityModel = + getConstitutiveModel< PermeabilityBase >( subRegion, subRegion.template getReference< string >( viewKeyStruct::permeabilityNamesString() ) ); + permeabilityModel.scaleHorizontalPermeability( netToGross ); + porousSolid.scaleReferencePorosity( netToGross ); + saveConvergedState( subRegion ); // necessary for a meaningful porosity update in sequential schemes + updatePorosityAndPermeability( subRegion ); + updateCompAmount( subRegion ); + updatePhaseVolumeFraction( subRegion ); + + // Now, we initialize and update each constitutive model one by one + + // 4.2 Save the computed porosity into the old porosity + // + // Note: + // - This must be called after updatePorosityAndPermeability + // - This step depends on porosity + string const & solidName = subRegion.template getReference< string >( viewKeyStruct::solidNamesString() ); + CoupledSolidBase const & porousMaterial = getConstitutiveModel< CoupledSolidBase >( subRegion, solidName ); + porousMaterial.initializeState(); + + // 4.3 Initialize/update the relative permeability model using the initial phase volume fraction + // This is needed to handle relative permeability hysteresis + // Also, initialize the fluid model + // + // Note: + // - This must be called after updatePhaseVolumeFraction + // - This step depends on phaseVolFraction + + // initialized phase volume fraction + arrayView2d< real64 const, compflow::USD_PHASE > const phaseVolFrac = + subRegion.template getField< fields::flow::phaseVolumeFraction >(); + + string const & relpermName = subRegion.template getReference< string >( viewKeyStruct::relPermNamesString() ); + RelativePermeabilityBase & relPermMaterial = + getConstitutiveModel< RelativePermeabilityBase >( subRegion, relpermName ); + relPermMaterial.saveConvergedPhaseVolFractionState( phaseVolFrac ); // this needs to happen before calling updateRelPermModel + updateRelPermModel( subRegion ); + relPermMaterial.saveConvergedState(); // this needs to happen after calling updateRelPermModel + + string const & fluidName = subRegion.template getReference< string >( viewKeyStruct::fluidNamesString() ); + MultiFluidBase & fluidMaterial = getConstitutiveModel< MultiFluidBase >( subRegion, fluidName ); + fluidMaterial.initializeState(); + + // 4.4 Then, we initialize/update the capillary pressure model + // + // Note: + // - This must be called after updatePorosityAndPermeability + // - This step depends on porosity and permeability + if( m_hasCapPressure ) + { + // initialized porosity + arrayView2d< real64 const > const porosity = porousMaterial.getPorosity(); + + string const & permName = subRegion.template getReference< string >( viewKeyStruct::permeabilityNamesString() ); + PermeabilityBase const & permeabilityMaterial = + getConstitutiveModel< PermeabilityBase >( subRegion, permName ); + // initialized permeability + arrayView3d< real64 const > const permeability = permeabilityMaterial.permeability(); + + string const & capPressureName = subRegion.template getReference< string >( viewKeyStruct::capPressureNamesString() ); + CapillaryPressureBase const & capPressureMaterial = + getConstitutiveModel< CapillaryPressureBase >( subRegion, capPressureName ); + capPressureMaterial.initializeRockState( porosity, permeability ); // this needs to happen before calling updateCapPressureModel + updateCapPressureModel( subRegion ); + } + + // 4.5 Update the phase mobility + // + // Note: + // - This must be called after updateRelPermModel + // - This step depends phaseRelPerm + updatePhaseMobility( subRegion ); + + } ); + + // 5. Save initial pressure + mesh.getElemManager().forElementSubRegions( regionNames, [&]( localIndex const, + ElementSubRegionBase & subRegion ) + { + arrayView1d< real64 const > const pres = subRegion.getField< fields::flow::pressure >(); + arrayView1d< real64 > const initPres = subRegion.getField< fields::flow::initialPressure >(); + arrayView1d< real64 const > const temp = subRegion.getField< fields::flow::temperature >(); + arrayView1d< real64 > const initTemp = subRegion.template getField< fields::flow::initialTemperature >(); + initPres.setValues< parallelDevicePolicy<> >( pres ); + initTemp.setValues< parallelDevicePolicy<> >( temp ); + } ); +} + +void ImmiscibleMultiphaseFlow::initializePostInitialConditionsPreSubGroups() +{ + GEOS_MARK_FUNCTION; + + FlowSolverBase::initializePostInitialConditionsPreSubGroups(); + + DomainPartition & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" ); + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + arrayView1d< string const > const & regionNames ) + { + FieldIdentifiers fieldsToBeSync; + fieldsToBeSync.addElementFields( { fields::flow::pressure::key(), + fields::flow::globalCompDensity::key() }, + regionNames ); + + CommunicationTools::getInstance().synchronizeFields( fieldsToBeSync, mesh, domain.getNeighbors(), false ); + + mesh.getElemManager().forElementSubRegions< CellElementSubRegion, SurfaceElementSubRegion >( regionNames, + [&]( localIndex const, + auto & subRegion ) + { + // set mass fraction flag on fluid models + string const & fluidName = subRegion.template getReference< string >( viewKeyStruct::fluidNamesString() ); + MultiFluidBase & fluid = getConstitutiveModel< MultiFluidBase >( subRegion, fluidName ); + fluid.setMassFlag( m_useMass ); + + saveConvergedState( subRegion ); // necessary for a meaningful porosity update in sequential schemes + updatePorosityAndPermeability( subRegion ); + + CoupledSolidBase const & porousSolid = + getConstitutiveModel< CoupledSolidBase >( subRegion, + subRegion.template getReference< string >( viewKeyStruct::solidNamesString() ) ); + porousSolid.initializeState(); + } ); + + // Initialize primary variables from applied initial conditions + initializeFluidState( mesh, domain, regionNames ); + + mesh.getElemManager().forElementRegions< SurfaceElementRegion >( regionNames, + [&]( localIndex const, + SurfaceElementRegion & region ) + { + region.forElementSubRegions< FaceElementSubRegion >( [&]( FaceElementSubRegion & subRegion ) + { + subRegion.getWrapper< real64_array >( fields::flow::hydraulicAperture::key() ). + setApplyDefaultValue( region.getDefaultAperture() ); + } ); + } ); + + } ); + + // report to the user if some pore volumes are very small + // note: this function is here because: 1) porosity has been initialized and 2) NTG has been applied + validatePoreVolumes( domain ); +} + +void +ImmiscibleMultiphaseFlow::implicitStepSetup( real64 const & GEOS_UNUSED_PARAM( time_n ), + real64 const & GEOS_UNUSED_PARAM( dt ), + DomainPartition & domain ) +{ + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + arrayView1d< string const > const & regionNames ) + { + mesh.getElemManager().forElementSubRegions< CellElementSubRegion, + SurfaceElementSubRegion >( regionNames, + [&]( localIndex const, + auto & subRegion ) + { + saveConvergedState( subRegion ); + + // update porosity, permeability + updatePorosityAndPermeability( subRegion ); + // update all fluid properties + updateFluidState( subRegion ); + + // after the update, save the new saturation + arrayView2d< real64 const, compflow::USD_PHASE > const phaseVolFrac = + subRegion.template getField< fields::flow::phaseVolumeFraction >(); + + arrayView2d< real64, compflow::USD_PHASE > const phaseVolFrac_n = + subRegion.template getField< fields::flow::phaseVolumeFraction_n >(); + phaseVolFrac_n.setValues< parallelDevicePolicy<> >( phaseVolFrac ); + + } ); + } ); +} + +void ImmiscibleMultiphaseFlow::assembleSystem( real64 const GEOS_UNUSED_PARAM( time_n ), + real64 const dt, + DomainPartition & domain, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) +{ + GEOS_MARK_FUNCTION; + + assembleAccumulationTerm( domain, + dofManager, + localMatrix, + localRhs ); + + + assembleFluxTerms( dt, + domain, + dofManager, + localMatrix, + localRhs ); +} + +void ImmiscibleMultiphaseFlow::assembleAccumulationTerm( DomainPartition & domain, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) const +{ + GEOS_MARK_FUNCTION; + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel const & mesh, + arrayView1d< string const > const & regionNames ) + { + mesh.getElemManager().forElementSubRegions( regionNames, + [&]( localIndex const, + ElementSubRegionBase const & subRegion ) + { + string const dofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); + string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); + string const & solidName = subRegion.getReference< string >( viewKeyStruct::solidNamesString() ); + + MultiFluidBase const & fluid = getConstitutiveModel< MultiFluidBase >( subRegion, fluidName ); + } ); + } ); +} + +void ImmiscibleMultiphaseFlow::applyBoundaryConditions( real64 const time_n, + real64 const dt, + DomainPartition & domain, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) +{ + GEOS_MARK_FUNCTION; + + // apply pressure boundary conditions. + applyDirichletBC( time_n, dt, dofManager, domain, localMatrix.toViewConstSizes(), localRhs.toView() ); + + // apply flux boundary conditions + applySourceFluxBC( time_n, dt, dofManager, domain, localMatrix.toViewConstSizes(), localRhs.toView() ); +} + +namespace +{ +char const bcLogMessage[] = + "ImmiscibleMultiphaseFlow {}: at time {}s, " + "the <{}> boundary condition '{}' is applied to the element set '{}' in subRegion '{}'. " + "\nThe scale of this boundary condition is {} and multiplies the value of the provided function (if any). " + "\nThe total number of target elements (including ghost elements) is {}. " + "\nNote that if this number is equal to zero for all subRegions, the boundary condition will not be applied on this element set."; +} + +void ImmiscibleMultiphaseFlow::applySourceFluxBC( real64 const time, + real64 const dt, + DofManager const & dofManager, + DomainPartition & domain, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) const +{ + GEOS_MARK_FUNCTION; + + FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); + + string const dofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); + + // Step 1: count individual source flux boundary conditions + + std::map< string, localIndex > bcNameToBcId; + localIndex bcCounter = 0; + + fsManager.forSubGroups< SourceFluxBoundaryCondition >( [&] ( SourceFluxBoundaryCondition const & bc ) + { + // collect all the bc names to idx + bcNameToBcId[bc.getName()] = bcCounter; + bcCounter++; + } ); + + if( bcCounter == 0 ) + { + return; + } + + // Step 2: count the set size for each source flux (each source flux may have multiple target sets) + + array1d< globalIndex > bcAllSetsSize( bcNameToBcId.size() ); + + computeSourceFluxSizeScalingFactor( time, + dt, + domain, + bcNameToBcId, + bcAllSetsSize.toView() ); + + // Step 3: we are ready to impose the boundary condition, normalized by the set size + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + arrayView1d< string const > const & ) + { + fsManager.apply< ElementSubRegionBase, + SourceFluxBoundaryCondition >( time + dt, + mesh, + SourceFluxBoundaryCondition::catalogName(), + [&]( SourceFluxBoundaryCondition const & fs, + string const & setName, + SortedArrayView< localIndex const > const & targetSet, + ElementSubRegionBase & subRegion, + string const & ) + { + if( fs.getLogLevel() >= 1 && m_nonlinearSolverParameters.m_numNewtonIterations == 0 ) + { + globalIndex const numTargetElems = MpiWrapper::sum< globalIndex >( targetSet.size() ); + GEOS_LOG_RANK_0( GEOS_FMT( bcLogMessage, + getName(), time+dt, fs.getCatalogName(), fs.getName(), + setName, subRegion.getName(), fs.getScale(), numTargetElems ) ); + } + + if( targetSet.size() == 0 ) + { + return; + } + if( !subRegion.hasWrapper( dofKey ) ) + { + if( fs.getLogLevel() >= 1 ) + { + GEOS_LOG_RANK( GEOS_FMT( "{}: trying to apply SourceFlux, but its targetSet named '{}' intersects with non-simulated region named '{}'.", + getDataContext(), setName, subRegion.getName() ) ); + } + return; + } + + arrayView1d< globalIndex const > const dofNumber = subRegion.getReference< array1d< globalIndex > >( dofKey ); + arrayView1d< integer const > const ghostRank = subRegion.ghostRank(); + + // Step 3.1: get the values of the source boundary condition that need to be added to the rhs + // We don't use FieldSpecificationBase::applyConditionToSystem here because we want to account for the row permutation used in the + // compositional solvers + + array1d< globalIndex > dofArray( targetSet.size() ); + array1d< real64 > rhsContributionArray( targetSet.size() ); + arrayView1d< real64 > rhsContributionArrayView = rhsContributionArray.toView(); + localIndex const rankOffset = dofManager.rankOffset(); + + RAJA::ReduceSum< parallelDeviceReduce, real64 > massProd( 0.0 ); + + // note that the dofArray will not be used after this step (simpler to use dofNumber instead) + fs.computeRhsContribution< FieldSpecificationAdd, + parallelDevicePolicy<> >( targetSet.toViewConst(), + time + dt, + dt, + subRegion, + dofNumber, + rankOffset, + localMatrix, + dofArray.toView(), + rhsContributionArrayView, + [] GEOS_HOST_DEVICE ( localIndex const ) + { + return 0.0; + } ); + + // Step 3.2: we are ready to add the right-hand side contributions, taking into account our equation layout + + // get the normalizer + real64 const sizeScalingFactor = bcAllSetsSize[bcNameToBcId.at( fs.getName())]; + + integer const fluidComponentId = fs.getComponent(); + integer const numFluidComponents = m_numComponents; + integer const useTotalMassEquation = m_useTotalMassEquation; + forAll< parallelDevicePolicy<> >( targetSet.size(), [sizeScalingFactor, + targetSet, + rankOffset, + ghostRank, + fluidComponentId, + numFluidComponents, + useTotalMassEquation, + dofNumber, + rhsContributionArrayView, + localRhs, + massProd] GEOS_HOST_DEVICE ( localIndex const a ) + { + // we need to filter out ghosts here, because targetSet may contain them + localIndex const ei = targetSet[a]; + if( ghostRank[ei] >= 0 ) + { + return; + } + + real64 const rhsValue = rhsContributionArrayView[a] / sizeScalingFactor; // scale the contribution by the sizeScalingFactor here! + massProd += rhsValue; + if( useTotalMassEquation > 0 ) + { + // for all "fluid components", we add the value to the total mass balance equation + globalIndex const totalMassBalanceRow = dofNumber[ei] - rankOffset; + localRhs[totalMassBalanceRow] += rhsValue; + if( fluidComponentId < numFluidComponents - 1 ) + { + globalIndex const compMassBalanceRow = totalMassBalanceRow + fluidComponentId + 1; // component mass bal equations are shifted + localRhs[compMassBalanceRow] += rhsValue; + } + } + else + { + globalIndex const compMassBalanceRow = dofNumber[ei] - rankOffset + fluidComponentId; + localRhs[compMassBalanceRow] += rhsValue; + } + } ); + + SourceFluxStatsAggregator::forAllFluxStatWrappers( subRegion, fs.getName(), + [&]( SourceFluxStatsAggregator::WrappedStats & wrapper ) + { + // set the new sub-region statistics for this timestep + array1d< real64 > massProdArr{ m_numComponents }; + massProdArr[fluidComponentId] = massProd.get(); + wrapper.gatherTimeStepStats( time, dt, massProdArr.toViewConst(), targetSet.size() ); + } ); + } ); + } ); +} + +bool ImmiscibleMultiphaseFlow::validateDirichletBC( DomainPartition & domain, + real64 const time ) const +{ + constexpr integer MAX_NC = MultiFluidBase::MAX_NUM_COMPONENTS; + FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); + + bool bcConsistent = true; + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + arrayView1d< string const > const & ) + { + // map: regionName -> subRegionName -> setName -> numComps to check pressure/comp are present consistent + map< string, map< string, map< string, ComponentMask< MAX_NC > > > > bcPresCompStatusMap; + // map: regionName -> subRegionName -> setName check to that temperature is present/consistent + map< string, map< string, set< string > > > bcTempStatusMap; + + // 1. Check pressure Dirichlet BCs + fsManager.apply< ElementSubRegionBase >( time, + mesh, + fields::flow::pressure::key(), + [&]( FieldSpecificationBase const &, + string const & setName, + SortedArrayView< localIndex const > const &, + ElementSubRegionBase & subRegion, + string const & ) + { + // Check whether pressure has already been applied to this set + string const & subRegionName = subRegion.getName(); + string const & regionName = subRegion.getParent().getParent().getName(); + + auto & subRegionSetMap = bcPresCompStatusMap[regionName][subRegionName]; + if( subRegionSetMap.count( setName ) > 0 ) + { + bcConsistent = false; + GEOS_WARNING( GEOS_FMT( "Conflicting pressure boundary conditions on set {}/{}/{}", regionName, subRegionName, setName ) ); + } + subRegionSetMap[setName].setNumComp( m_numComponents ); + } ); + } ); + return bcConsistent; +} + +void ImmiscibleMultiphaseFlow::applyDirichletBC( real64 const time_n, + real64 const dt, + DofManager const & dofManager, + DomainPartition & domain, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) const +{ + GEOS_MARK_FUNCTION; + + // Only validate BC at the beginning of Newton loop + if( m_nonlinearSolverParameters.m_numNewtonIterations == 0 ) + { + bool const bcConsistent = validateDirichletBC( domain, time_n + dt ); + GEOS_ERROR_IF( !bcConsistent, GEOS_FMT( "ImmiscibleMultiphaseFlow {}: inconsistent boundary conditions", getDataContext() ) ); + } + + FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + arrayView1d< string const > const & ) + { + + // 1. Apply pressure Dirichlet BCs, store in a separate field + applyFieldValue< ElementSubRegionBase >( time_n, dt, mesh, bcLogMessage, + fields::flow::pressure::key(), fields::flow::bcPressure::key() ); + // 2. Apply composition BC (global component fraction) and store them for constitutive call + applyFieldValue< ElementSubRegionBase >( time_n, dt, mesh, bcLogMessage, + fields::flow::globalCompFraction::key(), fields::flow::globalCompFraction::key() ); + // 3. Apply temperature Dirichlet BCs, store in a separate field + if( m_isThermal ) + { + applyFieldValue< ElementSubRegionBase >( time_n, dt, mesh, bcLogMessage, + fields::flow::temperature::key(), fields::flow::bcTemperature::key() ); + } + + globalIndex const rankOffset = dofManager.rankOffset(); + string const dofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); + + // 4. Call constitutive update, back-calculate target global component densities and apply to the system + fsManager.apply< ElementSubRegionBase >( time_n + dt, + mesh, + fields::flow::pressure::key(), + [&] ( FieldSpecificationBase const &, + string const &, + SortedArrayView< localIndex const > const & targetSet, + ElementSubRegionBase & subRegion, + string const & ) + { + string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); + MultiFluidBase & fluid = getConstitutiveModel< MultiFluidBase >( subRegion, fluidName ); + + // in the isothermal case, we use the reservoir temperature to enforce the boundary condition + // in the thermal case, the validation function guarantees that temperature has been provided + string const temperatureKey = m_isThermal ? fields::flow::bcTemperature::key() : fields::flow::temperature::key(); + + arrayView1d< real64 const > const bcPres = + subRegion.getReference< array1d< real64 > >( fields::flow::bcPressure::key() ); + arrayView1d< real64 const > const bcTemp = + subRegion.getReference< array1d< real64 > >( temperatureKey ); + arrayView2d< real64 const, compflow::USD_COMP > const compFrac = + subRegion.getReference< array2d< real64, compflow::LAYOUT_COMP > >( fields::flow::globalCompFraction::key() ); + + constitutiveUpdatePassThru( fluid, [&] ( auto & castedFluid ) + { + using FluidType = TYPEOFREF( castedFluid ); + using ExecPolicy = typename FluidType::exec_policy; + typename FluidType::KernelWrapper fluidWrapper = castedFluid.createKernelWrapper(); + + thermalImmiscibleMultiphaseFlowKernels:: + FluidUpdateKernel:: + launch< ExecPolicy >( targetSet, + fluidWrapper, + bcPres, + bcTemp, + compFrac ); + } ); + + arrayView1d< integer const > const ghostRank = + subRegion.getReference< array1d< integer > >( ObjectManagerBase::viewKeyStruct::ghostRankString() ); + arrayView1d< globalIndex const > const dofNumber = + subRegion.getReference< array1d< globalIndex > >( dofKey ); + arrayView1d< real64 const > const pres = + subRegion.getReference< array1d< real64 > >( fields::flow::pressure::key() ); + arrayView2d< real64 const, compflow::USD_COMP > const compDens = + subRegion.getReference< array2d< real64, compflow::LAYOUT_COMP > >( fields::flow::globalCompDensity::key() ); + arrayView2d< real64 const, multifluid::USD_FLUID > const totalDens = fluid.totalDensity(); + + integer const numComp = m_numComponents; + forAll< parallelDevicePolicy<> >( targetSet.size(), [=] GEOS_HOST_DEVICE ( localIndex const a ) + { + localIndex const ei = targetSet[a]; + if( ghostRank[ei] >= 0 ) + { + return; + } + + globalIndex const dofIndex = dofNumber[ei]; + localIndex const localRow = dofIndex - rankOffset; + real64 rhsValue; + + // 4.1. Apply pressure value to the matrix/rhs + FieldSpecificationEqual::SpecifyFieldValue( dofIndex, + rankOffset, + localMatrix, + rhsValue, + bcPres[ei], + pres[ei] ); + localRhs[localRow] = rhsValue; + + // 4.2. For each component, apply target global density value + for( integer ic = 0; ic < numComp; ++ic ) + { + FieldSpecificationEqual::SpecifyFieldValue( dofIndex + ic + 1, + rankOffset, + localMatrix, + rhsValue, + totalDens[ei][0] * compFrac[ei][ic], + compDens[ei][ic] ); + localRhs[localRow + ic + 1] = rhsValue; + } + } ); + } ); + + // 5. Apply temperature to the system + if( m_isThermal ) + { + fsManager.apply< ElementSubRegionBase >( time_n + dt, + mesh, + fields::flow::temperature::key(), + [&] ( FieldSpecificationBase const &, + string const &, + SortedArrayView< localIndex const > const & targetSet, + ElementSubRegionBase & subRegion, + string const & ) + { + arrayView1d< integer const > const ghostRank = + subRegion.getReference< array1d< integer > >( ObjectManagerBase::viewKeyStruct::ghostRankString() ); + arrayView1d< globalIndex const > const dofNumber = + subRegion.getReference< array1d< globalIndex > >( dofKey ); + arrayView1d< real64 const > const bcTemp = + subRegion.getReference< array1d< real64 > >( fields::flow::bcTemperature::key() ); + arrayView1d< real64 const > const temp = + subRegion.getReference< array1d< real64 > >( fields::flow::temperature::key() ); + + integer const numComp = m_numComponents; + forAll< parallelDevicePolicy<> >( targetSet.size(), [=] GEOS_HOST_DEVICE ( localIndex const a ) + { + localIndex const ei = targetSet[a]; + if( ghostRank[ei] >= 0 ) + { + return; + } + + globalIndex const dofIndex = dofNumber[ei]; + localIndex const localRow = dofIndex - rankOffset; + real64 rhsValue; + + // 4.2. Apply temperature value to the matrix/rhs + FieldSpecificationEqual::SpecifyFieldValue( dofIndex + numComp + 1, + rankOffset, + localMatrix, + rhsValue, + bcTemp[ei], + temp[ei] ); + localRhs[localRow + numComp + 1] = rhsValue; + } ); + } ); + } + } ); +} + + + +void ImmiscibleMultiphaseFlow::resetStateToBeginningOfStep( DomainPartition & domain ) +{ + GEOS_MARK_FUNCTION; + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + arrayView1d< string const > const & regionNames ) + { + mesh.getElemManager().forElementSubRegions< CellElementSubRegion, + SurfaceElementSubRegion >( regionNames, + [&]( localIndex const, + auto & subRegion ) + { + arrayView1d< real64 > const & pres = + subRegion.template getField< fields::flow::pressure >(); + arrayView1d< real64 const > const & pres_n = + subRegion.template getField< fields::flow::pressure_n >(); + pres.setValues< parallelDevicePolicy<> >( pres_n ); + + arrayView2d< real64, compflow::USD_COMP > const & compDens = + subRegion.template getField< fields::flow::globalCompDensity >(); + arrayView2d< real64 const, compflow::USD_COMP > const & compDens_n = + subRegion.template getField< fields::flow::globalCompDensity_n >(); + compDens.setValues< parallelDevicePolicy<> >( compDens_n ); + + if( m_isThermal ) + { + arrayView1d< real64 > const & temp = + subRegion.template getField< fields::flow::temperature >(); + arrayView1d< real64 const > const & temp_n = + subRegion.template getField< fields::flow::temperature_n >(); + temp.setValues< parallelDevicePolicy<> >( temp_n ); + } + + // update porosity, permeability + updatePorosityAndPermeability( subRegion ); + // update all fluid properties + updateFluidState( subRegion ); + } ); + } ); +} + +void ImmiscibleMultiphaseFlow::implicitStepComplete( real64 const & time, + real64 const & dt, + DomainPartition & domain ) +{ + // Step 1: save the converged aquifer state + // note: we have to save the aquifer state **before** updating the pressure, + // otherwise the aquifer flux is saved with the wrong pressure time level + saveAquiferConvergedState( time, dt, domain ); + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + arrayView1d< string const > const & regionNames ) + { + mesh.getElemManager().forElementSubRegions( regionNames, + [&]( localIndex const, + ElementSubRegionBase & subRegion ) + { + // update deltaPressure + arrayView1d< real64 const > const pres = subRegion.getField< fields::flow::pressure >(); + arrayView1d< real64 const > const initPres = subRegion.getField< fields::flow::initialPressure >(); + arrayView1d< real64 > const deltaPres = subRegion.getField< fields::flow::deltaPressure >(); + isothermalImmiscibleMultiphaseFlowKernels::StatisticsKernel:: + saveDeltaPressure< parallelDevicePolicy<> >( subRegion.size(), pres, initPres, deltaPres ); + + // Step 2: save the converged fluid state + string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); + MultiFluidBase const & fluidMaterial = getConstitutiveModel< MultiFluidBase >( subRegion, fluidName ); + fluidMaterial.saveConvergedState(); + + // Step 3: save the converged solid state + string const & solidName = subRegion.getReference< string >( viewKeyStruct::solidNamesString() ); + CoupledSolidBase const & porousMaterial = getConstitutiveModel< CoupledSolidBase >( subRegion, solidName ); + if( m_keepFlowVariablesConstantDuringInitStep ) + { + porousMaterial.ignoreConvergedState(); // newPorosity <- porosity_n + } + else + { + porousMaterial.saveConvergedState(); // porosity_n <- porosity + } + + // Step 4: save converged state for the relperm model to handle hysteresis + arrayView2d< real64 const, compflow::USD_PHASE > const phaseVolFrac = + subRegion.getField< fields::flow::phaseVolumeFraction >(); + string const & relPermName = subRegion.getReference< string >( viewKeyStruct::relPermNamesString() ); + RelativePermeabilityBase const & relPermMaterial = + getConstitutiveModel< RelativePermeabilityBase >( subRegion, relPermName ); + relPermMaterial.saveConvergedPhaseVolFractionState( phaseVolFrac ); + + // Step 5: if capillary pressure is supported, send the converged porosity and permeability to the capillary pressure model + // note: this is needed when the capillary pressure depends on porosity and permeability (Leverett J-function for instance) + if( m_hasCapPressure ) + { + arrayView2d< real64 const > const porosity = porousMaterial.getPorosity(); + + string const & permName = subRegion.getReference< string >( viewKeyStruct::permeabilityNamesString() ); + PermeabilityBase const & permeabilityMaterial = + getConstitutiveModel< PermeabilityBase >( subRegion, permName ); + arrayView3d< real64 const > const permeability = permeabilityMaterial.permeability(); + + string const & capPressName = subRegion.getReference< string >( viewKeyStruct::capPressureNamesString() ); + CapillaryPressureBase const & capPressureMaterial = + getConstitutiveModel< CapillaryPressureBase >( subRegion, capPressName ); + capPressureMaterial.saveConvergedRockState( porosity, permeability ); + } + } ); + } ); +} + +void ImmiscibleMultiphaseFlow::saveConvergedState( ElementSubRegionBase & subRegion ) const +{ + FlowSolverBase::saveConvergedState( subRegion ); + + arrayView2d< real64 const, compflow::USD_COMP > const & compDens = + subRegion.template getField< fields::flow::globalCompDensity >(); + arrayView2d< real64, compflow::USD_COMP > const & compDens_n = + subRegion.template getField< fields::flow::globalCompDensity_n >(); + compDens_n.setValues< parallelDevicePolicy<> >( compDens ); + + arrayView2d< real64 const, compflow::USD_COMP > const & compAmount = + subRegion.template getField< fields::flow::compAmount >(); + arrayView2d< real64, compflow::USD_COMP > const & compAmount_n = + subRegion.template getField< fields::flow::compAmount_n >(); + compAmount_n.setValues< parallelDevicePolicy<> >( compAmount ); + + if( m_isFixedStressPoromechanicsUpdate ) + { + arrayView2d< real64, compflow::USD_COMP > const & compDens_k = + subRegion.template getField< fields::flow::globalCompDensity_k >(); + compDens_k.setValues< parallelDevicePolicy<> >( compDens ); + } +} + +void ImmiscibleMultiphaseFlow::updateState( DomainPartition & domain ) +{ + GEOS_MARK_FUNCTION; + + real64 maxDeltaPhaseVolFrac = 0.0; + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + arrayView1d< string const > const & regionNames ) + { + mesh.getElemManager().forElementSubRegions< CellElementSubRegion, + SurfaceElementSubRegion >( regionNames, [&]( localIndex const, + auto & subRegion ) + { + // update porosity, permeability, and solid internal energy + updatePorosityAndPermeability( subRegion ); + // update all fluid properties + real64 const deltaPhaseVolFrac = updateFluidState( subRegion ); + maxDeltaPhaseVolFrac = LvArray::math::max( maxDeltaPhaseVolFrac, deltaPhaseVolFrac ); + // for thermal, update solid internal energy + if( m_isThermal ) + { + updateSolidInternalEnergyModel( subRegion ); + updateEnergy( subRegion ); + } + } ); + } ); + + maxDeltaPhaseVolFrac = MpiWrapper::max( maxDeltaPhaseVolFrac ); + + GEOS_LOG_LEVEL_RANK_0( 1, GEOS_FMT( " {}: Max phase volume fraction change = {}", getName(), fmt::format( "{:.{}f}", maxDeltaPhaseVolFrac, 4 ) ) ); +} + +real64 ImmiscibleMultiphaseFlow::setNextDt( const geos::real64 & currentDt, geos::DomainPartition & domain ) +{ + return SolverBase::setNextDt( currentDt, domain ); +} + +REGISTER_CATALOG_ENTRY( SolverBase, ImmiscibleMultiphaseFlow, string const &, Group * const ) + +} // namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp new file mode 100644 index 00000000000..e2e7b6ef838 --- /dev/null +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp @@ -0,0 +1,389 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 Total, S.A + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2018-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/** + * @file ImmiscibleMultiphaseFlow.hpp + */ + +#ifndef GEOS_PHYSICSSOLVERS_FLUIDFLOW_IMMISCIBLEMULTIPHASEFLOW_HPP_ +#define GEOS_PHYSICSSOLVERS_FLUIDFLOW_IMMISCIBLEMULTIPHASEFLOW_HPP_ + +#include "physicsSolvers/fluidFlow/FlowSolverBase.hpp" +#include "fieldSpecification/FieldSpecificationManager.hpp" + +namespace geos +{ + +//START_SPHINX_INCLUDE_00 +/** + * @class ImmiscibleMultiphaseFlow + * + * An Immiscible multiphase flow solver + */ +class ImmiscibleMultiphaseFlow : public FlowSolverBase +{ +public: + + /** + * @brief main constructor for Group Objects + * @param name the name of this instantiation of Group in the repository + * @param parent the parent group of this instantiation of Group + */ + ImmiscibleMultiphaseFlow( const string & name, + Group * const parent ); + + /// deleted default constructor + ImmiscibleMultiphaseFlow() = delete; + + /// deleted copy constructor + ImmiscibleMultiphaseFlow( ImmiscibleMultiphaseFlow const & ) = delete; + + /// default move constructor + ImmiscibleMultiphaseFlow( ImmiscibleMultiphaseFlow && ) = default; + + /// deleted assignment operator + ImmiscibleMultiphaseFlow & operator=( ImmiscibleMultiphaseFlow const & ) = delete; + + /// deleted move operator + ImmiscibleMultiphaseFlow & operator=( ImmiscibleMultiphaseFlow && ) = delete; + + /** + * @brief default destructor + */ + virtual ~ImmiscibleMultiphaseFlow() override = default; + +//START_SPHINX_INCLUDE_01 + + virtual void registerDataOnMesh( Group & meshBodies ) override; + + /** + * @defgroup Solver Interface Functions + * + * These functions provide the primary interface that is required for derived classes + */ + /**@{*/ + + virtual void + implicitStepSetup( real64 const & time_n, + real64 const & dt, + DomainPartition & domain ) override; + + virtual void + assembleSystem( real64 const time_n, + real64 const dt, + DomainPartition & domain, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) override; + + virtual void + applyBoundaryConditions( real64 const time_n, + real64 const dt, + DomainPartition & domain, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) override; + + virtual void + resetStateToBeginningOfStep( DomainPartition & domain ) override; + + virtual void + implicitStepComplete( real64 const & time, + real64 const & dt, + DomainPartition & domain ) override; + + /** + * @brief Recompute phase volume fractions (saturations) from constitutive and primary variables + * @param dataGroup the group storing the required fields + */ + real64 updatePhaseVolumeFraction( ObjectManagerBase & dataGroup ) const; + + /** + * @brief Update all relevant fluid models using current values of pressure and composition + * @param dataGroup the group storing the required fields + */ + void updateFluidModel( ObjectManagerBase & dataGroup ) const; + + /** + * @brief Update all relevant relperm models using current values of phase volume fraction + * @param dataGroup the group storing the required fields + */ + void updateRelPermModel( ObjectManagerBase & dataGroup ) const; + + /** + * @brief Update all relevant capillary pressure models using current values of phase volume fraction + * @param dataGroup the group storing the required fields + */ + void updateCapPressureModel( ObjectManagerBase & dataGroup ) const; + + + + + /** + * @brief Recompute phase mobility from constitutive and primary variables + * @param dataGroup the group storing the required field + */ + virtual void updatePhaseMobility( ObjectManagerBase & dataGroup ) const = 0; + + real64 updateFluidState( ElementSubRegionBase & subRegion ) const; + + virtual void saveConvergedState( ElementSubRegionBase & subRegion ) const override final; + + virtual void saveSequentialIterationState( DomainPartition & domain ) override final; + + virtual void updateState( DomainPartition & domain ) override final; + + + /** + * @brief Getter for the number of fluid phases + * @return the number of phases + */ + integer numFluidPhases() const { return m_numPhases; } + + /** + * @brief assembles the accumulation and volume balance terms for all cells + * @param time_n previous time value + * @param dt time step + * @param domain the physical domain object + * @param dofManager degree-of-freedom manager associated with the linear system + * @param localMatrix the system matrix + * @param localRhs the system right-hand side vector + */ + void assembleAccumulationAndVolumeBalanceTerms( DomainPartition & domain, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) const; + + /** + * @brief assembles the flux terms for all cells + * @param time_n previous time value + * @param dt time step + * @param domain the physical domain object + * @param dofManager degree-of-freedom manager associated with the linear system + * @param matrix the system matrix + * @param rhs the system right-hand side vector + */ + virtual void + assembleFluxTerms( real64 const dt, + DomainPartition const & domain, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) const = 0; + /** + * @brief Initialize all variables from initial conditions + * @param domain the domain containing the mesh and fields + * + * Initialize all variables from initial conditions. This calculating primary variable values + * from prescribed intermediate values (i.e. global densities from global fractions) + * and any applicable hydrostatic equilibration of the domain + */ + void initializeFluidState( MeshLevel & mesh, DomainPartition & domain, arrayView1d< string const > const & regionNames ); + + /** + * @brief Compute the hydrostatic equilibrium using the compositions and temperature input tables + */ + void computeHydrostaticEquilibrium(); + + /** + * @brief Function to perform the Application of Dirichlet type BC's + * @param time current time + * @param dt time step + * @param dofManager degree-of-freedom manager associated with the linear system + * @param domain the domain + * @param localMatrix local system matrix + * @param localRhs local system right-hand side vector + */ + void applyDirichletBC( real64 const time, + real64 const dt, + DofManager const & dofManager, + DomainPartition & domain, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) const; + + /** + * @brief Apply source flux boundary conditions to the system + * @param time current time + * @param dt time step + * @param dofManager degree-of-freedom manager associated with the linear system + * @param domain the domain + * @param localMatrix local system matrix + * @param localRhs local system right-hand side vector + */ + void applySourceFluxBC( real64 const time, + real64 const dt, + DofManager const & dofManager, + DomainPartition & domain, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) const; + + /** + * @brief Apply aquifer boundary conditions to the system + * @param time current time + * @param dt time step + * @param dofManager degree-of-freedom manager associated with the linear system + * @param domain the domain + * @param localMatrix local system matrix + * @param localRhs local system right-hand side vector + */ + virtual void applyAquiferBC( real64 const time, + real64 const dt, + DofManager const & dofManager, + DomainPartition & domain, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) const = 0; + + /** + * @brief Function to fix the initial state during the initialization step in coupled problems + * @param[in] time current time + * @param[in] dt time step + * @param[in] dofManager degree-of-freedom manager associated with the linear system + * @param[in] domain the domain + * @param[in] localMatrix local system matrix + * @param[in] localRhs local system right-hand side vector + * @detail This function is meant to be called when the flag m_keepFlowVariablesConstantDuringInitStep is on + * The main use case is the initialization step in coupled problems during which we solve an elastic problem for a fixed pressure + */ + void keepFlowVariablesConstantDuringInitStep( real64 const time, + real64 const dt, + DofManager const & dofManager, + DomainPartition & domain, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) const; + + + /** + * @brief Sets all the negative component densities (if any) to zero. + * @param domain the physical domain object + */ + void chopNegativeDensities( DomainPartition & domain ); + + virtual real64 setNextDtBasedOnStateChange( real64 const & currentDt, + DomainPartition & domain ) override; + + void computeCFLNumbers( DomainPartition & domain, real64 const & dt, real64 & maxPhaseCFL, real64 & maxCompCFL ); + + /** + * @brief function to set the next time step size + * @param[in] currentDt the current time step size + * @param[in] domain the domain object + * @return the prescribed time step size + */ + real64 setNextDt( real64 const & currentDt, + DomainPartition & domain ) override; + + virtual real64 setNextDtBasedOnCFL( real64 const & currentDt, + DomainPartition & domain ) override; + + virtual void initializePostInitialConditionsPreSubGroups() override; + + integer useSimpleAccumulation() const { return m_useSimpleAccumulation; } + + integer useTotalMassEquation() const { return m_useTotalMassEquation; } + + virtual bool checkSequentialSolutionIncrements( DomainPartition & domain ) const override; + +protected: + + virtual void postInputInitialization() override; + + virtual void initializePreSubGroups() override; + + + /** + * @brief Utility function that checks the consistency of the constitutive models + * @param[in] domain the domain partition + * This function will produce an error if one of the constitutive models + * (fluid, relperm) is incompatible with the reference fluid model. + */ + void validateConstitutiveModels( DomainPartition const & domain ) const; + + /** + * @brief Initialize the aquifer boundary condition (gravity vector, water phase index) + * @param[in] cm reference to the global constitutive model manager + */ + void initializeAquiferBC( constitutive::ConstitutiveManager const & cm ) const; + + /** + * @brief Utility function that encapsulates the call to FieldSpecificationBase::applyFieldValue in BC application + * @param[in] time_n the time at the beginning of the step + * @param[in] dt the time step + * @param[in] mesh the mesh level object + * @param[in] logMessage the log message issued by the solver if the bc is called + * @param[in] fieldKey the key of the field specified in the xml file + * @param[in] boundaryFieldKey the key of the boundary field + */ + template< typename OBJECT_TYPE > + void applyFieldValue( real64 const & time_n, + real64 const & dt, + MeshLevel & mesh, + char const logMessage[], + string const fieldKey, + string const boundaryFieldKey ) const; + + /// the max number of fluid phases + integer m_numPhases; + + /// flag to determine whether or not to apply capillary pressure + integer m_hasCapPressure; + + /// the targeted CFL for timestep + real64 m_targetFlowCFL; + +private: + + virtual void setConstitutiveNames( ElementSubRegionBase & subRegion ) const override; + +}; + +template< typename OBJECT_TYPE > +void ImmiscibleMultiphaseFlow::applyFieldValue( real64 const & time_n, + real64 const & dt, + MeshLevel & mesh, + char const logMessage[], + string const fieldKey, + string const boundaryFieldKey ) const +{ + FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); + + fsManager.apply< OBJECT_TYPE >( time_n + dt, + mesh, + fieldKey, + [&]( FieldSpecificationBase const & fs, + string const & setName, + SortedArrayView< localIndex const > const & lset, + OBJECT_TYPE & targetGroup, + string const & ) + { + if( fs.getLogLevel() >= 1 && m_nonlinearSolverParameters.m_numNewtonIterations == 0 ) + { + globalIndex const numTargetElems = MpiWrapper::sum< globalIndex >( lset.size() ); + GEOS_LOG_RANK_0( GEOS_FMT( logMessage, + getName(), time_n+dt, fs.getCatalogName(), fs.getName(), + setName, targetGroup.getName(), fs.getScale(), numTargetElems ) ); + } + + // Specify the bc value of the field + fs.applyFieldValue< FieldSpecificationEqual, + parallelDevicePolicy<> >( lset, + time_n + dt, + targetGroup, + boundaryFieldKey ); + } ); +} + + +} // namespace geos + +#endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_IMMISCIBLEMULTIPHASEFLOW_HPP_ From 22aed17ce1322055d2408ae72c56a88d928de1d6 Mon Sep 17 00:00:00 2001 From: Matteo Cusini Date: Fri, 26 Jul 2024 16:47:44 -0700 Subject: [PATCH 002/104] catalog name, register and cmakelist. --- .../physicsSolvers/fluidFlow/CMakeLists.txt | 2 + .../fluidFlow/ImmiscibleMultiphaseFlow.cpp | 27 +++-- .../fluidFlow/ImmiscibleMultiphaseFlow.hpp | 103 ++---------------- 3 files changed, 30 insertions(+), 102 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt b/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt index ee3263c50b2..65e1180ffe2 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt +++ b/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt @@ -7,6 +7,7 @@ set( physicsSolvers_headers fluidFlow/IsothermalCompositionalMultiphaseBaseKernels.hpp fluidFlow/ThermalCompositionalMultiphaseBaseKernels.hpp fluidFlow/CompositionalMultiphaseFVM.hpp + fluidFlow/ImmiscibleMultiphaseFlow.hpp fluidFlow/IsothermalCompositionalMultiphaseFVMKernels.hpp fluidFlow/IsothermalCompositionalMultiphaseFVMKernelUtilities.hpp fluidFlow/ThermalCompositionalMultiphaseFVMKernels.hpp @@ -59,6 +60,7 @@ set( physicsSolvers_sources fluidFlow/CompositionalMultiphaseBase.cpp fluidFlow/CompositionalMultiphaseFVM.cpp fluidFlow/CompositionalMultiphaseStatistics.cpp + fluidFlow/ImmiscibleMultiphaseFlow.cpp fluidFlow/IsothermalCompositionalMultiphaseFVMKernels.cpp fluidFlow/CompositionalMultiphaseHybridFVM.cpp fluidFlow/CompositionalMultiphaseHybridFVMKernels.cpp diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index db3a431bcd0..74e4ba7ad14 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -238,16 +238,16 @@ void ImmiscibleMultiphaseFlow::updateRelPermModel( ObjectManagerBase & dataGroup string const & relPermName = dataGroup.getReference< string >( viewKeyStruct::relPermNamesString() ); RelativePermeabilityBase & relPerm = getConstitutiveModel< RelativePermeabilityBase >( dataGroup, relPermName ); - constitutive::constitutiveUpdatePassThru( relPerm, [&] ( auto & castedRelPerm ) - { - typename TYPEOFREF( castedRelPerm ) ::KernelWrapper relPermWrapper = castedRelPerm.createKernelWrapper(); - - isothermalImmiscibleMultiphaseFlowKernels:: - RelativePermeabilityUpdateKernel:: - launch< parallelDevicePolicy<> >( dataGroup.size(), - relPermWrapper, - phaseVolFrac ); - } ); + // constitutive::constitutiveUpdatePassThru( relPerm, [&] ( auto & castedRelPerm ) + // { + // typename TYPEOFREF( castedRelPerm ) ::KernelWrapper relPermWrapper = castedRelPerm.createKernelWrapper(); + + // isothermalImmiscibleMultiphaseFlowKernels:: + // RelativePermeabilityUpdateKernel:: + // launch< parallelDevicePolicy<> >( dataGroup.size(), + // relPermWrapper, + // phaseVolFrac ); + // } ); } void ImmiscibleMultiphaseFlow::updateCapPressureModel( ObjectManagerBase & dataGroup ) const @@ -565,6 +565,13 @@ void ImmiscibleMultiphaseFlow::assembleAccumulationTerm( DomainPartition & domai } ); } +void ImmiscibleMultiphaseFlow::assembleFluxTerms( real64 const dt, + DomainPartition const & domain, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) const +{} + void ImmiscibleMultiphaseFlow::applyBoundaryConditions( real64 const time_n, real64 const dt, DomainPartition & domain, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp index e2e7b6ef838..ec5c2605c20 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp @@ -63,8 +63,15 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase * @brief default destructor */ virtual ~ImmiscibleMultiphaseFlow() override = default; - -//START_SPHINX_INCLUDE_01 + /** + * @brief name of the solver in the object catalog + * @return string that contains the catalog name to generate a new object through the object catalog. + */ + static string catalogName() { return "ImmiscibleMultiphaseFlow"; } + /** + * @copydoc SolverBase::getCatalogName() + */ + string getCatalogName() const override { return catalogName(); } virtual void registerDataOnMesh( Group & meshBodies ) override; @@ -104,12 +111,6 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase real64 const & dt, DomainPartition & domain ) override; - /** - * @brief Recompute phase volume fractions (saturations) from constitutive and primary variables - * @param dataGroup the group storing the required fields - */ - real64 updatePhaseVolumeFraction( ObjectManagerBase & dataGroup ) const; - /** * @brief Update all relevant fluid models using current values of pressure and composition * @param dataGroup the group storing the required fields @@ -129,8 +130,6 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase void updateCapPressureModel( ObjectManagerBase & dataGroup ) const; - - /** * @brief Recompute phase mobility from constitutive and primary variables * @param dataGroup the group storing the required field @@ -141,7 +140,6 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase virtual void saveConvergedState( ElementSubRegionBase & subRegion ) const override final; - virtual void saveSequentialIterationState( DomainPartition & domain ) override final; virtual void updateState( DomainPartition & domain ) override final; @@ -161,7 +159,7 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase * @param localMatrix the system matrix * @param localRhs the system right-hand side vector */ - void assembleAccumulationAndVolumeBalanceTerms( DomainPartition & domain, + void assembleAccumulationTerm( DomainPartition & domain, DofManager const & dofManager, CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) const; @@ -180,7 +178,7 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase DomainPartition const & domain, DofManager const & dofManager, CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) const = 0; + arrayView1d< real64 > const & localRhs ) const override final; /** * @brief Initialize all variables from initial conditions * @param domain the domain containing the mesh and fields @@ -191,11 +189,6 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase */ void initializeFluidState( MeshLevel & mesh, DomainPartition & domain, arrayView1d< string const > const & regionNames ); - /** - * @brief Compute the hydrostatic equilibrium using the compositions and temperature input tables - */ - void computeHydrostaticEquilibrium(); - /** * @brief Function to perform the Application of Dirichlet type BC's * @param time current time @@ -227,53 +220,6 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase DomainPartition & domain, CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) const; - - /** - * @brief Apply aquifer boundary conditions to the system - * @param time current time - * @param dt time step - * @param dofManager degree-of-freedom manager associated with the linear system - * @param domain the domain - * @param localMatrix local system matrix - * @param localRhs local system right-hand side vector - */ - virtual void applyAquiferBC( real64 const time, - real64 const dt, - DofManager const & dofManager, - DomainPartition & domain, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) const = 0; - - /** - * @brief Function to fix the initial state during the initialization step in coupled problems - * @param[in] time current time - * @param[in] dt time step - * @param[in] dofManager degree-of-freedom manager associated with the linear system - * @param[in] domain the domain - * @param[in] localMatrix local system matrix - * @param[in] localRhs local system right-hand side vector - * @detail This function is meant to be called when the flag m_keepFlowVariablesConstantDuringInitStep is on - * The main use case is the initialization step in coupled problems during which we solve an elastic problem for a fixed pressure - */ - void keepFlowVariablesConstantDuringInitStep( real64 const time, - real64 const dt, - DofManager const & dofManager, - DomainPartition & domain, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) const; - - - /** - * @brief Sets all the negative component densities (if any) to zero. - * @param domain the physical domain object - */ - void chopNegativeDensities( DomainPartition & domain ); - - virtual real64 setNextDtBasedOnStateChange( real64 const & currentDt, - DomainPartition & domain ) override; - - void computeCFLNumbers( DomainPartition & domain, real64 const & dt, real64 & maxPhaseCFL, real64 & maxCompCFL ); - /** * @brief function to set the next time step size * @param[in] currentDt the current time step size @@ -283,38 +229,14 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase real64 setNextDt( real64 const & currentDt, DomainPartition & domain ) override; - virtual real64 setNextDtBasedOnCFL( real64 const & currentDt, - DomainPartition & domain ) override; - virtual void initializePostInitialConditionsPreSubGroups() override; - integer useSimpleAccumulation() const { return m_useSimpleAccumulation; } - - integer useTotalMassEquation() const { return m_useTotalMassEquation; } - - virtual bool checkSequentialSolutionIncrements( DomainPartition & domain ) const override; - protected: virtual void postInputInitialization() override; virtual void initializePreSubGroups() override; - - /** - * @brief Utility function that checks the consistency of the constitutive models - * @param[in] domain the domain partition - * This function will produce an error if one of the constitutive models - * (fluid, relperm) is incompatible with the reference fluid model. - */ - void validateConstitutiveModels( DomainPartition const & domain ) const; - - /** - * @brief Initialize the aquifer boundary condition (gravity vector, water phase index) - * @param[in] cm reference to the global constitutive model manager - */ - void initializeAquiferBC( constitutive::ConstitutiveManager const & cm ) const; - /** * @brief Utility function that encapsulates the call to FieldSpecificationBase::applyFieldValue in BC application * @param[in] time_n the time at the beginning of the step @@ -338,9 +260,6 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase /// flag to determine whether or not to apply capillary pressure integer m_hasCapPressure; - /// the targeted CFL for timestep - real64 m_targetFlowCFL; - private: virtual void setConstitutiveNames( ElementSubRegionBase & subRegion ) const override; From fd51d9191444e8c54c0d02a24f2a9f55421c7c1b Mon Sep 17 00:00:00 2001 From: Matteo Cusini Date: Mon, 29 Jul 2024 15:45:00 -0700 Subject: [PATCH 003/104] fix fields. --- src/coreComponents/common/DataLayouts.hpp | 29 ++ .../fluidFlow/ImmiscibleMultiphaseFlow.cpp | 305 +----------------- .../fluidFlow/ImmiscibleMultiphaseFlow.hpp | 13 +- .../ImmiscibleMultiphaseFlowFields.hpp | 93 ++++++ 4 files changed, 135 insertions(+), 305 deletions(-) create mode 100644 src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp diff --git a/src/coreComponents/common/DataLayouts.hpp b/src/coreComponents/common/DataLayouts.hpp index 38d149a1938..d1c892754ee 100644 --- a/src/coreComponents/common/DataLayouts.hpp +++ b/src/coreComponents/common/DataLayouts.hpp @@ -205,6 +205,35 @@ static constexpr int STIFFNESS_USD = LvArray::typeManipulation::getStrideOneDime } // namespace solid + +namespace immiscibleFlow +{ +#if defined( GEOS_USE_DEVICE ) + +/// Phase property array layout +using LAYOUT_PHASE = RAJA::PERM_JI; + +/// Phase property array layout +using LAYOUT_PHASE_DS = RAJA::PERM_JKI; + +#else + +/// Phase property array layout +using LAYOUT_PHASE = RAJA::PERM_IJ; + +/// Phase property array layout +using LAYOUT_PHASE_DS = RAJA::PERM_IJK; + +#endif + +/// Phase property unit stride dimension +static constexpr int USD_PHASE = LvArray::typeManipulation::getStrideOneDimension( LAYOUT_PHASE{} ); + +/// Phase property compositional derivative unit stride dimension +static constexpr int USD_PHASE_DS = LvArray::typeManipulation::getStrideOneDimension( LAYOUT_PHASE_DS{} ); + +} // namespace immiscibleFlow + namespace compflow { diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index 74e4ba7ad14..0c7932f7ba2 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -19,6 +19,8 @@ #include "ImmiscibleMultiphaseFlow.hpp" + +#include "ImmiscibleMultiphaseFlowFields.hpp" #include "constitutive/ConstitutiveManager.hpp" #include "constitutive/capillaryPressure/CapillaryPressureFields.hpp" #include "constitutive/capillaryPressure/capillaryPressureSelector.hpp" @@ -33,6 +35,7 @@ namespace geos using namespace dataRepository; using namespace constitutive; +using namespace fields:flow:immiscibleFlow; ImmiscibleMultiphaseFlow::ImmiscibleMultiphaseFlow( const string & name, Group * const parent ) @@ -106,15 +109,14 @@ void ImmiscibleMultiphaseFlow::registerDataOnMesh( Group & meshBodies ) InputError ); } - - string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); - MultiFluidBase const & fluid = getConstitutiveModel< MultiFluidBase >( subRegion, fluidName ); - // The resizing of the arrays needs to happen here, before the call to initializePreSubGroups, // to make sure that the dimensions are properly set before the timeHistoryOutput starts its initialization. subRegion.registerField< phaseVolumeFraction >( getName() ). setDimLabels( 1, fluid.phaseNames() ). reference().resizeDimension< 1 >( m_numPhases ); + + subRegion.registerField< phaseVolumeFraction_n >( getName() ). + reference().resizeDimension< 1 >( m_numPhases ); subRegion.registerField< phaseMobility >( getName() ). setDimLabels( 1, fluid.phaseNames() ). @@ -123,29 +125,17 @@ void ImmiscibleMultiphaseFlow::registerDataOnMesh( Group & meshBodies ) subRegion.registerField< dPhaseMobility >( getName() ). reference().resizeDimension< 1, 2 >( m_numPhases, m_numPhases ); // dP, dT, dC - subRegion.registerField< phaseVolumeFraction_n >( getName() ). - reference().resizeDimension< 1 >( m_numPhases ); } ); FaceManager & faceManager = mesh.getFaceManager(); { faceManager.registerField< totalMassFlux >( getName() ); - // TODO: add conditional registration later, this is only needed when there is a face-based Dirichlet BC - faceManager.registerField< facePressure >( getName() ); - faceManager.registerField< faceTemperature >( getName() ); } } ); } void ImmiscibleMultiphaseFlow::setConstitutiveNames( ElementSubRegionBase & subRegion ) const { - string & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); - fluidName = getConstitutiveName< MultiFluidBase >( subRegion ); - GEOS_THROW_IF( fluidName.empty(), - GEOS_FMT( "{}: Fluid model not found on subregion {}", - getDataContext(), subRegion.getDataContext() ), - InputError ); - string & relPermName = subRegion.registerWrapper< string >( viewKeyStruct::relPermNamesString() ). setPlotLevel( PlotLevel::NOPLOT ). setRestartFlags( RestartFlags::NO_WRITE ). @@ -192,7 +182,6 @@ void ImmiscibleMultiphaseFlow::validateConstitutiveModels( DomainPartition const GEOS_MARK_FUNCTION; ConstitutiveManager const & cm = domain.getConstitutiveManager(); - MultiFluidBase const & referenceFluid = cm.getConstitutiveRelation< MultiFluidBase >( m_referenceFluidModelName ); forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, MeshLevel const & mesh, @@ -203,16 +192,9 @@ void ImmiscibleMultiphaseFlow::validateConstitutiveModels( DomainPartition const [&]( localIndex const, ElementSubRegionBase const & subRegion ) { - - string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); - MultiFluidBase const & fluid = getConstitutiveModel< MultiFluidBase >( subRegion, fluidName ); - compareMultiphaseModels( fluid, referenceFluid ); - compareMulticomponentModels( fluid, referenceFluid ); - string const & relpermName = subRegion.getReference< string >( viewKeyStruct::relPermNamesString() ); RelativePermeabilityBase const & relPerm = getConstitutiveModel< RelativePermeabilityBase >( subRegion, relpermName ); compareMultiphaseModels( relPerm, referenceFluid ); - } ); } ); } @@ -223,9 +205,6 @@ void ImmiscibleMultiphaseFlow::updateFluidModel( ObjectManagerBase & dataGroup ) arrayView1d< real64 const > const pres = dataGroup.getField< fields::flow::pressure >(); arrayView1d< real64 const > const temp = dataGroup.getField< fields::flow::temperature >(); - - string const & fluidName = dataGroup.getReference< string >( viewKeyStruct::fluidNamesString() ); - MultiFluidBase & fluid = getConstitutiveModel< MultiFluidBase >( dataGroup, fluidName ); } void ImmiscibleMultiphaseFlow::updateRelPermModel( ObjectManagerBase & dataGroup ) const @@ -301,24 +280,6 @@ void ImmiscibleMultiphaseFlow::initializeFluidState( MeshLevel & mesh, // Initialize constitutive state to get fluid density. updateFluidModel( subRegion ); - // 3. Back-calculate global component densities from fractions and total fluid density - // in order to initialize the primary solution variables - string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); - MultiFluidBase const & fluid = getConstitutiveModel< MultiFluidBase >( subRegion, fluidName ); - arrayView2d< real64 const, multifluid::USD_FLUID > const totalDens = fluid.totalDensity(); - - arrayView2d< real64 const, compflow::USD_COMP > const compFrac = - subRegion.getField< fields::flow::globalCompFraction >(); - arrayView2d< real64, compflow::USD_COMP > const compDens = - subRegion.getField< fields::flow::globalCompDensity >(); - - forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const ei ) - { - for( integer ic = 0; ic < numComp; ++ic ) - { - compDens[ei][ic] = totalDens[ei][0] * compFrac[ei][ic]; - } - } ); } ); // with initial component densities defined - check if they need to be corrected to avoid zero diags etc @@ -379,10 +340,6 @@ void ImmiscibleMultiphaseFlow::initializeFluidState( MeshLevel & mesh, updateRelPermModel( subRegion ); relPermMaterial.saveConvergedState(); // this needs to happen after calling updateRelPermModel - string const & fluidName = subRegion.template getReference< string >( viewKeyStruct::fluidNamesString() ); - MultiFluidBase & fluidMaterial = getConstitutiveModel< MultiFluidBase >( subRegion, fluidName ); - fluidMaterial.initializeState(); - // 4.4 Then, we initialize/update the capillary pressure model // // Note: @@ -451,11 +408,6 @@ void ImmiscibleMultiphaseFlow::initializePostInitialConditionsPreSubGroups() [&]( localIndex const, auto & subRegion ) { - // set mass fraction flag on fluid models - string const & fluidName = subRegion.template getReference< string >( viewKeyStruct::fluidNamesString() ); - MultiFluidBase & fluid = getConstitutiveModel< MultiFluidBase >( subRegion, fluidName ); - fluid.setMassFlag( m_useMass ); - saveConvergedState( subRegion ); // necessary for a meaningful porosity update in sequential schemes updatePorosityAndPermeability( subRegion ); @@ -559,8 +511,6 @@ void ImmiscibleMultiphaseFlow::assembleAccumulationTerm( DomainPartition & domai string const dofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); string const & solidName = subRegion.getReference< string >( viewKeyStruct::solidNamesString() ); - - MultiFluidBase const & fluid = getConstitutiveModel< MultiFluidBase >( subRegion, fluidName ); } ); } ); } @@ -765,222 +715,6 @@ void ImmiscibleMultiphaseFlow::applySourceFluxBC( real64 const time, } ); } -bool ImmiscibleMultiphaseFlow::validateDirichletBC( DomainPartition & domain, - real64 const time ) const -{ - constexpr integer MAX_NC = MultiFluidBase::MAX_NUM_COMPONENTS; - FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); - - bool bcConsistent = true; - - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel & mesh, - arrayView1d< string const > const & ) - { - // map: regionName -> subRegionName -> setName -> numComps to check pressure/comp are present consistent - map< string, map< string, map< string, ComponentMask< MAX_NC > > > > bcPresCompStatusMap; - // map: regionName -> subRegionName -> setName check to that temperature is present/consistent - map< string, map< string, set< string > > > bcTempStatusMap; - - // 1. Check pressure Dirichlet BCs - fsManager.apply< ElementSubRegionBase >( time, - mesh, - fields::flow::pressure::key(), - [&]( FieldSpecificationBase const &, - string const & setName, - SortedArrayView< localIndex const > const &, - ElementSubRegionBase & subRegion, - string const & ) - { - // Check whether pressure has already been applied to this set - string const & subRegionName = subRegion.getName(); - string const & regionName = subRegion.getParent().getParent().getName(); - - auto & subRegionSetMap = bcPresCompStatusMap[regionName][subRegionName]; - if( subRegionSetMap.count( setName ) > 0 ) - { - bcConsistent = false; - GEOS_WARNING( GEOS_FMT( "Conflicting pressure boundary conditions on set {}/{}/{}", regionName, subRegionName, setName ) ); - } - subRegionSetMap[setName].setNumComp( m_numComponents ); - } ); - } ); - return bcConsistent; -} - -void ImmiscibleMultiphaseFlow::applyDirichletBC( real64 const time_n, - real64 const dt, - DofManager const & dofManager, - DomainPartition & domain, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) const -{ - GEOS_MARK_FUNCTION; - - // Only validate BC at the beginning of Newton loop - if( m_nonlinearSolverParameters.m_numNewtonIterations == 0 ) - { - bool const bcConsistent = validateDirichletBC( domain, time_n + dt ); - GEOS_ERROR_IF( !bcConsistent, GEOS_FMT( "ImmiscibleMultiphaseFlow {}: inconsistent boundary conditions", getDataContext() ) ); - } - - FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); - - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel & mesh, - arrayView1d< string const > const & ) - { - - // 1. Apply pressure Dirichlet BCs, store in a separate field - applyFieldValue< ElementSubRegionBase >( time_n, dt, mesh, bcLogMessage, - fields::flow::pressure::key(), fields::flow::bcPressure::key() ); - // 2. Apply composition BC (global component fraction) and store them for constitutive call - applyFieldValue< ElementSubRegionBase >( time_n, dt, mesh, bcLogMessage, - fields::flow::globalCompFraction::key(), fields::flow::globalCompFraction::key() ); - // 3. Apply temperature Dirichlet BCs, store in a separate field - if( m_isThermal ) - { - applyFieldValue< ElementSubRegionBase >( time_n, dt, mesh, bcLogMessage, - fields::flow::temperature::key(), fields::flow::bcTemperature::key() ); - } - - globalIndex const rankOffset = dofManager.rankOffset(); - string const dofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); - - // 4. Call constitutive update, back-calculate target global component densities and apply to the system - fsManager.apply< ElementSubRegionBase >( time_n + dt, - mesh, - fields::flow::pressure::key(), - [&] ( FieldSpecificationBase const &, - string const &, - SortedArrayView< localIndex const > const & targetSet, - ElementSubRegionBase & subRegion, - string const & ) - { - string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); - MultiFluidBase & fluid = getConstitutiveModel< MultiFluidBase >( subRegion, fluidName ); - - // in the isothermal case, we use the reservoir temperature to enforce the boundary condition - // in the thermal case, the validation function guarantees that temperature has been provided - string const temperatureKey = m_isThermal ? fields::flow::bcTemperature::key() : fields::flow::temperature::key(); - - arrayView1d< real64 const > const bcPres = - subRegion.getReference< array1d< real64 > >( fields::flow::bcPressure::key() ); - arrayView1d< real64 const > const bcTemp = - subRegion.getReference< array1d< real64 > >( temperatureKey ); - arrayView2d< real64 const, compflow::USD_COMP > const compFrac = - subRegion.getReference< array2d< real64, compflow::LAYOUT_COMP > >( fields::flow::globalCompFraction::key() ); - - constitutiveUpdatePassThru( fluid, [&] ( auto & castedFluid ) - { - using FluidType = TYPEOFREF( castedFluid ); - using ExecPolicy = typename FluidType::exec_policy; - typename FluidType::KernelWrapper fluidWrapper = castedFluid.createKernelWrapper(); - - thermalImmiscibleMultiphaseFlowKernels:: - FluidUpdateKernel:: - launch< ExecPolicy >( targetSet, - fluidWrapper, - bcPres, - bcTemp, - compFrac ); - } ); - - arrayView1d< integer const > const ghostRank = - subRegion.getReference< array1d< integer > >( ObjectManagerBase::viewKeyStruct::ghostRankString() ); - arrayView1d< globalIndex const > const dofNumber = - subRegion.getReference< array1d< globalIndex > >( dofKey ); - arrayView1d< real64 const > const pres = - subRegion.getReference< array1d< real64 > >( fields::flow::pressure::key() ); - arrayView2d< real64 const, compflow::USD_COMP > const compDens = - subRegion.getReference< array2d< real64, compflow::LAYOUT_COMP > >( fields::flow::globalCompDensity::key() ); - arrayView2d< real64 const, multifluid::USD_FLUID > const totalDens = fluid.totalDensity(); - - integer const numComp = m_numComponents; - forAll< parallelDevicePolicy<> >( targetSet.size(), [=] GEOS_HOST_DEVICE ( localIndex const a ) - { - localIndex const ei = targetSet[a]; - if( ghostRank[ei] >= 0 ) - { - return; - } - - globalIndex const dofIndex = dofNumber[ei]; - localIndex const localRow = dofIndex - rankOffset; - real64 rhsValue; - - // 4.1. Apply pressure value to the matrix/rhs - FieldSpecificationEqual::SpecifyFieldValue( dofIndex, - rankOffset, - localMatrix, - rhsValue, - bcPres[ei], - pres[ei] ); - localRhs[localRow] = rhsValue; - - // 4.2. For each component, apply target global density value - for( integer ic = 0; ic < numComp; ++ic ) - { - FieldSpecificationEqual::SpecifyFieldValue( dofIndex + ic + 1, - rankOffset, - localMatrix, - rhsValue, - totalDens[ei][0] * compFrac[ei][ic], - compDens[ei][ic] ); - localRhs[localRow + ic + 1] = rhsValue; - } - } ); - } ); - - // 5. Apply temperature to the system - if( m_isThermal ) - { - fsManager.apply< ElementSubRegionBase >( time_n + dt, - mesh, - fields::flow::temperature::key(), - [&] ( FieldSpecificationBase const &, - string const &, - SortedArrayView< localIndex const > const & targetSet, - ElementSubRegionBase & subRegion, - string const & ) - { - arrayView1d< integer const > const ghostRank = - subRegion.getReference< array1d< integer > >( ObjectManagerBase::viewKeyStruct::ghostRankString() ); - arrayView1d< globalIndex const > const dofNumber = - subRegion.getReference< array1d< globalIndex > >( dofKey ); - arrayView1d< real64 const > const bcTemp = - subRegion.getReference< array1d< real64 > >( fields::flow::bcTemperature::key() ); - arrayView1d< real64 const > const temp = - subRegion.getReference< array1d< real64 > >( fields::flow::temperature::key() ); - - integer const numComp = m_numComponents; - forAll< parallelDevicePolicy<> >( targetSet.size(), [=] GEOS_HOST_DEVICE ( localIndex const a ) - { - localIndex const ei = targetSet[a]; - if( ghostRank[ei] >= 0 ) - { - return; - } - - globalIndex const dofIndex = dofNumber[ei]; - localIndex const localRow = dofIndex - rankOffset; - real64 rhsValue; - - // 4.2. Apply temperature value to the matrix/rhs - FieldSpecificationEqual::SpecifyFieldValue( dofIndex + numComp + 1, - rankOffset, - localMatrix, - rhsValue, - bcTemp[ei], - temp[ei] ); - localRhs[localRow + numComp + 1] = rhsValue; - } ); - } ); - } - } ); -} - - void ImmiscibleMultiphaseFlow::resetStateToBeginningOfStep( DomainPartition & domain ) { @@ -1048,11 +782,6 @@ void ImmiscibleMultiphaseFlow::implicitStepComplete( real64 const & time, isothermalImmiscibleMultiphaseFlowKernels::StatisticsKernel:: saveDeltaPressure< parallelDevicePolicy<> >( subRegion.size(), pres, initPres, deltaPres ); - // Step 2: save the converged fluid state - string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); - MultiFluidBase const & fluidMaterial = getConstitutiveModel< MultiFluidBase >( subRegion, fluidName ); - fluidMaterial.saveConvergedState(); - // Step 3: save the converged solid state string const & solidName = subRegion.getReference< string >( viewKeyStruct::solidNamesString() ); CoupledSolidBase const & porousMaterial = getConstitutiveModel< CoupledSolidBase >( subRegion, solidName ); @@ -1097,24 +826,12 @@ void ImmiscibleMultiphaseFlow::saveConvergedState( ElementSubRegionBase & subReg { FlowSolverBase::saveConvergedState( subRegion ); - arrayView2d< real64 const, compflow::USD_COMP > const & compDens = - subRegion.template getField< fields::flow::globalCompDensity >(); - arrayView2d< real64, compflow::USD_COMP > const & compDens_n = - subRegion.template getField< fields::flow::globalCompDensity_n >(); - compDens_n.setValues< parallelDevicePolicy<> >( compDens ); - - arrayView2d< real64 const, compflow::USD_COMP > const & compAmount = - subRegion.template getField< fields::flow::compAmount >(); - arrayView2d< real64, compflow::USD_COMP > const & compAmount_n = - subRegion.template getField< fields::flow::compAmount_n >(); - compAmount_n.setValues< parallelDevicePolicy<> >( compAmount ); + arrayView2d< real64 const, compflow::USD_PHASE > const phaseVolFrac = + subRegion.getField< fields::flow::phaseVolumeFraction >(); + arrayView2d< real64, compflow::USD_PHASE > const phaseVolFrac_n = + subRegion.getField< fields::flow::phaseVolumeFraction_n >(); + phaseVolFrac_n.setValues< parallelDevicePolicy<> >( phaseVolFrac ); - if( m_isFixedStressPoromechanicsUpdate ) - { - arrayView2d< real64, compflow::USD_COMP > const & compDens_k = - subRegion.template getField< fields::flow::globalCompDensity_k >(); - compDens_k.setValues< parallelDevicePolicy<> >( compDens ); - } } void ImmiscibleMultiphaseFlow::updateState( DomainPartition & domain ) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp index ec5c2605c20..1480c0fc0d9 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp @@ -73,14 +73,7 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase */ string getCatalogName() const override { return catalogName(); } - virtual void registerDataOnMesh( Group & meshBodies ) override; - - /** - * @defgroup Solver Interface Functions - * - * These functions provide the primary interface that is required for derived classes - */ - /**@{*/ + virtual void registerDataOnMesh( Group & meshBodies ) override final; virtual void implicitStepSetup( real64 const & time_n, @@ -134,16 +127,14 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase * @brief Recompute phase mobility from constitutive and primary variables * @param dataGroup the group storing the required field */ - virtual void updatePhaseMobility( ObjectManagerBase & dataGroup ) const = 0; + void updatePhaseMobility( ObjectManagerBase & dataGroup ) const; real64 updateFluidState( ElementSubRegionBase & subRegion ) const; virtual void saveConvergedState( ElementSubRegionBase & subRegion ) const override final; - virtual void updateState( DomainPartition & domain ) override final; - /** * @brief Getter for the number of fluid phases * @return the number of phases diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp new file mode 100644 index 00000000000..2c2db7636d8 --- /dev/null +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp @@ -0,0 +1,93 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 Total, S.A + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2018-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/** + * @file CompositionalMultiphaseBaseFields.hpp + */ + +#ifndef GEOS_PHYSICSSOLVERS_FLUIDFLOW_COMPOSITIONALMULTIPHASEBASEFIELDS_HPP_ +#define GEOS_PHYSICSSOLVERS_FLUIDFLOW_COMPOSITIONALMULTIPHASEBASEFIELDS_HPP_ + +#include "common/DataLayouts.hpp" +#include "mesh/MeshFields.hpp" + +namespace geos +{ +/** + * A scope for field traits. + */ +namespace fields +{ + +namespace immiscibleMultiphaseFlow +{ + +using array2dLayoutPhase = array2d< real64, immiscibleFlow::LAYOUT_PHASE >; +using array3dLayoutPhase_dS = array3d< real64, immiscibleFlow::LAYOUT_PHASE_DS >; + +DECLARE_FIELD( phaseVolumeFraction, + "phaseVolumeFraction", + array2dLayoutPhase, + 0, + LEVEL_0, + WRITE_AND_READ, + "Phase volume fraction" ); + +DECLARE_FIELD( phaseVolumeFraction_n, + "phaseVolumeFraction_n", + array2dLayoutPhase, + 0, + NOPLOT, + WRITE_AND_READ, + "Phase volume fraction at the previous converged time step" ); + +DECLARE_FIELD( phaseMobility, + "phaseMobility", + array2dLayoutPhase, + 0, + LEVEL_0, + WRITE_AND_READ, + "Phase mobility" ); + +DECLARE_FIELD( dPhaseMobility, + "dPhaseMobility", + array3dLayoutPhase_dS, + 0, + NOPLOT, + NO_WRITE, + "Derivative of phase volume fraction with respect to pressure, temperature, global component density" ); + +DECLARE_FIELD( phaseOutflux, + "phaseOutflux", + array2dLayoutPhase, + 0, + NOPLOT, + NO_WRITE, + "Phase outflux" ); + +DECLARE_FIELD( phaseCFLNumber, + "phaseCFLNumber", + array1d< real64 >, + 0, + LEVEL_0, + NO_WRITE, + "Phase CFL number" ); +} + +} + +} + +#endif // GEOS_PHYSICSSOLVERS_FLUIDFLOW_COMPOSITIONALMULTIPHASEBASEFIELDS_HPP_ From c90724affc8f514aaa8ca14e79f7a930068b572c Mon Sep 17 00:00:00 2001 From: Matteo Cusini Date: Mon, 29 Jul 2024 16:04:35 -0700 Subject: [PATCH 004/104] removed all compositional references. --- .../fluidFlow/ImmiscibleMultiphaseFlow.cpp | 111 ++++++++++-------- .../fluidFlow/ImmiscibleMultiphaseFlow.hpp | 2 +- .../ImmiscibleMultiphaseFlowFields.hpp | 16 +++ 3 files changed, 80 insertions(+), 49 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index 0c7932f7ba2..dcd8af9c24c 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -123,14 +123,14 @@ void ImmiscibleMultiphaseFlow::registerDataOnMesh( Group & meshBodies ) reference().resizeDimension< 1 >( m_numPhases ); subRegion.registerField< dPhaseMobility >( getName() ). - reference().resizeDimension< 1, 2 >( m_numPhases, m_numPhases ); // dP, dT, dC + reference().resizeDimension< 1, 2 >( m_numPhases, m_numPhases ); // dP, dS } ); - FaceManager & faceManager = mesh.getFaceManager(); - { - faceManager.registerField< totalMassFlux >( getName() ); - } + // FaceManager & faceManager = mesh.getFaceManager(); + // { + // faceManager.registerField< totalMassFlux >( getName() ); + // } } ); } @@ -203,30 +203,31 @@ void ImmiscibleMultiphaseFlow::updateFluidModel( ObjectManagerBase & dataGroup ) { GEOS_MARK_FUNCTION; - arrayView1d< real64 const > const pres = dataGroup.getField< fields::flow::pressure >(); - arrayView1d< real64 const > const temp = dataGroup.getField< fields::flow::temperature >(); + // arrayView1d< real64 const > const pres = dataGroup.getField< fields::flow::pressure >(); + // arrayView1d< real64 const > const temp = dataGroup.getField< fields::flow::temperature >(); + GEOS_UNUSED_VAR(dataGroup); } void ImmiscibleMultiphaseFlow::updateRelPermModel( ObjectManagerBase & dataGroup ) const { GEOS_MARK_FUNCTION; - arrayView2d< real64 const, compflow::USD_PHASE > const phaseVolFrac = - dataGroup.getField< fields::flow::phaseVolumeFraction >(); + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac = + dataGroup.getField< fields::flow::immiscibleFlow::phaseVolumeFraction >(); string const & relPermName = dataGroup.getReference< string >( viewKeyStruct::relPermNamesString() ); RelativePermeabilityBase & relPerm = getConstitutiveModel< RelativePermeabilityBase >( dataGroup, relPermName ); - // constitutive::constitutiveUpdatePassThru( relPerm, [&] ( auto & castedRelPerm ) - // { - // typename TYPEOFREF( castedRelPerm ) ::KernelWrapper relPermWrapper = castedRelPerm.createKernelWrapper(); + constitutive::constitutiveUpdatePassThru( relPerm, [&] ( auto & castedRelPerm ) + { + typename TYPEOFREF( castedRelPerm ) ::KernelWrapper relPermWrapper = castedRelPerm.createKernelWrapper(); - // isothermalImmiscibleMultiphaseFlowKernels:: - // RelativePermeabilityUpdateKernel:: - // launch< parallelDevicePolicy<> >( dataGroup.size(), - // relPermWrapper, - // phaseVolFrac ); - // } ); + // isothermalImmiscibleMultiphaseFlowKernels:: + // RelativePermeabilityUpdateKernel:: + // launch< parallelDevicePolicy<> >( dataGroup.size(), + // relPermWrapper, + // phaseVolFrac ); + } ); } void ImmiscibleMultiphaseFlow::updateCapPressureModel( ObjectManagerBase & dataGroup ) const @@ -235,8 +236,8 @@ void ImmiscibleMultiphaseFlow::updateCapPressureModel( ObjectManagerBase & dataG if( m_hasCapPressure ) { - arrayView2d< real64 const, compflow::USD_PHASE > const phaseVolFrac = - dataGroup.getField< fields::flow::phaseVolumeFraction >(); + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac = + dataGroup.getField< fields::flow::immiscibleFlow::phaseVolumeFraction >(); string const & cappresName = dataGroup.getReference< string >( viewKeyStruct::capPressureNamesString() ); CapillaryPressureBase & capPressure = getConstitutiveModel< CapillaryPressureBase >( dataGroup, cappresName ); @@ -282,9 +283,6 @@ void ImmiscibleMultiphaseFlow::initializeFluidState( MeshLevel & mesh, } ); - // with initial component densities defined - check if they need to be corrected to avoid zero diags etc - chopNegativeDensities( domain ); - // for some reason CUDA does not want the host_device lambda to be defined inside the generic lambda // I need the exact type of the subRegion for updateSolidflowProperties to work well. mesh.getElemManager().forElementSubRegions< CellElementSubRegion, @@ -330,8 +328,8 @@ void ImmiscibleMultiphaseFlow::initializeFluidState( MeshLevel & mesh, // - This step depends on phaseVolFraction // initialized phase volume fraction - arrayView2d< real64 const, compflow::USD_PHASE > const phaseVolFrac = - subRegion.template getField< fields::flow::phaseVolumeFraction >(); + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac = + subRegion.template getField< fields::flow::immiscibleFlow::phaseVolumeFraction >(); string const & relpermName = subRegion.template getReference< string >( viewKeyStruct::relPermNamesString() ); RelativePermeabilityBase & relPermMaterial = @@ -460,13 +458,20 @@ ImmiscibleMultiphaseFlow::implicitStepSetup( real64 const & GEOS_UNUSED_PARAM( t updateFluidState( subRegion ); // after the update, save the new saturation - arrayView2d< real64 const, compflow::USD_PHASE > const phaseVolFrac = - subRegion.template getField< fields::flow::phaseVolumeFraction >(); + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac = + subRegion.template getField< fields::flow::immiscibleFlow::phaseVolumeFraction >(); - arrayView2d< real64, compflow::USD_PHASE > const phaseVolFrac_n = - subRegion.template getField< fields::flow::phaseVolumeFraction_n >(); + arrayView2d< real64, immiscibleFlow::USD_PHASE > const phaseVolFrac_n = + subRegion.template getField< fields::flow::immiscibleFlow::phaseVolumeFraction_n >(); phaseVolFrac_n.setValues< parallelDevicePolicy<> >( phaseVolFrac ); + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const & phaseMass = + subRegion.template getField< fields::flow::immiscibleFlow::phaseMass >(); + + arrayView2d< real64, immiscibleFlow::USD_PHASE > const & phaseMass_n = + subRegion.template getField< fields::flow::immiscibleFlow::phaseMass_n >(); + phaseMass_n.setValues< parallelDevicePolicy<> >( phaseMass ); + } ); } ); } @@ -481,16 +486,16 @@ void ImmiscibleMultiphaseFlow::assembleSystem( real64 const GEOS_UNUSED_PARAM( t GEOS_MARK_FUNCTION; assembleAccumulationTerm( domain, - dofManager, - localMatrix, - localRhs ); + dofManager, + localMatrix, + localRhs ); assembleFluxTerms( dt, - domain, - dofManager, - localMatrix, - localRhs ); + domain, + dofManager, + localMatrix, + localRhs ); } void ImmiscibleMultiphaseFlow::assembleAccumulationTerm( DomainPartition & domain, @@ -509,7 +514,6 @@ void ImmiscibleMultiphaseFlow::assembleAccumulationTerm( DomainPartition & domai ElementSubRegionBase const & subRegion ) { string const dofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); - string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); string const & solidName = subRegion.getReference< string >( viewKeyStruct::solidNamesString() ); } ); } ); @@ -735,11 +739,20 @@ void ImmiscibleMultiphaseFlow::resetStateToBeginningOfStep( DomainPartition & do subRegion.template getField< fields::flow::pressure_n >(); pres.setValues< parallelDevicePolicy<> >( pres_n ); - arrayView2d< real64, compflow::USD_COMP > const & compDens = - subRegion.template getField< fields::flow::globalCompDensity >(); - arrayView2d< real64 const, compflow::USD_COMP > const & compDens_n = - subRegion.template getField< fields::flow::globalCompDensity_n >(); - compDens.setValues< parallelDevicePolicy<> >( compDens_n ); + // after the update, save the new saturation + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac_n = + subRegion.template getField< fields::flow::immiscibleFlow::phaseVolumeFraction_n >(); + + arrayView2d< real64, immiscibleFlow::USD_PHASE > const phaseVolFrac = + subRegion.template getField< fields::flow::immiscibleFlow::phaseVolumeFraction >(); + phaseVolFrac.setValues< parallelDevicePolicy<> >( phaseVolFrac ); + + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const & phaseMass_n = + subRegion.template getField< fields::flow::immiscibleFlow::phaseMass_n >(); + + arrayView2d< real64, immiscibleFlow::USD_PHASE > const & phaseMass = + subRegion.template getField< fields::flow::immiscibleFlow::phaseMass >(); + phaseMass.setValues< parallelDevicePolicy<> >( phaseMass_n ); if( m_isThermal ) { @@ -795,8 +808,8 @@ void ImmiscibleMultiphaseFlow::implicitStepComplete( real64 const & time, } // Step 4: save converged state for the relperm model to handle hysteresis - arrayView2d< real64 const, compflow::USD_PHASE > const phaseVolFrac = - subRegion.getField< fields::flow::phaseVolumeFraction >(); + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac = + subRegion.getField< fields::flow::immiscibleFlow::phaseVolumeFraction >(); string const & relPermName = subRegion.getReference< string >( viewKeyStruct::relPermNamesString() ); RelativePermeabilityBase const & relPermMaterial = getConstitutiveModel< RelativePermeabilityBase >( subRegion, relPermName ); @@ -826,12 +839,14 @@ void ImmiscibleMultiphaseFlow::saveConvergedState( ElementSubRegionBase & subReg { FlowSolverBase::saveConvergedState( subRegion ); - arrayView2d< real64 const, compflow::USD_PHASE > const phaseVolFrac = - subRegion.getField< fields::flow::phaseVolumeFraction >(); - arrayView2d< real64, compflow::USD_PHASE > const phaseVolFrac_n = - subRegion.getField< fields::flow::phaseVolumeFraction_n >(); + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac = + subRegion.getField< fields::flow::immiscibleFlow::phaseVolumeFraction >(); + arrayView2d< real64, immiscibleFlow::USD_PHASE > const phaseVolFrac_n = + subRegion.getField< fields::flow::immiscibleFlow::phaseVolumeFraction_n >(); phaseVolFrac_n.setValues< parallelDevicePolicy<> >( phaseVolFrac ); + + } void ImmiscibleMultiphaseFlow::updateState( DomainPartition & domain ) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp index 1480c0fc0d9..c49cd9b8ba8 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp @@ -105,7 +105,7 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase DomainPartition & domain ) override; /** - * @brief Update all relevant fluid models using current values of pressure and composition + * @brief Update all relevant fluid models using current values of pressure and phase volume fraction * @param dataGroup the group storing the required fields */ void updateFluidModel( ObjectManagerBase & dataGroup ) const; diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp index 2c2db7636d8..abf3588f0eb 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp @@ -53,6 +53,22 @@ DECLARE_FIELD( phaseVolumeFraction_n, WRITE_AND_READ, "Phase volume fraction at the previous converged time step" ); +DECLARE_FIELD( phaseMass, + "phaseMass", + array2dLayoutPhase, + 0, + LEVEL_0, + WRITE_AND_READ, + "Phase mass" ); + +DECLARE_FIELD( phaseMass_n, + "phaseMass_n", + array2dLayoutPhase, + 0, + NOPLOT, + WRITE_AND_READ, + "Phase mass at the previous converged time step" ); + DECLARE_FIELD( phaseMobility, "phaseMobility", array2dLayoutPhase, From 446e4010fdc57f2a7aa245fcbd70a807f0771830 Mon Sep 17 00:00:00 2001 From: Matteo Cusini Date: Tue, 30 Jul 2024 11:36:46 -0700 Subject: [PATCH 005/104] Compiles and links. --- .../physicsSolvers/fluidFlow/CMakeLists.txt | 1 + .../fluidFlow/ImmiscibleMultiphaseFlow.cpp | 421 +++++------------- .../fluidFlow/ImmiscibleMultiphaseFlow.hpp | 97 ++-- .../ImmiscibleMultiphaseFlowFields.hpp | 8 +- ...rmalCompositionalMultiphaseBaseKernels.hpp | 1 + 5 files changed, 169 insertions(+), 359 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt b/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt index 65e1180ffe2..e2e7320694d 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt +++ b/src/coreComponents/physicsSolvers/fluidFlow/CMakeLists.txt @@ -8,6 +8,7 @@ set( physicsSolvers_headers fluidFlow/ThermalCompositionalMultiphaseBaseKernels.hpp fluidFlow/CompositionalMultiphaseFVM.hpp fluidFlow/ImmiscibleMultiphaseFlow.hpp + fluidFlow/ImmiscibleMultiphaseFlowFields.hpp fluidFlow/IsothermalCompositionalMultiphaseFVMKernels.hpp fluidFlow/IsothermalCompositionalMultiphaseFVMKernelUtilities.hpp fluidFlow/ThermalCompositionalMultiphaseFVMKernels.hpp diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index dcd8af9c24c..9a93fec7e66 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -19,11 +19,19 @@ #include "ImmiscibleMultiphaseFlow.hpp" +#include "FlowSolverBaseFields.hpp" +#include "physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp" +#include "physicsSolvers/fluidFlow/IsothermalCompositionalMultiphaseBaseKernels.hpp" +#include "physicsSolvers/fluidFlow/IsothermalCompositionalMultiphaseFVMKernels.hpp" -#include "ImmiscibleMultiphaseFlowFields.hpp" #include "constitutive/ConstitutiveManager.hpp" #include "constitutive/capillaryPressure/CapillaryPressureFields.hpp" #include "constitutive/capillaryPressure/capillaryPressureSelector.hpp" +#include "constitutive/relativePermeability/RelativePermeabilitySelector.hpp" + +#include "fieldSpecification/SourceFluxBoundaryCondition.hpp" + + #include "constitutive/ConstitutivePassThru.hpp" #if defined( __INTEL_COMPILER ) @@ -35,10 +43,10 @@ namespace geos using namespace dataRepository; using namespace constitutive; -using namespace fields:flow:immiscibleFlow; +using namespace fields::immiscibleMultiphaseFlow; ImmiscibleMultiphaseFlow::ImmiscibleMultiphaseFlow( const string & name, - Group * const parent ) + Group * const parent ) : FlowSolverBase( name, parent ), m_numPhases( 2 ), @@ -56,12 +64,10 @@ void ImmiscibleMultiphaseFlow::postInputInitialization() void ImmiscibleMultiphaseFlow::registerDataOnMesh( Group & meshBodies ) { - using namespace fields::flow; - FlowSolverBase::registerDataOnMesh( meshBodies ); - DomainPartition const & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" ); - ConstitutiveManager const & cm = domain.getConstitutiveManager(); + // DomainPartition const & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" ); + // ConstitutiveManager const & cm = domain.getConstitutiveManager(); // 0. Find a "reference" fluid model name (at this point, models are already attached to subregions) forDiscretizationOnMeshTargets( meshBodies, [&]( string const &, @@ -112,14 +118,12 @@ void ImmiscibleMultiphaseFlow::registerDataOnMesh( Group & meshBodies ) // The resizing of the arrays needs to happen here, before the call to initializePreSubGroups, // to make sure that the dimensions are properly set before the timeHistoryOutput starts its initialization. subRegion.registerField< phaseVolumeFraction >( getName() ). - setDimLabels( 1, fluid.phaseNames() ). reference().resizeDimension< 1 >( m_numPhases ); - + subRegion.registerField< phaseVolumeFraction_n >( getName() ). - reference().resizeDimension< 1 >( m_numPhases ); + reference().resizeDimension< 1 >( m_numPhases ); subRegion.registerField< phaseMobility >( getName() ). - setDimLabels( 1, fluid.phaseNames() ). reference().resizeDimension< 1 >( m_numPhases ); subRegion.registerField< dPhaseMobility >( getName() ). @@ -156,10 +160,10 @@ void ImmiscibleMultiphaseFlow::initializePreSubGroups() FlowSolverBase::initializePreSubGroups(); DomainPartition & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" ); - ConstitutiveManager const & cm = domain.getConstitutiveManager(); + // ConstitutiveManager const & cm = domain.getConstitutiveManager(); - // 1. Validate various models against each other (must have same phases and components) - validateConstitutiveModels( domain ); + // // 1. Validate various models against each other (must have same phases and components) + // validateConstitutiveModels( domain ); // 2. Set the value of temperature forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, @@ -177,43 +181,23 @@ void ImmiscibleMultiphaseFlow::initializePreSubGroups() } ); } -void ImmiscibleMultiphaseFlow::validateConstitutiveModels( DomainPartition const & domain ) const -{ - GEOS_MARK_FUNCTION; - - ConstitutiveManager const & cm = domain.getConstitutiveManager(); - - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel const & mesh, - arrayView1d< string const > const & regionNames ) - - { - mesh.getElemManager().forElementSubRegions( regionNames, - [&]( localIndex const, - ElementSubRegionBase const & subRegion ) - { - string const & relpermName = subRegion.getReference< string >( viewKeyStruct::relPermNamesString() ); - RelativePermeabilityBase const & relPerm = getConstitutiveModel< RelativePermeabilityBase >( subRegion, relpermName ); - compareMultiphaseModels( relPerm, referenceFluid ); - } ); - } ); -} - void ImmiscibleMultiphaseFlow::updateFluidModel( ObjectManagerBase & dataGroup ) const { GEOS_MARK_FUNCTION; // arrayView1d< real64 const > const pres = dataGroup.getField< fields::flow::pressure >(); // arrayView1d< real64 const > const temp = dataGroup.getField< fields::flow::temperature >(); - GEOS_UNUSED_VAR(dataGroup); + GEOS_UNUSED_VAR( dataGroup ); } void ImmiscibleMultiphaseFlow::updateRelPermModel( ObjectManagerBase & dataGroup ) const { GEOS_MARK_FUNCTION; + GEOS_UNUSED_VAR( dataGroup ); + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac = - dataGroup.getField< fields::flow::immiscibleFlow::phaseVolumeFraction >(); + dataGroup.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); string const & relPermName = dataGroup.getReference< string >( viewKeyStruct::relPermNamesString() ); RelativePermeabilityBase & relPerm = getConstitutiveModel< RelativePermeabilityBase >( dataGroup, relPermName ); @@ -222,11 +206,11 @@ void ImmiscibleMultiphaseFlow::updateRelPermModel( ObjectManagerBase & dataGroup { typename TYPEOFREF( castedRelPerm ) ::KernelWrapper relPermWrapper = castedRelPerm.createKernelWrapper(); - // isothermalImmiscibleMultiphaseFlowKernels:: - // RelativePermeabilityUpdateKernel:: - // launch< parallelDevicePolicy<> >( dataGroup.size(), - // relPermWrapper, - // phaseVolFrac ); + isothermalCompositionalMultiphaseBaseKernels:: + RelativePermeabilityUpdateKernel:: + launch< parallelDevicePolicy<> >( dataGroup.size(), + relPermWrapper, + phaseVolFrac ); } ); } @@ -237,7 +221,7 @@ void ImmiscibleMultiphaseFlow::updateCapPressureModel( ObjectManagerBase & dataG if( m_hasCapPressure ) { arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac = - dataGroup.getField< fields::flow::immiscibleFlow::phaseVolumeFraction >(); + dataGroup.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); string const & cappresName = dataGroup.getReference< string >( viewKeyStruct::capPressureNamesString() ); CapillaryPressureBase & capPressure = getConstitutiveModel< CapillaryPressureBase >( dataGroup, cappresName ); @@ -246,7 +230,7 @@ void ImmiscibleMultiphaseFlow::updateCapPressureModel( ObjectManagerBase & dataG { typename TYPEOFREF( castedCapPres ) ::KernelWrapper capPresWrapper = castedCapPres.createKernelWrapper(); - isothermalImmiscibleMultiphaseFlowKernels:: + isothermalCompositionalMultiphaseBaseKernels:: CapillaryPressureUpdateKernel:: launch< parallelDevicePolicy<> >( dataGroup.size(), capPresWrapper, @@ -255,7 +239,7 @@ void ImmiscibleMultiphaseFlow::updateCapPressureModel( ObjectManagerBase & dataG } } -real64 ImmiscibleMultiphaseFlow::updateFluidState( ElementSubRegionBase & subRegion ) const +void ImmiscibleMultiphaseFlow::updateFluidState( ElementSubRegionBase & subRegion ) const { GEOS_MARK_FUNCTION; @@ -263,13 +247,34 @@ real64 ImmiscibleMultiphaseFlow::updateFluidState( ElementSubRegionBase & subReg updateRelPermModel( subRegion ); updatePhaseMobility( subRegion ); updateCapPressureModel( subRegion ); +} - return maxDeltaPhaseVolFrac; +void ImmiscibleMultiphaseFlow::updatePhaseMobility( ObjectManagerBase & dataGroup ) const +{ + GEOS_MARK_FUNCTION; + + GEOS_UNUSED_VAR( dataGroup ); + + /// Matteo: looks like you will to create a new update function for the mobility. I have left the code as an example. + // // note that the phase mobility computed here also includes phase density + // string const & fluidName = dataGroup.getReference< string >( viewKeyStruct::fluidNamesString() ); + // MultiFluidBase const & fluid = getConstitutiveModel< MultiFluidBase >( dataGroup, fluidName ); + + // string const & relpermName = dataGroup.getReference< string >( viewKeyStruct::relPermNamesString() ); + // RelativePermeabilityBase const & relperm = getConstitutiveModel< RelativePermeabilityBase >( dataGroup, relpermName ); + + // isothermalCompositionalMultiphaseFVMKernels:: + // PhaseMobilityKernelFactory:: + // createAndLaunch< parallelDevicePolicy<> >( m_numComponents, + // m_numPhases, + // dataGroup, + // fluid, + // relperm ); } void ImmiscibleMultiphaseFlow::initializeFluidState( MeshLevel & mesh, - DomainPartition & domain, - arrayView1d< string const > const & regionNames ) + DomainPartition & GEOS_UNUSED_PARAM( domain ), + arrayView1d< string const > const & regionNames ) { GEOS_MARK_FUNCTION; @@ -305,8 +310,6 @@ void ImmiscibleMultiphaseFlow::initializeFluidState( MeshLevel & mesh, porousSolid.scaleReferencePorosity( netToGross ); saveConvergedState( subRegion ); // necessary for a meaningful porosity update in sequential schemes updatePorosityAndPermeability( subRegion ); - updateCompAmount( subRegion ); - updatePhaseVolumeFraction( subRegion ); // Now, we initialize and update each constitutive model one by one @@ -329,7 +332,7 @@ void ImmiscibleMultiphaseFlow::initializeFluidState( MeshLevel & mesh, // initialized phase volume fraction arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac = - subRegion.template getField< fields::flow::immiscibleFlow::phaseVolumeFraction >(); + subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); string const & relpermName = subRegion.template getReference< string >( viewKeyStruct::relPermNamesString() ); RelativePermeabilityBase & relPermMaterial = @@ -349,8 +352,7 @@ void ImmiscibleMultiphaseFlow::initializeFluidState( MeshLevel & mesh, arrayView2d< real64 const > const porosity = porousMaterial.getPorosity(); string const & permName = subRegion.template getReference< string >( viewKeyStruct::permeabilityNamesString() ); - PermeabilityBase const & permeabilityMaterial = - getConstitutiveModel< PermeabilityBase >( subRegion, permName ); + PermeabilityBase const & permeabilityMaterial = getConstitutiveModel< PermeabilityBase >( subRegion, permName ); // initialized permeability arrayView3d< real64 const > const permeability = permeabilityMaterial.permeability(); @@ -397,7 +399,7 @@ void ImmiscibleMultiphaseFlow::initializePostInitialConditionsPreSubGroups() { FieldIdentifiers fieldsToBeSync; fieldsToBeSync.addElementFields( { fields::flow::pressure::key(), - fields::flow::globalCompDensity::key() }, + fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key() }, regionNames ); CommunicationTools::getInstance().synchronizeFields( fieldsToBeSync, mesh, domain.getNeighbors(), false ); @@ -438,8 +440,8 @@ void ImmiscibleMultiphaseFlow::initializePostInitialConditionsPreSubGroups() void ImmiscibleMultiphaseFlow::implicitStepSetup( real64 const & GEOS_UNUSED_PARAM( time_n ), - real64 const & GEOS_UNUSED_PARAM( dt ), - DomainPartition & domain ) + real64 const & GEOS_UNUSED_PARAM( dt ), + DomainPartition & domain ) { forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, MeshLevel & mesh, @@ -459,17 +461,17 @@ ImmiscibleMultiphaseFlow::implicitStepSetup( real64 const & GEOS_UNUSED_PARAM( t // after the update, save the new saturation arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac = - subRegion.template getField< fields::flow::immiscibleFlow::phaseVolumeFraction >(); + subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); arrayView2d< real64, immiscibleFlow::USD_PHASE > const phaseVolFrac_n = - subRegion.template getField< fields::flow::immiscibleFlow::phaseVolumeFraction_n >(); + subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction_n >(); phaseVolFrac_n.setValues< parallelDevicePolicy<> >( phaseVolFrac ); arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const & phaseMass = - subRegion.template getField< fields::flow::immiscibleFlow::phaseMass >(); - + subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseMass >(); + arrayView2d< real64, immiscibleFlow::USD_PHASE > const & phaseMass_n = - subRegion.template getField< fields::flow::immiscibleFlow::phaseMass_n >(); + subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseMass_n >(); phaseMass_n.setValues< parallelDevicePolicy<> >( phaseMass ); } ); @@ -477,11 +479,11 @@ ImmiscibleMultiphaseFlow::implicitStepSetup( real64 const & GEOS_UNUSED_PARAM( t } void ImmiscibleMultiphaseFlow::assembleSystem( real64 const GEOS_UNUSED_PARAM( time_n ), - real64 const dt, - DomainPartition & domain, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) + real64 const dt, + DomainPartition & domain, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) { GEOS_MARK_FUNCTION; @@ -490,7 +492,7 @@ void ImmiscibleMultiphaseFlow::assembleSystem( real64 const GEOS_UNUSED_PARAM( t localMatrix, localRhs ); - + assembleFluxTerms( dt, domain, dofManager, @@ -499,227 +501,61 @@ void ImmiscibleMultiphaseFlow::assembleSystem( real64 const GEOS_UNUSED_PARAM( t } void ImmiscibleMultiphaseFlow::assembleAccumulationTerm( DomainPartition & domain, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) const + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) const { GEOS_MARK_FUNCTION; - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel const & mesh, - arrayView1d< string const > const & regionNames ) - { - mesh.getElemManager().forElementSubRegions( regionNames, - [&]( localIndex const, - ElementSubRegionBase const & subRegion ) - { - string const dofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); - string const & solidName = subRegion.getReference< string >( viewKeyStruct::solidNamesString() ); - } ); - } ); + + GEOS_UNUSED_VAR( domain, dofManager, localMatrix, localRhs ); + + // forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + // MeshLevel const & mesh, + // arrayView1d< string const > const & regionNames ) + // { + // mesh.getElemManager().forElementSubRegions( regionNames, + // [&]( localIndex const, + // ElementSubRegionBase const & subRegion ) + // { + // string const dofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); + // string const & solidName = subRegion.getReference< string >( viewKeyStruct::solidNamesString() ); + // } ); + // } ); } void ImmiscibleMultiphaseFlow::assembleFluxTerms( real64 const dt, - DomainPartition const & domain, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) const -{} + DomainPartition const & domain, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) const +{ + GEOS_UNUSED_VAR( dt, domain, dofManager, localMatrix, localRhs ); +} void ImmiscibleMultiphaseFlow::applyBoundaryConditions( real64 const time_n, - real64 const dt, - DomainPartition & domain, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) + real64 const dt, + DomainPartition & domain, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) { GEOS_MARK_FUNCTION; // apply pressure boundary conditions. applyDirichletBC( time_n, dt, dofManager, domain, localMatrix.toViewConstSizes(), localRhs.toView() ); - - // apply flux boundary conditions - applySourceFluxBC( time_n, dt, dofManager, domain, localMatrix.toViewConstSizes(), localRhs.toView() ); -} - -namespace -{ -char const bcLogMessage[] = - "ImmiscibleMultiphaseFlow {}: at time {}s, " - "the <{}> boundary condition '{}' is applied to the element set '{}' in subRegion '{}'. " - "\nThe scale of this boundary condition is {} and multiplies the value of the provided function (if any). " - "\nThe total number of target elements (including ghost elements) is {}. " - "\nNote that if this number is equal to zero for all subRegions, the boundary condition will not be applied on this element set."; } -void ImmiscibleMultiphaseFlow::applySourceFluxBC( real64 const time, - real64 const dt, - DofManager const & dofManager, - DomainPartition & domain, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) const +void ImmiscibleMultiphaseFlow::applyDirichletBC( real64 const time, + real64 const dt, + DofManager const & dofManager, + DomainPartition & domain, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) const { - GEOS_MARK_FUNCTION; - - FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); - - string const dofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); - - // Step 1: count individual source flux boundary conditions - - std::map< string, localIndex > bcNameToBcId; - localIndex bcCounter = 0; - - fsManager.forSubGroups< SourceFluxBoundaryCondition >( [&] ( SourceFluxBoundaryCondition const & bc ) - { - // collect all the bc names to idx - bcNameToBcId[bc.getName()] = bcCounter; - bcCounter++; - } ); - - if( bcCounter == 0 ) - { - return; - } - - // Step 2: count the set size for each source flux (each source flux may have multiple target sets) - - array1d< globalIndex > bcAllSetsSize( bcNameToBcId.size() ); - - computeSourceFluxSizeScalingFactor( time, - dt, - domain, - bcNameToBcId, - bcAllSetsSize.toView() ); - - // Step 3: we are ready to impose the boundary condition, normalized by the set size - - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel & mesh, - arrayView1d< string const > const & ) - { - fsManager.apply< ElementSubRegionBase, - SourceFluxBoundaryCondition >( time + dt, - mesh, - SourceFluxBoundaryCondition::catalogName(), - [&]( SourceFluxBoundaryCondition const & fs, - string const & setName, - SortedArrayView< localIndex const > const & targetSet, - ElementSubRegionBase & subRegion, - string const & ) - { - if( fs.getLogLevel() >= 1 && m_nonlinearSolverParameters.m_numNewtonIterations == 0 ) - { - globalIndex const numTargetElems = MpiWrapper::sum< globalIndex >( targetSet.size() ); - GEOS_LOG_RANK_0( GEOS_FMT( bcLogMessage, - getName(), time+dt, fs.getCatalogName(), fs.getName(), - setName, subRegion.getName(), fs.getScale(), numTargetElems ) ); - } - - if( targetSet.size() == 0 ) - { - return; - } - if( !subRegion.hasWrapper( dofKey ) ) - { - if( fs.getLogLevel() >= 1 ) - { - GEOS_LOG_RANK( GEOS_FMT( "{}: trying to apply SourceFlux, but its targetSet named '{}' intersects with non-simulated region named '{}'.", - getDataContext(), setName, subRegion.getName() ) ); - } - return; - } - - arrayView1d< globalIndex const > const dofNumber = subRegion.getReference< array1d< globalIndex > >( dofKey ); - arrayView1d< integer const > const ghostRank = subRegion.ghostRank(); - - // Step 3.1: get the values of the source boundary condition that need to be added to the rhs - // We don't use FieldSpecificationBase::applyConditionToSystem here because we want to account for the row permutation used in the - // compositional solvers - - array1d< globalIndex > dofArray( targetSet.size() ); - array1d< real64 > rhsContributionArray( targetSet.size() ); - arrayView1d< real64 > rhsContributionArrayView = rhsContributionArray.toView(); - localIndex const rankOffset = dofManager.rankOffset(); - - RAJA::ReduceSum< parallelDeviceReduce, real64 > massProd( 0.0 ); - - // note that the dofArray will not be used after this step (simpler to use dofNumber instead) - fs.computeRhsContribution< FieldSpecificationAdd, - parallelDevicePolicy<> >( targetSet.toViewConst(), - time + dt, - dt, - subRegion, - dofNumber, - rankOffset, - localMatrix, - dofArray.toView(), - rhsContributionArrayView, - [] GEOS_HOST_DEVICE ( localIndex const ) - { - return 0.0; - } ); - - // Step 3.2: we are ready to add the right-hand side contributions, taking into account our equation layout - - // get the normalizer - real64 const sizeScalingFactor = bcAllSetsSize[bcNameToBcId.at( fs.getName())]; - - integer const fluidComponentId = fs.getComponent(); - integer const numFluidComponents = m_numComponents; - integer const useTotalMassEquation = m_useTotalMassEquation; - forAll< parallelDevicePolicy<> >( targetSet.size(), [sizeScalingFactor, - targetSet, - rankOffset, - ghostRank, - fluidComponentId, - numFluidComponents, - useTotalMassEquation, - dofNumber, - rhsContributionArrayView, - localRhs, - massProd] GEOS_HOST_DEVICE ( localIndex const a ) - { - // we need to filter out ghosts here, because targetSet may contain them - localIndex const ei = targetSet[a]; - if( ghostRank[ei] >= 0 ) - { - return; - } - - real64 const rhsValue = rhsContributionArrayView[a] / sizeScalingFactor; // scale the contribution by the sizeScalingFactor here! - massProd += rhsValue; - if( useTotalMassEquation > 0 ) - { - // for all "fluid components", we add the value to the total mass balance equation - globalIndex const totalMassBalanceRow = dofNumber[ei] - rankOffset; - localRhs[totalMassBalanceRow] += rhsValue; - if( fluidComponentId < numFluidComponents - 1 ) - { - globalIndex const compMassBalanceRow = totalMassBalanceRow + fluidComponentId + 1; // component mass bal equations are shifted - localRhs[compMassBalanceRow] += rhsValue; - } - } - else - { - globalIndex const compMassBalanceRow = dofNumber[ei] - rankOffset + fluidComponentId; - localRhs[compMassBalanceRow] += rhsValue; - } - } ); - - SourceFluxStatsAggregator::forAllFluxStatWrappers( subRegion, fs.getName(), - [&]( SourceFluxStatsAggregator::WrappedStats & wrapper ) - { - // set the new sub-region statistics for this timestep - array1d< real64 > massProdArr{ m_numComponents }; - massProdArr[fluidComponentId] = massProd.get(); - wrapper.gatherTimeStepStats( time, dt, massProdArr.toViewConst(), targetSet.size() ); - } ); - } ); - } ); + GEOS_UNUSED_VAR( time, dt, dofManager, domain, localMatrix, localRhs ); } - void ImmiscibleMultiphaseFlow::resetStateToBeginningOfStep( DomainPartition & domain ) { GEOS_MARK_FUNCTION; @@ -741,17 +577,17 @@ void ImmiscibleMultiphaseFlow::resetStateToBeginningOfStep( DomainPartition & do // after the update, save the new saturation arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac_n = - subRegion.template getField< fields::flow::immiscibleFlow::phaseVolumeFraction_n >(); + subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction_n >(); arrayView2d< real64, immiscibleFlow::USD_PHASE > const phaseVolFrac = - subRegion.template getField< fields::flow::immiscibleFlow::phaseVolumeFraction >(); + subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); phaseVolFrac.setValues< parallelDevicePolicy<> >( phaseVolFrac ); arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const & phaseMass_n = - subRegion.template getField< fields::flow::immiscibleFlow::phaseMass_n >(); - + subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseMass_n >(); + arrayView2d< real64, immiscibleFlow::USD_PHASE > const & phaseMass = - subRegion.template getField< fields::flow::immiscibleFlow::phaseMass >(); + subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseMass >(); phaseMass.setValues< parallelDevicePolicy<> >( phaseMass_n ); if( m_isThermal ) @@ -772,8 +608,8 @@ void ImmiscibleMultiphaseFlow::resetStateToBeginningOfStep( DomainPartition & do } void ImmiscibleMultiphaseFlow::implicitStepComplete( real64 const & time, - real64 const & dt, - DomainPartition & domain ) + real64 const & dt, + DomainPartition & domain ) { // Step 1: save the converged aquifer state // note: we have to save the aquifer state **before** updating the pressure, @@ -788,13 +624,6 @@ void ImmiscibleMultiphaseFlow::implicitStepComplete( real64 const & time, [&]( localIndex const, ElementSubRegionBase & subRegion ) { - // update deltaPressure - arrayView1d< real64 const > const pres = subRegion.getField< fields::flow::pressure >(); - arrayView1d< real64 const > const initPres = subRegion.getField< fields::flow::initialPressure >(); - arrayView1d< real64 > const deltaPres = subRegion.getField< fields::flow::deltaPressure >(); - isothermalImmiscibleMultiphaseFlowKernels::StatisticsKernel:: - saveDeltaPressure< parallelDevicePolicy<> >( subRegion.size(), pres, initPres, deltaPres ); - // Step 3: save the converged solid state string const & solidName = subRegion.getReference< string >( viewKeyStruct::solidNamesString() ); CoupledSolidBase const & porousMaterial = getConstitutiveModel< CoupledSolidBase >( subRegion, solidName ); @@ -809,7 +638,7 @@ void ImmiscibleMultiphaseFlow::implicitStepComplete( real64 const & time, // Step 4: save converged state for the relperm model to handle hysteresis arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac = - subRegion.getField< fields::flow::immiscibleFlow::phaseVolumeFraction >(); + subRegion.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); string const & relPermName = subRegion.getReference< string >( viewKeyStruct::relPermNamesString() ); RelativePermeabilityBase const & relPermMaterial = getConstitutiveModel< RelativePermeabilityBase >( subRegion, relPermName ); @@ -840,9 +669,9 @@ void ImmiscibleMultiphaseFlow::saveConvergedState( ElementSubRegionBase & subReg FlowSolverBase::saveConvergedState( subRegion ); arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac = - subRegion.getField< fields::flow::immiscibleFlow::phaseVolumeFraction >(); - arrayView2d< real64, immiscibleFlow::USD_PHASE > const phaseVolFrac_n = - subRegion.getField< fields::flow::immiscibleFlow::phaseVolumeFraction_n >(); + subRegion.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); + arrayView2d< real64, immiscibleFlow::USD_PHASE > const phaseVolFrac_n = + subRegion.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction_n >(); phaseVolFrac_n.setValues< parallelDevicePolicy<> >( phaseVolFrac ); @@ -853,7 +682,6 @@ void ImmiscibleMultiphaseFlow::updateState( DomainPartition & domain ) { GEOS_MARK_FUNCTION; - real64 maxDeltaPhaseVolFrac = 0.0; forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, MeshLevel & mesh, arrayView1d< string const > const & regionNames ) @@ -865,20 +693,9 @@ void ImmiscibleMultiphaseFlow::updateState( DomainPartition & domain ) // update porosity, permeability, and solid internal energy updatePorosityAndPermeability( subRegion ); // update all fluid properties - real64 const deltaPhaseVolFrac = updateFluidState( subRegion ); - maxDeltaPhaseVolFrac = LvArray::math::max( maxDeltaPhaseVolFrac, deltaPhaseVolFrac ); - // for thermal, update solid internal energy - if( m_isThermal ) - { - updateSolidInternalEnergyModel( subRegion ); - updateEnergy( subRegion ); - } + updateFluidState( subRegion ); } ); } ); - - maxDeltaPhaseVolFrac = MpiWrapper::max( maxDeltaPhaseVolFrac ); - - GEOS_LOG_LEVEL_RANK_0( 1, GEOS_FMT( " {}: Max phase volume fraction change = {}", getName(), fmt::format( "{:.{}f}", maxDeltaPhaseVolFrac, 4 ) ) ); } real64 ImmiscibleMultiphaseFlow::setNextDt( const geos::real64 & currentDt, geos::DomainPartition & domain ) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp index c49cd9b8ba8..3c6236afc70 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp @@ -42,7 +42,7 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase * @param parent the parent group of this instantiation of Group */ ImmiscibleMultiphaseFlow( const string & name, - Group * const parent ); + Group * const parent ); /// deleted default constructor ImmiscibleMultiphaseFlow() = delete; @@ -71,7 +71,7 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase /** * @copydoc SolverBase::getCatalogName() */ - string getCatalogName() const override { return catalogName(); } + string getCatalogName() const override { return catalogName(); } virtual void registerDataOnMesh( Group & meshBodies ) override final; @@ -104,32 +104,7 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase real64 const & dt, DomainPartition & domain ) override; - /** - * @brief Update all relevant fluid models using current values of pressure and phase volume fraction - * @param dataGroup the group storing the required fields - */ - void updateFluidModel( ObjectManagerBase & dataGroup ) const; - - /** - * @brief Update all relevant relperm models using current values of phase volume fraction - * @param dataGroup the group storing the required fields - */ - void updateRelPermModel( ObjectManagerBase & dataGroup ) const; - - /** - * @brief Update all relevant capillary pressure models using current values of phase volume fraction - * @param dataGroup the group storing the required fields - */ - void updateCapPressureModel( ObjectManagerBase & dataGroup ) const; - - - /** - * @brief Recompute phase mobility from constitutive and primary variables - * @param dataGroup the group storing the required field - */ - void updatePhaseMobility( ObjectManagerBase & dataGroup ) const; - - real64 updateFluidState( ElementSubRegionBase & subRegion ) const; + void updateFluidState( ElementSubRegionBase & subRegion ) const; virtual void saveConvergedState( ElementSubRegionBase & subRegion ) const override final; @@ -151,9 +126,9 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase * @param localRhs the system right-hand side vector */ void assembleAccumulationTerm( DomainPartition & domain, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) const; + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) const; /** * @brief assembles the flux terms for all cells @@ -169,7 +144,7 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase DomainPartition const & domain, DofManager const & dofManager, CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) const override final; + arrayView1d< real64 > const & localRhs ) const; /** * @brief Initialize all variables from initial conditions * @param domain the domain containing the mesh and fields @@ -196,21 +171,6 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) const; - /** - * @brief Apply source flux boundary conditions to the system - * @param time current time - * @param dt time step - * @param dofManager degree-of-freedom manager associated with the linear system - * @param domain the domain - * @param localMatrix local system matrix - * @param localRhs local system right-hand side vector - */ - void applySourceFluxBC( real64 const time, - real64 const dt, - DofManager const & dofManager, - DomainPartition & domain, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) const; /** * @brief function to set the next time step size * @param[in] currentDt the current time step size @@ -222,12 +182,36 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase virtual void initializePostInitialConditionsPreSubGroups() override; -protected: +private: virtual void postInputInitialization() override; virtual void initializePreSubGroups() override; + /** + * @brief Update all relevant fluid models using current values of pressure and phase volume fraction + * @param dataGroup the group storing the required fields + */ + void updateFluidModel( ObjectManagerBase & dataGroup ) const; + + /** + * @brief Update all relevant relperm models using current values of phase volume fraction + * @param dataGroup the group storing the required fields + */ + void updateRelPermModel( ObjectManagerBase & dataGroup ) const; + + /** + * @brief Update all relevant capillary pressure models using current values of phase volume fraction + * @param dataGroup the group storing the required fields + */ + void updateCapPressureModel( ObjectManagerBase & dataGroup ) const; + + /** + * @brief Recompute phase mobility from constitutive and primary variables + * @param dataGroup the group storing the required field + */ + void updatePhaseMobility( ObjectManagerBase & dataGroup ) const; + /** * @brief Utility function that encapsulates the call to FieldSpecificationBase::applyFieldValue in BC application * @param[in] time_n the time at the beginning of the step @@ -251,6 +235,13 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase /// flag to determine whether or not to apply capillary pressure integer m_hasCapPressure; + struct viewKeyStruct : public FlowSolverBase::viewKeyStruct + { + static constexpr char const * capPressureNamesString() { return "capPressureNames"; } + static constexpr char const * relPermNamesString() { return "relPermNames"; } + static constexpr char const * elemDofFieldString() { return "elemDofField"; } + }; + private: virtual void setConstitutiveNames( ElementSubRegionBase & subRegion ) const override; @@ -259,11 +250,11 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase template< typename OBJECT_TYPE > void ImmiscibleMultiphaseFlow::applyFieldValue( real64 const & time_n, - real64 const & dt, - MeshLevel & mesh, - char const logMessage[], - string const fieldKey, - string const boundaryFieldKey ) const + real64 const & dt, + MeshLevel & mesh, + char const logMessage[], + string const fieldKey, + string const boundaryFieldKey ) const { FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp index abf3588f0eb..3cb4fc7a6df 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp @@ -17,8 +17,8 @@ * @file CompositionalMultiphaseBaseFields.hpp */ -#ifndef GEOS_PHYSICSSOLVERS_FLUIDFLOW_COMPOSITIONALMULTIPHASEBASEFIELDS_HPP_ -#define GEOS_PHYSICSSOLVERS_FLUIDFLOW_COMPOSITIONALMULTIPHASEBASEFIELDS_HPP_ +#ifndef GEOS_PHYSICSSOLVERS_FLUIDFLOW_IMMISCIBLEMULTIPHASEFLOWFIELDS_HPP_ +#define GEOS_PHYSICSSOLVERS_FLUIDFLOW_IMMISCIBLEMULTIPHASEFLOWFIELDS_HPP_ #include "common/DataLayouts.hpp" #include "mesh/MeshFields.hpp" @@ -67,7 +67,7 @@ DECLARE_FIELD( phaseMass_n, 0, NOPLOT, WRITE_AND_READ, - "Phase mass at the previous converged time step" ); + "Phase mass at the previous converged time step" ); DECLARE_FIELD( phaseMobility, "phaseMobility", @@ -106,4 +106,4 @@ DECLARE_FIELD( phaseCFLNumber, } -#endif // GEOS_PHYSICSSOLVERS_FLUIDFLOW_COMPOSITIONALMULTIPHASEBASEFIELDS_HPP_ +#endif // GEOS_PHYSICSSOLVERS_FLUIDFLOW_IMMISCIBLEMULTIPHASEFLOWFIELDS_HPP_ diff --git a/src/coreComponents/physicsSolvers/fluidFlow/IsothermalCompositionalMultiphaseBaseKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/IsothermalCompositionalMultiphaseBaseKernels.hpp index 108e5a9261a..61493575cd7 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/IsothermalCompositionalMultiphaseBaseKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/IsothermalCompositionalMultiphaseBaseKernels.hpp @@ -26,6 +26,7 @@ #include "common/GEOS_RAJA_Interface.hpp" #include "constitutive/solid/CoupledSolidBase.hpp" #include "constitutive/fluid/multifluid/MultiFluidBase.hpp" +#include "constitutive/relativePermeability/layouts.hpp" #include "functions/TableFunction.hpp" #include "mesh/ElementSubRegionBase.hpp" #include "mesh/ObjectManagerBase.hpp" From 0d159ae1fafaba46a9543cf718585176c2c5ee52 Mon Sep 17 00:00:00 2001 From: Ryan Michael Aronson Date: Thu, 1 Aug 2024 11:12:39 -0700 Subject: [PATCH 006/104] update input file so it runs --- .../immiscible_2phaseFlow_1d.xml | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscible_2phaseFlow_1d.xml b/inputFiles/immiscibleMultiphaseFlow/immiscible_2phaseFlow_1d.xml index 0c928a15e2b..ecbf73253af 100644 --- a/inputFiles/immiscibleMultiphaseFlow/immiscible_2phaseFlow_1d.xml +++ b/inputFiles/immiscibleMultiphaseFlow/immiscible_2phaseFlow_1d.xml @@ -7,7 +7,8 @@ name="FlowSolver" discretization="TPFA" targetRegions="{ Domain }" - logLevel="1"> + logLevel="1" + temperature="300"> @@ -51,7 +52,7 @@ + target="/Solvers/FlowSolver"/> + materialList="{ water, rock, relperm }"/> @@ -101,6 +102,15 @@ + + + + From 7783a15411524b2d4b865f894442fb29e33e3af3 Mon Sep 17 00:00:00 2001 From: Ryan Michael Aronson Date: Thu, 1 Aug 2024 12:25:20 -0700 Subject: [PATCH 007/104] adding skeleton for setupDofs --- .../fluidFlow/ImmiscibleMultiphaseFlow.cpp | 28 +++++++++++++++++++ .../fluidFlow/ImmiscibleMultiphaseFlow.hpp | 4 +++ 2 files changed, 32 insertions(+) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index 9a93fec7e66..48625cc4c3b 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -533,6 +533,34 @@ void ImmiscibleMultiphaseFlow::assembleFluxTerms( real64 const dt, GEOS_UNUSED_VAR( dt, domain, dofManager, localMatrix, localRhs ); } +// Ryan: Looks like this will need to be overwritten as well... +// I have left the CompositionalMultiphaseFVM implementation for reference +void ImmiscibleMultiphaseFlow::setupDofs( DomainPartition const & domain, + DofManager & dofManager ) const +{ + GEOS_UNUSED_VAR(domain, dofManager); + //// add a field for the cell-centered degrees of freedom + //dofManager.addField( viewKeyStruct::elemDofFieldString(), + // FieldLocation::Elem, + // m_numDofPerCell, + // getMeshTargets() ); + + //// this call with instruct GEOS to reorder the dof numbers + //dofManager.setLocalReorderingType( viewKeyStruct::elemDofFieldString(), + // DofManager::LocalReorderingType::ReverseCutHillMcKee ); + + //// for the volume balance equation, disable global coupling + //// this equation is purely local (not coupled to neighbors or other physics) + //dofManager.disableGlobalCouplingForEquation( viewKeyStruct::elemDofFieldString(), + // m_numComponents ); + + + //NumericalMethodsManager const & numericalMethodManager = domain.getNumericalMethodManager(); + //FiniteVolumeManager const & fvManager = numericalMethodManager.getFiniteVolumeManager(); + //FluxApproximationBase const & fluxApprox = fvManager.getFluxApproximation( m_discretizationName ); + //dofManager.addCoupling( viewKeyStruct::elemDofFieldString(), fluxApprox ); +} + void ImmiscibleMultiphaseFlow::applyBoundaryConditions( real64 const time_n, real64 const dt, DomainPartition & domain, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp index 3c6236afc70..34d603abadb 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp @@ -88,6 +88,10 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) override; + virtual void + setupDofs( DomainPartition const & domain, + DofManager & dofManager ) const override; + virtual void applyBoundaryConditions( real64 const time_n, real64 const dt, From 5fcd5d8adc46530bcc479ff6c6c538f36670794c Mon Sep 17 00:00:00 2001 From: rpiazza87 Date: Wed, 31 Jul 2024 17:19:00 -0700 Subject: [PATCH 008/104] testing --- .../physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index 48625cc4c3b..441c7ebc926 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -485,7 +485,7 @@ void ImmiscibleMultiphaseFlow::assembleSystem( real64 const GEOS_UNUSED_PARAM( t CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) { - GEOS_MARK_FUNCTION; + GEOS_MARK_FUNCTION; // TODO Ralph assembleAccumulationTerm( domain, dofManager, From 8e132b9ac85c5890c623e76a47c5981b461274b3 Mon Sep 17 00:00:00 2001 From: rpiazza87 Date: Fri, 2 Aug 2024 08:58:20 -0700 Subject: [PATCH 009/104] fluid model --- .../fluidFlow/ImmiscibleMultiphaseFlow.cpp | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index 441c7ebc926..a05d5ed652f 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -34,6 +34,8 @@ #include "constitutive/ConstitutivePassThru.hpp" +#include + #if defined( __INTEL_COMPILER ) #pragma GCC optimize "O0" #endif @@ -45,6 +47,48 @@ using namespace dataRepository; using namespace constitutive; using namespace fields::immiscibleMultiphaseFlow; +// Fluid model for isothermal T = 175 oC +double co2_viscosity(double P) +{ + P = P / 1000000; // check whether GEOS uses Pa or MPa + return ( -1.5596 * pow(10, -10) * pow(P, 3) + 1.94571 * pow(10, -8) * pow(P, 2) + 6.77304 * pow(10, -8) * P + 0.0000214166); // [Pa.s] +} + +double co2_dviscosity(double P) +{ + P = P / 1000000; // check whether GEOS uses Pa or MPa + return ( -4.6788 * pow(10, -10) * pow(P, 2) + 3.89142 * pow(10, -8) * P + 6.77304 * pow(10, -8)); +} + +double co2_density(double P) +{ + P = P / 1000000; // check whether GEOS uses Pa or MPa + return ( -0.0000126691 * pow(P, 3) - 0.118131 * pow(P, 2) + 19.6211 * P - 52.0635 ); +} + +double co2_ddensity(double P) +{ + P = P / 1000000; // check whether GEOS uses Pa or MPa + return ( -0.0000380073 * pow(P, 2) - 0.236262 * P + 19.6211 ); +} + +double water_viscosity(double P) { + return ( 0.000164 ); +} + +double water_dviscosity(double P) { + return ( 0.0 ); +} + +double water_density(double P) { + P = P / 1000000; // check whether GEOS uses Pa or MPa + return ( 0.55125 * P + 893.06044); +} + +double water_ddensity(double P) { + return ( 0.55125 ); +} + ImmiscibleMultiphaseFlow::ImmiscibleMultiphaseFlow( const string & name, Group * const parent ) : From c21d0474e02cd03a3d387968f05558751c6b4f88 Mon Sep 17 00:00:00 2001 From: rpiazza87 Date: Fri, 2 Aug 2024 09:44:45 -0700 Subject: [PATCH 010/104] rock-fluid model --- .../fluidFlow/ImmiscibleMultiphaseFlow.cpp | 45 ++++++++++++++++--- 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index a05d5ed652f..a5654480c27 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -57,36 +57,67 @@ double co2_viscosity(double P) double co2_dviscosity(double P) { P = P / 1000000; // check whether GEOS uses Pa or MPa - return ( -4.6788 * pow(10, -10) * pow(P, 2) + 3.89142 * pow(10, -8) * P + 6.77304 * pow(10, -8)); + return ( -4.6788 * pow(10, -10) * pow(P, 2) + 3.89142 * pow(10, -8) * P + 6.77304 * pow(10, -8)); // [Pa.s/MPa] } double co2_density(double P) { P = P / 1000000; // check whether GEOS uses Pa or MPa - return ( -0.0000126691 * pow(P, 3) - 0.118131 * pow(P, 2) + 19.6211 * P - 52.0635 ); + return ( -0.0000126691 * pow(P, 3) - 0.118131 * pow(P, 2) + 19.6211 * P - 52.0635 ); // [kg/m3] } double co2_ddensity(double P) { P = P / 1000000; // check whether GEOS uses Pa or MPa - return ( -0.0000380073 * pow(P, 2) - 0.236262 * P + 19.6211 ); + return ( -0.0000380073 * pow(P, 2) - 0.236262 * P + 19.6211 ); // [kg/m3.MPa] } double water_viscosity(double P) { - return ( 0.000164 ); + return ( 0.000164 ); // [Pa.s] } double water_dviscosity(double P) { - return ( 0.0 ); + return ( 0.0 ); // [Pa.s/MPa] } double water_density(double P) { P = P / 1000000; // check whether GEOS uses Pa or MPa - return ( 0.55125 * P + 893.06044); + return ( 0.55125 * P + 893.06044); // [kg/m3] } double water_ddensity(double P) { - return ( 0.55125 ); + return ( 0.55125 ); // [kg/m3.MPa] +} + +// Rock-Fluid model +double co2_relperm(double S) +{ + return ( pow(1 - S, 2) ); // [-] +} + +double co2_drelperm(double S) +{ + return ( 2 * (1 - S) ); // [-] +} + +double water_relperm(double S) +{ + return ( pow(S, 6) ); // [-] +} + +double water_drelperm(double S) +{ + return ( 6 * pow(S, 5) ); // [-] +} + +double co2_cappress(double S) +{ + return ( 0.00049309 * pow(S, -2.34806) ); // [MPa] check whether GEOS uses Pa or MPa +} + +double co2_dcappress(double S) +{ + return ( -0.00021 * pow(S, -1.34806) ); // [MPa] check whether GEOS uses Pa or MPa } ImmiscibleMultiphaseFlow::ImmiscibleMultiphaseFlow( const string & name, From d59fa4ef7c4ed92dca2702f9bed2a07cceab5597 Mon Sep 17 00:00:00 2001 From: rpiazza87 Date: Tue, 6 Aug 2024 18:08:51 -0700 Subject: [PATCH 011/104] new kernel file --- .../fluidFlow/ImmiscibleMultiphaseFlow.cpp | 99 +++++-- .../fluidFlow/ImmiscibleMultiphaseKernels.hpp | 246 ++++++++++++++++++ 2 files changed, 324 insertions(+), 21 deletions(-) create mode 100644 src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index a5654480c27..507ab656c42 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -21,6 +21,7 @@ #include "FlowSolverBaseFields.hpp" #include "physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp" +#include "physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp" #include "physicsSolvers/fluidFlow/IsothermalCompositionalMultiphaseBaseKernels.hpp" #include "physicsSolvers/fluidFlow/IsothermalCompositionalMultiphaseFVMKernels.hpp" @@ -48,74 +49,78 @@ using namespace constitutive; using namespace fields::immiscibleMultiphaseFlow; // Fluid model for isothermal T = 175 oC -double co2_viscosity(double P) +real64 co2_viscosity(real64 P) { - P = P / 1000000; // check whether GEOS uses Pa or MPa + P = P / 1000000.0; // check whether GEOS uses Pa or MPa return ( -1.5596 * pow(10, -10) * pow(P, 3) + 1.94571 * pow(10, -8) * pow(P, 2) + 6.77304 * pow(10, -8) * P + 0.0000214166); // [Pa.s] } -double co2_dviscosity(double P) +real64 co2_dviscosity(real64 P) { - P = P / 1000000; // check whether GEOS uses Pa or MPa + P = P / 1000000.0; // check whether GEOS uses Pa or MPa return ( -4.6788 * pow(10, -10) * pow(P, 2) + 3.89142 * pow(10, -8) * P + 6.77304 * pow(10, -8)); // [Pa.s/MPa] } -double co2_density(double P) +real64 co2_density(real64 P) { - P = P / 1000000; // check whether GEOS uses Pa or MPa + P = P / 1000000.0; // check whether GEOS uses Pa or MPa return ( -0.0000126691 * pow(P, 3) - 0.118131 * pow(P, 2) + 19.6211 * P - 52.0635 ); // [kg/m3] } -double co2_ddensity(double P) +real64 co2_ddensity(real64 P) { - P = P / 1000000; // check whether GEOS uses Pa or MPa + P = P / 1000000.0; // check whether GEOS uses Pa or MPa return ( -0.0000380073 * pow(P, 2) - 0.236262 * P + 19.6211 ); // [kg/m3.MPa] } -double water_viscosity(double P) { +real64 water_viscosity(real64 P) +{ return ( 0.000164 ); // [Pa.s] } -double water_dviscosity(double P) { +real64 water_dviscosity(real64 P) +{ return ( 0.0 ); // [Pa.s/MPa] } -double water_density(double P) { - P = P / 1000000; // check whether GEOS uses Pa or MPa +real64 water_density(real64 P) +{ + P = P / 1000000.0; // check whether GEOS uses Pa or MPa return ( 0.55125 * P + 893.06044); // [kg/m3] } -double water_ddensity(double P) { +real64 water_ddensity(real64 P) +{ return ( 0.55125 ); // [kg/m3.MPa] } // Rock-Fluid model -double co2_relperm(double S) +real64 co2_relperm(real64 S) { return ( pow(1 - S, 2) ); // [-] } -double co2_drelperm(double S) +real64 co2_drelperm(real64 S) { - return ( 2 * (1 - S) ); // [-] + return ( 2.0 * (1 - S) ); // [-] } -double water_relperm(double S) +real64 water_relperm(real64 S) { return ( pow(S, 6) ); // [-] } -double water_drelperm(double S) +real64 water_drelperm(real64 S) { - return ( 6 * pow(S, 5) ); // [-] + return ( 6.0 * pow(S, 5) ); // [-] } -double co2_cappress(double S) +real64 co2_cappress(real64 S) { return ( 0.00049309 * pow(S, -2.34806) ); // [MPa] check whether GEOS uses Pa or MPa } -double co2_dcappress(double S) +real64 co2_dcappress(real64 S) { return ( -0.00021 * pow(S, -1.34806) ); // [MPa] check whether GEOS uses Pa or MPa } @@ -606,6 +611,58 @@ void ImmiscibleMultiphaseFlow::assembleFluxTerms( real64 const dt, arrayView1d< real64 > const & localRhs ) const { GEOS_UNUSED_VAR( dt, domain, dofManager, localMatrix, localRhs ); + + GEOS_MARK_FUNCTION; + + NumericalMethodsManager const & numericalMethodManager = domain.getNumericalMethodManager(); + FiniteVolumeManager const & fvManager = numericalMethodManager.getFiniteVolumeManager(); + FluxApproximationBase const & fluxApprox = fvManager.getFluxApproximation( m_discretizationName ); + + string const & dofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, + MeshLevel const & mesh, + arrayView1d< string const > const & ) + { + fluxApprox.forAllStencils( mesh, [&]( auto & stencil ) + { + FaceBasedAssemblyKernelFactory::createAndLaunch< parallelDevicePolicy<> >( dofManager.rankOffset(), + dofKey, + getName(), + mesh.getElemManager(), + stencilWrapper, + dt, + localMatrix.toViewConstSizes(), + localRhs.toView() ); + } ); + } ); + +} + +void ImmiscibleMultiphaseFlow::setupDofs( DomainPartition const & domain, + DofManager & dofManager ) const +{ + GEOS_UNUSED_VAR(domain, dofManager); + //// add a field for the cell-centered degrees of freedom + //dofManager.addField( viewKeyStruct::elemDofFieldString(), + // FieldLocation::Elem, + // m_numDofPerCell, + // getMeshTargets() ); + + //// this call with instruct GEOS to reorder the dof numbers + //dofManager.setLocalReorderingType( viewKeyStruct::elemDofFieldString(), + // DofManager::LocalReorderingType::ReverseCutHillMcKee ); + + //// for the volume balance equation, disable global coupling + //// this equation is purely local (not coupled to neighbors or other physics) + //dofManager.disableGlobalCouplingForEquation( viewKeyStruct::elemDofFieldString(), + // m_numComponents ); + + + //NumericalMethodsManager const & numericalMethodManager = domain.getNumericalMethodManager(); + //FiniteVolumeManager const & fvManager = numericalMethodManager.getFiniteVolumeManager(); + //FluxApproximationBase const & fluxApprox = fvManager.getFluxApproximation( m_discretizationName ); + //dofManager.addCoupling( viewKeyStruct::elemDofFieldString(), fluxApprox ); } // Ryan: Looks like this will need to be overwritten as well... diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp new file mode 100644 index 00000000000..c098607d6fa --- /dev/null +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp @@ -0,0 +1,246 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2018-2020 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2020 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2018-2020 TotalEnergies + * Copyright (c) 2019- GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/** + * @file ImmiscibleMultiphaseKernels.hpp + */ + +#ifndef GEOS_PHYSICSSOLVERS_FLUIDFLOW_MULTIPHASEKERNELS_HPP +#define GEOS_PHYSICSSOLVERS_FLUIDFLOW_MULTIPHASEKERNELS_HPP + +#include "common/DataLayouts.hpp" +#include "common/DataTypes.hpp" +#include "common/GEOS_RAJA_Interface.hpp" +#include "constitutive/fluid/singlefluid/SingleFluidBase.hpp" +#include "constitutive/fluid/singlefluid/SingleFluidFields.hpp" +#include "constitutive/fluid/singlefluid/SlurryFluidBase.hpp" +#include "constitutive/fluid/singlefluid/SlurryFluidFields.hpp" +#include "constitutive/permeability/PermeabilityBase.hpp" +#include "constitutive/permeability/PermeabilityFields.hpp" +#include "fieldSpecification/AquiferBoundaryCondition.hpp" +#include "finiteVolume/BoundaryStencil.hpp" +#include "finiteVolume/FluxApproximationBase.hpp" +#include "linearAlgebra/interfaces/InterfaceTypes.hpp" +#include "physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp" +#include "physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp" +#include "physicsSolvers/fluidFlow/SinglePhaseBaseKernels.hpp" // create for multiphase +#include "physicsSolvers/fluidFlow/StencilAccessors.hpp" + +namespace geos +{ + +namespace immiscibleMultiphaseKernels +{ +using namespace constitutive; + + +/******************************** FaceBasedAssemblyKernelBase ********************************/ + +/** + * @brief Base class for FaceBasedAssemblyKernel that holds all data not dependent + * on template parameters (like stencil type and number of dofs). + */ +class FaceBasedAssemblyKernelBase +{ +public: + + /** + * @brief The type for element-based data. Consists entirely of ArrayView's. + * + * Can be converted from ElementRegionManager::ElementViewConstAccessor + * by calling .toView() or .toViewConst() on an accessor instance + */ + template< typename VIEWTYPE > + using ElementViewConst = ElementRegionManager::ElementViewConst< VIEWTYPE >; + + using DofNumberAccessor = ElementRegionManager::ElementViewAccessor< arrayView1d< globalIndex const > >; + + using ImmiscibleMultiphaseFlowAccessors = + StencilAccessors< fields::ghostRank, + fields::flow::pressure, + fields::flow::pressure_n, + fields::flow::gravityCoefficient, + fields::flow::mobility, + fields::flow::dMobility_dPressure >; + + using ImmiscibleMultiphaseFluidAccessors = + StencilMaterialAccessors< SingleFluidBase, + fields::singlefluid::density, + fields::singlefluid::dDensity_dPressure >; + + using SlurryFluidAccessors = + StencilMaterialAccessors< SlurryFluidBase, + fields::singlefluid::density, + fields::singlefluid::dDensity_dPressure >; + + using PermeabilityAccessors = + StencilMaterialAccessors< PermeabilityBase, + fields::permeability::permeability, + fields::permeability::dPerm_dPressure >; + + using ProppantPermeabilityAccessors = + StencilMaterialAccessors< PermeabilityBase, + fields::permeability::permeability, + fields::permeability::dPerm_dPressure, + fields::permeability::dPerm_dDispJump, + fields::permeability::permeabilityMultiplier >; + + /** + * @brief Constructor for the kernel interface + * @param[in] rankOffset the offset of my MPI rank + * @param[in] dofNumberAccessor accessor for the dof numbers + * @param[in] singleFlowAccessors accessor for wrappers registered by the solver + * @param[in] singlePhaseFluidAccessors accessor for wrappers registered by the singlefluid model + * @param[in] permeabilityAccessors accessor for wrappers registered by the permeability model + * @param[in] dt time step size + * @param[inout] localMatrix the local CRS matrix + * @param[inout] localRhs the local right-hand side vector + */ + FaceBasedAssemblyKernelBase( globalIndex const rankOffset, + DofNumberAccessor const & dofNumberAccessor, + ImmiscibleMultiphaseFlowAccessors const & singlePhaseFlowAccessors, + ImmiscibleMultiphaseFluidAccessors const & singlePhaseFluidAccessors, + PermeabilityAccessors const & permeabilityAccessors, + real64 const & dt, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) + : m_rankOffset( rankOffset ), + m_dt( dt ), + m_dofNumber( dofNumberAccessor.toNestedViewConst() ), + m_permeability( permeabilityAccessors.get( fields::permeability::permeability {} ) ), + m_dPerm_dPres( permeabilityAccessors.get( fields::permeability::dPerm_dPressure {} ) ), + m_ghostRank( singlePhaseFlowAccessors.get( fields::ghostRank {} ) ), + m_gravCoef( singlePhaseFlowAccessors.get( fields::flow::gravityCoefficient {} ) ), + m_pres( singlePhaseFlowAccessors.get( fields::flow::pressure {} ) ), + m_mob( singlePhaseFlowAccessors.get( fields::flow::mobility {} ) ), + m_dMob_dPres( singlePhaseFlowAccessors.get( fields::flow::dMobility_dPressure {} ) ), + m_dens( singlePhaseFluidAccessors.get( fields::singlefluid::density {} ) ), + m_dDens_dPres( singlePhaseFluidAccessors.get( fields::singlefluid::dDensity_dPressure {} ) ), + m_localMatrix( localMatrix ), + m_localRhs( localRhs ) + {} + +protected: + + /// Offset for my MPI rank + globalIndex const m_rankOffset; + + /// Time step size + real64 const m_dt; + + /// Views on dof numbers + ElementViewConst< arrayView1d< globalIndex const > > const m_dofNumber; + + /// Views on permeability + ElementViewConst< arrayView3d< real64 const > > m_permeability; + ElementViewConst< arrayView3d< real64 const > > m_dPerm_dPres; + + /// Views on ghost rank numbers and gravity coefficients + ElementViewConst< arrayView1d< integer const > > const m_ghostRank; + ElementViewConst< arrayView1d< real64 const > > const m_gravCoef; + + // Primary and secondary variables + /// Views on pressure + ElementViewConst< arrayView1d< real64 const > > const m_pres; + + /// Views on fluid mobility + ElementViewConst< arrayView1d< real64 const > > const m_mob; + ElementViewConst< arrayView1d< real64 const > > const m_dMob_dPres; + + /// Views on fluid density + ElementViewConst< arrayView2d< real64 const > > const m_dens; + ElementViewConst< arrayView2d< real64 const > > const m_dDens_dPres; + + // Residual and jacobian + + /// View on the local CRS matrix + CRSMatrixView< real64, globalIndex const > const m_localMatrix; + /// View on the local RHS + arrayView1d< real64 > const m_localRhs; +}; + + + + + + + + + + + + + + + + + + +/** + * @class FaceBasedAssemblyKernelFactory + */ +class FaceBasedAssemblyKernelFactory +{ +public: + + /** + * @brief Create a new kernel and launch + * @tparam POLICY the policy used in the RAJA kernel + * @tparam STENCILWRAPPER the type of the stencil wrapper + * @param[in] rankOffset the offset of my MPI rank + * @param[in] dofKey string to get the element degrees of freedom numbers + * @param[in] solverName name of the solver (to name accessors) + * @param[in] elemManager reference to the element region manager + * @param[in] stencilWrapper reference to the stencil wrapper + * @param[in] dt time step size + * @param[inout] localMatrix the local CRS matrix + * @param[inout] localRhs the local right-hand side vector + */ + template< typename POLICY, typename STENCILWRAPPER > + static void + createAndLaunch( globalIndex const rankOffset, + string const & dofKey, + string const & solverName, + ElementRegionManager const & elemManager, + STENCILWRAPPER const & stencilWrapper, + real64 const & dt, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) + { + integer constexpr NUM_EQN = 1; + integer constexpr NUM_DOF = 1; + + ElementRegionManager::ElementViewAccessor< arrayView1d< globalIndex const > > dofNumberAccessor = + elemManager.constructArrayViewAccessor< globalIndex, 1 >( dofKey ); + dofNumberAccessor.setName( solverName + "/accessors/" + dofKey ); + + using kernelType = FaceBasedAssemblyKernel< NUM_EQN, NUM_DOF, STENCILWRAPPER >; + typename kernelType::SinglePhaseFlowAccessors flowAccessors( elemManager, solverName ); + typename kernelType::SinglePhaseFluidAccessors fluidAccessors( elemManager, solverName ); + typename kernelType::PermeabilityAccessors permAccessors( elemManager, solverName ); + + kernelType kernel( rankOffset, stencilWrapper, dofNumberAccessor, + flowAccessors, fluidAccessors, permAccessors, + dt, localMatrix, localRhs ); + kernelType::template launch< POLICY >( stencilWrapper.size(), kernel ); + } +}; + + + + +} // namesace immiscible multiphasekernels + + +} // namespace geos \ No newline at end of file From 1fe657043a19696fada2b06e49b51c72f967a18f Mon Sep 17 00:00:00 2001 From: rpiazza87 Date: Mon, 12 Aug 2024 00:33:37 -0700 Subject: [PATCH 012/104] updated kernel functions --- .../fluidFlow/ImmiscibleMultiphaseKernels.hpp | 579 ++++++++++++++++-- 1 file changed, 534 insertions(+), 45 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp index c098607d6fa..c6f1a05c868 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp @@ -22,7 +22,7 @@ #include "common/DataLayouts.hpp" #include "common/DataTypes.hpp" #include "common/GEOS_RAJA_Interface.hpp" -#include "constitutive/fluid/singlefluid/SingleFluidBase.hpp" +#include "constitutive/fluid/singlefluid/SingleFluidBase.hpp" // get correct fluid model #include "constitutive/fluid/singlefluid/SingleFluidFields.hpp" #include "constitutive/fluid/singlefluid/SlurryFluidBase.hpp" #include "constitutive/fluid/singlefluid/SlurryFluidFields.hpp" @@ -34,7 +34,7 @@ #include "linearAlgebra/interfaces/InterfaceTypes.hpp" #include "physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp" #include "physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp" -#include "physicsSolvers/fluidFlow/SinglePhaseBaseKernels.hpp" // create for multiphase +#include "physicsSolvers/fluidFlow/SinglePhaseBaseKernels.hpp" // create for multiphase for kernels #include "physicsSolvers/fluidFlow/StencilAccessors.hpp" namespace geos @@ -70,69 +70,79 @@ class FaceBasedAssemblyKernelBase StencilAccessors< fields::ghostRank, fields::flow::pressure, fields::flow::pressure_n, + fields::flow::phaseVolumeFraction, + fields::flow::phaseVolumeFraction_n, fields::flow::gravityCoefficient, - fields::flow::mobility, - fields::flow::dMobility_dPressure >; + fields::flow::phaseMobility, + fields::flow::dPhaseMobility >; // TODO: fix derivatives of mobility using ImmiscibleMultiphaseFluidAccessors = - StencilMaterialAccessors< SingleFluidBase, - fields::singlefluid::density, - fields::singlefluid::dDensity_dPressure >; + StencilMaterialAccessors< MultiFluidBase, + fields::multifluid::phaseDensity, + fields::multifluid::dPhaseDensity >; - using SlurryFluidAccessors = - StencilMaterialAccessors< SlurryFluidBase, - fields::singlefluid::density, - fields::singlefluid::dDensity_dPressure >; + using CapPressureAccessors = + StencilMaterialAccessors< CapillaryPressureBase, + fields::cappres::phaseCapPressure, + fields::cappres::dPhaseCapPressure_dPhaseVolFraction >; using PermeabilityAccessors = StencilMaterialAccessors< PermeabilityBase, fields::permeability::permeability, - fields::permeability::dPerm_dPressure >; - - using ProppantPermeabilityAccessors = - StencilMaterialAccessors< PermeabilityBase, - fields::permeability::permeability, - fields::permeability::dPerm_dPressure, - fields::permeability::dPerm_dDispJump, - fields::permeability::permeabilityMultiplier >; + fields::permeability::dPerm_dPressure >; /** * @brief Constructor for the kernel interface + * @param[in] numPhases the number of fluid phases * @param[in] rankOffset the offset of my MPI rank * @param[in] dofNumberAccessor accessor for the dof numbers - * @param[in] singleFlowAccessors accessor for wrappers registered by the solver - * @param[in] singlePhaseFluidAccessors accessor for wrappers registered by the singlefluid model + * @param[in] multiPhaseFlowAccessors accessor for wrappers registered by the solver + * @param[in] multiPhaseFluidAccessors accessor for wrappers registered by the multiphase fluid model + * @param[in] capPressureAccessors accessor for wrappers registered by the capillary pressure model * @param[in] permeabilityAccessors accessor for wrappers registered by the permeability model * @param[in] dt time step size * @param[inout] localMatrix the local CRS matrix * @param[inout] localRhs the local right-hand side vector */ - FaceBasedAssemblyKernelBase( globalIndex const rankOffset, + FaceBasedAssemblyKernelBase( integer const numPhases, + globalIndex const rankOffset, DofNumberAccessor const & dofNumberAccessor, - ImmiscibleMultiphaseFlowAccessors const & singlePhaseFlowAccessors, - ImmiscibleMultiphaseFluidAccessors const & singlePhaseFluidAccessors, + ImmiscibleMultiphaseFlowAccessors const & multiPhaseFlowAccessors, + ImmiscibleMultiphaseFluidAccessors const & multiPhaseFluidAccessors, + CapPressureAccessors const & capPressureAccessors, PermeabilityAccessors const & permeabilityAccessors, real64 const & dt, CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) - : m_rankOffset( rankOffset ), + arrayView1d< real64 > const & localRhs, + integer const hasCapPressure, + integer const useTotalMassEquation ) + : m_numPhases (numPhases), + m_rankOffset( rankOffset ), m_dt( dt ), m_dofNumber( dofNumberAccessor.toNestedViewConst() ), m_permeability( permeabilityAccessors.get( fields::permeability::permeability {} ) ), m_dPerm_dPres( permeabilityAccessors.get( fields::permeability::dPerm_dPressure {} ) ), - m_ghostRank( singlePhaseFlowAccessors.get( fields::ghostRank {} ) ), - m_gravCoef( singlePhaseFlowAccessors.get( fields::flow::gravityCoefficient {} ) ), - m_pres( singlePhaseFlowAccessors.get( fields::flow::pressure {} ) ), - m_mob( singlePhaseFlowAccessors.get( fields::flow::mobility {} ) ), - m_dMob_dPres( singlePhaseFlowAccessors.get( fields::flow::dMobility_dPressure {} ) ), - m_dens( singlePhaseFluidAccessors.get( fields::singlefluid::density {} ) ), - m_dDens_dPres( singlePhaseFluidAccessors.get( fields::singlefluid::dDensity_dPressure {} ) ), + m_ghostRank( multiPhaseFlowAccessors.get( fields::ghostRank {} ) ), + m_gravCoef( multiPhaseFlowAccessors.get( fields::flow::gravityCoefficient {} ) ), + m_pres( multiPhaseFlowAccessors.get( fields::flow::pressure {} ) ), + m_mob( multiPhaseFlowAccessors.get( fields::flow::phaseMobility {} ) ), + m_dMob_dPres( multiPhaseFlowAccessors.get( fields::flow::dPhaseMobility {} ) ), + m_dMob_dSat( multiPhaseFlowAccessors.get( fields::flow::dPhaseMobility {} ) ), + m_dens( multiPhaseFluidAccessors.get( fields::multifluid::phaseDensity {} ) ), + m_dDens_dPres( multiPhaseFluidAccessors.get( fields::multifluid::dPhaseDensity {} ) ), + m_phaseCapPressure( capPressureAccessors.get( fields::cappres::phaseCapPressure {} ) ), + m_dPhaseCapPressure_dPhaseVolFrac( capPressureAccessors.get( fields::cappres::dPhaseCapPressure_dPhaseVolFraction {} ) ), m_localMatrix( localMatrix ), - m_localRhs( localRhs ) + m_localRhs( localRhs ), + m_hasCapPressure ( hasCapPressure ), + m_useTotalMassEquation ( useTotalMassEquation ) {} protected: + /// Number of fluid phases + integer const m_numPhases; + /// Offset for my MPI rank globalIndex const m_rankOffset; @@ -153,39 +163,512 @@ class FaceBasedAssemblyKernelBase // Primary and secondary variables /// Views on pressure ElementViewConst< arrayView1d< real64 const > > const m_pres; + /// Views on saturation + ElementViewConst< arrayView1d< real64 const > > const m_phaseVolFraction; /// Views on fluid mobility - ElementViewConst< arrayView1d< real64 const > > const m_mob; - ElementViewConst< arrayView1d< real64 const > > const m_dMob_dPres; + ElementViewConst< arrayView2d< real64 const > > const m_mob; + ElementViewConst< arrayView2d< real64 const > > const m_dMob_dPres; + ElementViewConst< arrayView2d< real64 const > > const m_dMob_dSat; /// Views on fluid density ElementViewConst< arrayView2d< real64 const > > const m_dens; ElementViewConst< arrayView2d< real64 const > > const m_dDens_dPres; + /// Views on capillary pressure + ElementViewConst< arrayView2d< real64 const > > const m_phaseCapPressure; + ElementViewConst< arrayView2d< real64 const > > const m_dPhaseCapPressure_dPhaseVolFrac; + // Residual and jacobian /// View on the local CRS matrix CRSMatrixView< real64, globalIndex const > const m_localMatrix; /// View on the local RHS arrayView1d< real64 > const m_localRhs; + + // Flags + integer const m_hasCapPressure; + integer const m_useTotalMassEquation; }; +/***************************************** */ +/** + * @class FaceBasedAssemblyKernel + * @tparam NUM_DOF number of degrees of freedom + * @tparam STENCILWRAPPER the type of the stencil wrapper + * @brief Define the interface for the assembly kernel in charge of flux terms + */ +template< integer NUM_EQN, integer NUM_DOF, typename STENCILWRAPPER > +class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase +{ +public: + /// Compute time value for the number of degrees of freedom + static constexpr integer numDof = NUM_DOF; + /// Compute time value for the number of equations + static constexpr integer numEqn = NUM_EQN; + /// Maximum number of elements at the face + static constexpr localIndex maxNumElems = STENCILWRAPPER::maxNumPointsInFlux; + /// Maximum number of connections at the face + static constexpr localIndex maxNumConns = STENCILWRAPPER::maxNumConnections; + /// Maximum number of points in the stencil + static constexpr localIndex maxStencilSize = STENCILWRAPPER::maxStencilSize; + /** + * @brief Constructor for the kernel interface + * @param[in] rankOffset the offset of my MPI rank + * @param[in] stencilWrapper reference to the stencil wrapper + * @param[in] dofNumberAccessor + * @param[in] singlePhaseFlowAccessors + * @param[in] singlePhaseFluidAccessors + * @param[in] capPressureAccessors + * @param[in] permeabilityAccessors + * @param[in] dt time step size + * @param[inout] localMatrix the local CRS matrix + * @param[inout] localRhs the local right-hand side vector + * @param[in] hasCapPressure flags for capillary pressure + * @param[in] useTotalMassEquation flags for using total velocity formulation + */ + FaceBasedAssemblyKernel( integer const numPhases, + globalIndex const rankOffset, + STENCILWRAPPER const & stencilWrapper, + DofNumberAccessor const & dofNumberAccessor, + ImmiscibleMultiphaseFlowAccessors const & multiPhaseFlowAccessors, + ImmiscibleMultiphaseFluidAccessors const & multiPhaseFluidAccessors, + CapPressureAccessors const & capPressureAccessors, + PermeabilityAccessors const & permeabilityAccessors, + real64 const & dt, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs, + integer const hasCapPressure, + integer const useTotalMassEquation ) + : FaceBasedAssemblyKernelBase( numPhases, + rankOffset, + dofNumberAccessor, + multiPhaseFlowAccessors, + multiPhaseFluidAccessors, + capPressureAccessors, + permeabilityAccessors, + dt, + localMatrix, + localRhs, + hasCapPressure, + useTotalMassEquation ), + m_stencilWrapper( stencilWrapper ), + m_seri( stencilWrapper.getElementRegionIndices() ), + m_sesri( stencilWrapper.getElementSubRegionIndices() ), + m_sei( stencilWrapper.getElementIndices() ) + {} + + /** + * @struct StackVariables + * @brief Kernel variables (dof numbers, jacobian and residual) located on the stack + */ + struct StackVariables + { + public: + /** + * @brief Constructor for the stack variables + * @param[in] size size of the stencil for this connection + * @param[in] numElems number of elements for this connection + */ + GEOS_HOST_DEVICE + StackVariables( localIndex const size, localIndex numElems ) + : stencilSize( size ), + numFluxElems( numElems ), + dofColIndices( size * numDof ), + localFlux( numElems * numEqn ), + localFluxJacobian( numElems * numEqn, size * numDof ) + {} + // Stencil information + /// Stencil size for a given connection + localIndex const stencilSize; + /// Number of elements for a given connection + localIndex const numFluxElems; + // Transmissibility and derivatives + /// Transmissibility + real64 transmissibility[maxNumConns][2]{}; + /// Derivatives of transmissibility with respect to pressure + real64 dTrans_dPres[maxNumConns][2]{}; + // Local degrees of freedom and local residual/jacobian + /// Indices of the matrix rows/columns corresponding to the dofs in this face + stackArray1d< globalIndex, maxNumElems * numDof > dofColIndices; + /// Storage for the face local residual vector (all equations except volume balance) + stackArray1d< real64, maxNumElems * numEqn > localFlux; + /// Storage for the face local Jacobian matrix + stackArray2d< real64, maxNumElems * numEqn * maxStencilSize * numDof > localFluxJacobian; + }; + + /** + * @brief Getter for the stencil size at this connection + * @param[in] iconn the connection index + * @return the size of the stencil at this connection + */ + GEOS_HOST_DEVICE + localIndex stencilSize( localIndex const iconn ) const + { return m_sei[iconn].size(); } + + /** + * @brief Getter for the number of elements at this connection + * @param[in] iconn the connection index + * @return the number of elements at this connection + */ + GEOS_HOST_DEVICE + localIndex numPointsInFlux( localIndex const iconn ) const + { return m_stencilWrapper.numPointsInFlux( iconn ); } + + /** + * @brief Performs the setup phase for the kernel. + * @param[in] iconn the connection index + * @param[in] stack the stack variables + */ + + GEOS_HOST_DEVICE + void setup( localIndex const iconn, + StackVariables & stack ) const + { + // set degrees of freedom indices for this face + for( integer i = 0; i < stack.stencilSize; ++i ) + { + globalIndex const offset = m_dofNumber[m_seri( iconn, i )][m_sesri( iconn, i )][m_sei( iconn, i )]; + + for( integer jdof = 0; jdof < numDof; ++jdof ) + { + stack.dofColIndices[i * numDof + jdof] = offset + jdof; + } + } + } + + /** + * @brief Compute the local flux contributions to the residual and Jacobian + * @tparam FUNC the type of the function that can be used to customize the computation of the flux + * @param[in] iconn the connection index + * @param[inout] stack the stack variables + * @param[in] NoOpFunc the function used to customize the computation of the flux + */ + template< typename FUNC = multiPhaseBaseKernels::NoOpFunc > + GEOS_HOST_DEVICE + void computeFlux( localIndex const iconn, + StackVariables & stack, + FUNC && kernelOp = singlePhaseBaseKernels::NoOpFunc{} ) const + { + // first, compute the transmissibilities at this face // get k and dk/dP from global arrays and place in stack + m_stencilWrapper.computeWeights( iconn, + m_permeability, + m_dPerm_dPres, + stack.transmissibility, + stack.dTrans_dPres ); + + localIndex k[2]; + localIndex connectionIndex = 0; + + for( k[0] = 0; k[0] < stack.numFluxElems; ++k[0] ) + { + for( k[1] = k[0] + 1; k[1] < stack.numFluxElems; ++k[1] ) + { + // clear working arrays + real64 densMean[m_numPhases]{}; + real64 dDensMean_dP[m_numPhases][2]{}; + // real64 densMean = 0.0; + // real64 dDensMean_dP[2]{0.0, 0.0}; + + real64 presGrad[m_numPhases]{}; /// check need for vector + real64 dPresGrad_dP[m_numPhases][2]{}; + // real64 presGrad = 0.0; + // real64 dPresGrad_dP[2]{0.0, 0.0}; + + real64 gravHead[m_numPhases]{}; + real64 dGravHead_dP[m_numPhases][2]{}; + // real64 gravHead = 0.0; + // real64 dGravHead_dP[2]{0.0, 0.0}; + + real64 capGrad[m_numPhases]{}; + real64 dCapGrad_dP[m_numPhases][2]{}; + real64 dCapGrad_dS[m_numPhases][2]{}; + + real64 fluxVal[m_numPhases]{}; + real64 dFlux_dP[m_numPhases][2]{}; + real64 dFlux_dS[m_numPhases][2]{}; + // real64 fluxVal = 0.0; + // real64 dFlux_dP[2]{0.0, 0.0}; + + real64 mobility[m_numPhases]{}; + real64 dMob_dP[m_numPhases][2]{}; + real64 dMob_dS[m_numPhases][2]{}; + + real64 const trans[2] = { stack.transmissibility[connectionIndex][0], stack.transmissibility[connectionIndex][1] }; + real64 const dTrans_dP[2] = { stack.dTrans_dPres[connectionIndex][0], stack.dTrans_dPres[connectionIndex][1] }; + + // cell indices + localIndex const seri[2] = {m_seri( iconn, k[0] ), m_seri( iconn, k[1] )}; + localIndex const sesri[2] = {m_sesri( iconn, k[0] ), m_sesri( iconn, k[1] )}; + localIndex const sei[2] = {m_sei( iconn, k[0] ), m_sei( iconn, k[1] )}; + + // loop over phases + for( integer ip = 0; ip < m_numPhases; ++ip ) + { + + // calculate quantities on primary connected cells + for( integer ke = 0; ke < 2; ++ke ) + { + // density + real64 const density = m_dens[seri[ke]][sesri[ke]][sei[ke]][ip]; + real64 const dDens_dP = m_dDens_dPres[seri[ke]][sesri[ke]][sei[ke]][ip]; + + // average density and derivatives + densMean[ip] += 0.5 * density; // rho = (rho1 + rho2) / 2 + dDensMean_dP[ip][ke] = 0.5 * dDens_dP; // drho/dP = { (drho1/dP)/2 , (drho2/dP)/2 } + } + + //***** calculation of flux ***** + + // compute potential difference + real64 potScale = 0.0; + real64 dPresGrad_dTrans = 0.0; + real64 dGravHead_dTrans = 0.0; + real64 dCapGrad_dTrans = 0.0; + int signPotDiff[2] = {1, -1}; + + for( integer ke = 0; ke < 2; ++ke ) + { + localIndex const er = seri[ke]; + localIndex const esr = sesri[ke]; + localIndex const ei = sei[ke]; + + real64 const pressure = m_pres[er][esr][ei]; // P = P1 || P2 + presGrad[ip] += trans[ke] * pressure; // DPv = T (P1 - P2) + dPresGrad_dTrans += signPotDiff[ke] * pressure; // dDPv/dT = (P1 - P2) + dPresGrad_dP[ip][ke] = trans[ke]; // dDPv/dP = {T , -T} + + real64 const gravD = trans[ke] * m_gravCoef[er][esr][ei]; // D = T g z1 || -T g z2 + real64 const pot = trans[ke] * pressure - densMean[ip] * gravD; // Phi = T P1 - rho T g z1 || -T P2 + rho T g z2 + + gravHead[ip] += densMean[ip] * gravD; // DPg = rho (T g z1 - T g z2) = T rho g (z1 - z2) + dGravHead_dTrans += signPotDiff[ke] * densMean[ip] * m_gravCoef[er][esr][ei]; // dDPg/dT = rho g z1 - rho g z2 = rho g (z1 - z2) + + for( integer i = 0; i < 2; ++i ) + { + dGravHead_dP[ip][i] += dDensMean_dP[ip][i] * gravD; // dDPg/dP = {drho1/dP * T g (z1 - z2) , drho2/dP * T g (z1 - z2)} + } + + if ( m_hasCapPressure ) // check sign convention + { + real64 const capPres = m_phaseCapPressure[er][esr][ei]; // Pc = Pc1 || Pc2 + dCapGrad_dTrans -= signPotDiff[ke] * capPres; // dDPc/dT = (-Pc1 + Pc2) + pot -= trans[ke] * capPres; // Phi = T P1 - rho T g z1 - T Pc1 || -T P2 + rho T g z2 + T Pc2 + capGrad[ip] -= trans[ke] * capPres; // DPc = T (-Pc1 + Pc2) + } + + potScale = fmax( potScale, fabs( pot ) ); // maxPhi = Phi1 > Phi2 ? Phi1 : Phi2 + } + + for( integer ke = 0; ke < 2; ++ke ) + { + dPresGrad_dP[ip][ke] += dTrans_dP[ke] * dPresGrad_dTrans; // dDPv/dP = { T + dT/dP1 * (P1 - P2) , -T + dT/dP2 * (P1 - P2)} + dGravHead_dP[ip][ke] += dTrans_dP[ke] * dGravHead_dTrans; // dDPg/dP = { drho1/dP * T g (z1 - z2) + dT/dP1 * rho g (z1 - z2) , + // drho2/dP * T g (z1 - z2) + dT/dP2 * rho g (z1 - z2) } + if ( m_hasCapPressure ) + { + dCapGrad_dP[ip][ke] += dTrans_dP[ke] * dCapGrad_dTrans; // dDPc/dP = { dT/dP1 * (-Pc1 + Pc2) , dT/dP2 * (-Pc1 + Pc2) } + } + } + + // *** upwinding *** + + // compute potential gradient + real64 const potGrad = presGrad[ip] - gravHead[ip]; // DPhi = T (P1 - P2) - T rho g (z1 - z2) + if ( m_hasCapPressure ) + { + potGrad += capGrad[ip]; // DPhi = T (P1 - P2) - T rho g (z1 - z2) + T (-Pc1 + Pc2) + } + + // compute upwinding tolerance + real64 constexpr upwRelTol = 1e-8; + real64 const upwAbsTol = fmax( potScale * upwRelTol, LvArray::NumericLimits< real64 >::epsilon ); // abstol = maxPhi * tol > eps ? maxPhi * tol : eps + + // decide mobility coefficients - smooth variation in [-upwAbsTol; upwAbsTol] + real64 const alpha = ( potGrad + upwAbsTol ) / ( 2 * upwAbsTol ); // alpha = (DPhi + abstol) / abstol / 2 + + // choose upstream cell + // real64 mobility{}; + // real64 dMob_dP[2]{}; + if( alpha <= 0.0 || alpha >= 1.0 ) // no smoothing needed + { + localIndex const k_up = 1 - localIndex( fmax( fmin( alpha, 1.0 ), 0.0 ) ); // 1 upwind -> k_up = 0 || 2 upwind -> k_up = 1 + + mobility[ip] = m_mob[seri[k_up]][sesri[k_up]][sei[k_up]][ip]; // M = Mupstream + dMob_dP[ip][k_up] = m_dMob_dPres[seri[k_up]][sesri[k_up]][sei[k_up]][ip]; // dM/dP = {dM/dP1 , 0} OR {0 , dM/dP2} + dMob_dS[ip][k_up] = m_dMob_dSat[seri[k_up]][sesri[k_up]][sei[k_up]][ip]; // dM/dS = {dM/dS1 , 0} OR {0 , dM/dS2} + } + else // perform smoothing + { + real64 const mobWeights[2] = { alpha, 1.0 - alpha }; + for( integer ke = 0; ke < 2; ++ke ) + { + mobility[ip] += mobWeights[ke] * m_mob[seri[ke]][sesri[ke]][sei[ke]][ip]; // M = alpha * M1 + (1 - alpha) * M2 + dMob_dP[ip][ke] = mobWeights[ke] * m_dMob_dPres[seri[ke]][sesri[ke]][sei[ke]][ip]; // dM/dP = {alpha * dM1/dP1 , (1 - alpha) * dM2/dP2} + dMob_dS[ip][ke] = mobWeights[ke] * m_dMob_dSat[seri[ke]][sesri[ke]][sei[ke]][ip]; // dM/dP = {alpha * dM1/dS1 , (1 - alpha) * dM2/dS2} + } + } + + // pressure gradient depends on all points in the stencil + for( integer ke = 0; ke < 2; ++ke ) + { + dFlux_dP[ip][ke] += dPresGrad_dP[ip][ke]; // dF/dP = { T + dT/dP1 * (P1 - P2) , + // -T + dT/dP2 * (P1 - P2) } + } + + // gravitational head depends only on the two cells connected (same as mean density) + for( integer ke = 0; ke < 2; ++ke ) + { + dFlux_dP[ip][ke] -= dGravHead_dP[ip][ke]; // dF/dP = { T + dT/dP1 * (P1 - P2) - drho1/dP * T g (z1 - z2) - dT/dP1 * rho g (z1 - z2) , + // -T + dT/dP2 * (P1 - P2) - drho2/dP * T g (z1 - z2) - dT/dP2 * rho g (z1 - z2) } + } + + // capillary pressure contribution + if ( m_hasCapPressure ) + { + for( integer ke = 0; ke < 2; ++ke ) + { + dFlux_dP[ip][ke] += dCapGrad_dP[ip][ke]; // dF/dP = { T + dT/dP1 * (P1 - P2) - drho1/dP * T g (z1 - z2) - dT/dP1 * rho g (z1 - z2) + dT/dP1 * (-Pc1 + Pc2) , + // -T + dT/dP2 * (P1 - P2) - drho2/dP * T g (z1 - z2) - dT/dP2 * rho g (z1 - z2) + dT/dP2 * (-Pc1 + Pc2) } + } + } + + // compute the flux and derivatives using upstream cell mobility + fluxVal[ip] = mobility[ip] * potGrad; // F = M * DPhi + + for( integer ke = 0; ke < 2; ++ke ) + { + dFlux_dP[ip][ke] *= mobility[ip]; // dF/dP = { M [ T + dT/dP1 * (P1 - P2) - drho1/dP * T g (z1 - z2) - dT/dP1 * rho g (z1 - z2) + dT/dP1 * (-Pc1 + Pc2)] , + // M [-T + dT/dP2 * (P1 - P2) - drho2/dP * T g (z1 - z2) - dT/dP2 * rho g (z1 - z2) + dT/dP2 * (-Pc1 + Pc2)] } + } + + // add contribution from upstream cell mobility derivatives + for( integer ke = 0; ke < 2; ++ke ) + { + dFlux_dP[ip][ke] += dMob_dP[ip][ke] * potGrad; // dF/dP = { M [ T + dT/dP1 * (P1 - P2) - drho1/dP * T g (z1 - z2) - dT/dP1 * rho g (z1 - z2) + dT/dP1 * (-Pc1 + Pc2)] + dM/dP1 * DPhi , + // M [-T + dT/dP2 * (P1 - P2) - drho2/dP * T g (z1 - z2) - dT/dP2 * rho g (z1 - z2) + dT/dP2 * (-Pc1 + Pc2)] + dM/dP2 * DPhi } + + dFlux_dS[ip][ke] += dMob_dS[ip][ke] * potGrad; // dF/dS = { dM/dS1 * DPhi , dM/dS2 * DPhi } + } + + // populate local flux vector and derivatives + stack.localFlux[k[0]*numEqn + ip] += m_dt * fluxVal[ip]; + stack.localFlux[k[1]*numEqn + ip] -= m_dt * fluxVal[ip]; + + for( integer ke = 0; ke < 2; ++ke ) + { + // pressure + localIndex const localDofIndexPres = k[ke] * numDof; + stack.localFluxJacobian[k[0]*numEqn + ip][localDofIndexPres] += m_dt * dFlux_dP[ip][ke]; + stack.localFluxJacobian[k[1]*numEqn + ip][localDofIndexPres] -= m_dt * dFlux_dP[ip][ke]; + + // saturation (hard-coded for 2-phase currently) + localIndex const localDofIndexSat = k[ke] * numDof + 1; + stack.localFluxJacobian[k[0]*numEqn + ip][localDofIndexSat] += m_dt * dFlux_dS[ip][ke]; + stack.localFluxJacobian[k[1]*numEqn + ip][localDofIndexSat] -= m_dt * dFlux_dS[ip][ke]; + } + + // Customize the kernel with this lambda + kernelOp( k, seri, sesri, sei, connectionIndex, alpha, mobility, potGrad, fluxVal, dFlux_dP, dFlux_dS ); // Not sure what this does + + } // loop over phases + + connectionIndex++; + } + } // loop over connection elements + } + + /** + * @brief Performs the complete phase for the kernel. + * @param[in] iconn the connection index + * @param[inout] stack the stack variables + */ + template< typename FUNC = multiPhaseBaseKernels::NoOpFunc > + GEOS_HOST_DEVICE + void complete( localIndex const iconn, + StackVariables & stack, + FUNC && kernelOp = singlePhaseBaseKernels::NoOpFunc{} ) const + { + // add contribution to residual and jacobian into: + // - the mass balance equation + // note that numDof includes derivatives wrt temperature if this class is derived in ThermalKernels + for( integer i = 0; i < stack.numFluxElems; ++i ) + { + if( m_ghostRank[m_seri( iconn, i )][m_sesri( iconn, i )][m_sei( iconn, i )] < 0 ) + { + globalIndex const globalRow = m_dofNumber[m_seri( iconn, i )][m_sesri( iconn, i )][m_sei( iconn, i )]; + localIndex const localRow = LvArray::integerConversion< localIndex >( globalRow - m_rankOffset ); + GEOS_ASSERT_GE( localRow, 0 ); + GEOS_ASSERT_GT( m_localMatrix.numRows(), localRow ); + + RAJA::atomicAdd( parallelDeviceAtomic{}, &m_localRhs[localRow], stack.localFlux[i * numEqn] ); + m_localMatrix.addToRowBinarySearchUnsorted< parallelDeviceAtomic >( localRow, + stack.dofColIndices.data(), + stack.localFluxJacobian[i * numEqn].dataIfContiguous(), // fix numbering + stack.stencilSize * numDof ); + + // call the lambda to assemble additional terms, such as thermal terms + kernelOp( i, localRow ); + } + } + } + + /** + * @brief Performs the kernel launch + * @tparam POLICY the policy used in the RAJA kernels + * @tparam KERNEL_TYPE the kernel type + * @param[in] numConnections the number of connections + * @param[inout] kernelComponent the kernel component providing access to setup/compute/complete functions and stack variables + */ + template< typename POLICY, typename KERNEL_TYPE > + static void + launch( localIndex const numConnections, + KERNEL_TYPE const & kernelComponent ) + { + GEOS_MARK_FUNCTION; + + forAll< POLICY >( numConnections, [=] GEOS_HOST_DEVICE ( localIndex const iconn ) + { + typename KERNEL_TYPE::StackVariables stack( kernelComponent.stencilSize( iconn ), + kernelComponent.numPointsInFlux( iconn ) ); + + kernelComponent.setup( iconn, stack ); + kernelComponent.computeFlux( iconn, stack ); + kernelComponent.complete( iconn, stack ); + } ); + } + +protected: + + // Stencil information + + /// Reference to the stencil wrapper + STENCILWRAPPER const m_stencilWrapper; + + /// Connection to element maps + typename STENCILWRAPPER::IndexContainerViewConstType const m_seri; + typename STENCILWRAPPER::IndexContainerViewConstType const m_sesri; + typename STENCILWRAPPER::IndexContainerViewConstType const m_sei; +}; + + +/****************************************** */ /** * @class FaceBasedAssemblyKernelFactory @@ -209,8 +692,11 @@ class FaceBasedAssemblyKernelFactory */ template< typename POLICY, typename STENCILWRAPPER > static void - createAndLaunch( globalIndex const rankOffset, + createAndLaunch( integer const numPhases, + globalIndex const rankOffset, // add capillary pressure and total mass equation flags string const & dofKey, + integer const hasCapPressure, + integer const useTotalMassEquation, string const & solverName, ElementRegionManager const & elemManager, STENCILWRAPPER const & stencilWrapper, @@ -218,21 +704,22 @@ class FaceBasedAssemblyKernelFactory CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) { - integer constexpr NUM_EQN = 1; - integer constexpr NUM_DOF = 1; + integer constexpr NUM_EQN = 2; + integer constexpr NUM_DOF = 2; ElementRegionManager::ElementViewAccessor< arrayView1d< globalIndex const > > dofNumberAccessor = elemManager.constructArrayViewAccessor< globalIndex, 1 >( dofKey ); dofNumberAccessor.setName( solverName + "/accessors/" + dofKey ); using kernelType = FaceBasedAssemblyKernel< NUM_EQN, NUM_DOF, STENCILWRAPPER >; - typename kernelType::SinglePhaseFlowAccessors flowAccessors( elemManager, solverName ); - typename kernelType::SinglePhaseFluidAccessors fluidAccessors( elemManager, solverName ); + typename kernelType::ImmiscibleMultiPhaseFlowAccessors flowAccessors( elemManager, solverName ); + typename kernelType::ImmiscibleMultiPhaseFluidAccessors fluidAccessors( elemManager, solverName ); + typename kernelType::CapPressureAccessors capPressureAccessors( elemManager, solverName ); typename kernelType::PermeabilityAccessors permAccessors( elemManager, solverName ); - kernelType kernel( rankOffset, stencilWrapper, dofNumberAccessor, - flowAccessors, fluidAccessors, permAccessors, - dt, localMatrix, localRhs ); + kernelType kernel( numPhases, rankOffset, stencilWrapper, dofNumberAccessor, + flowAccessors, fluidAccessors, capPressureAccessors, permAccessors, + dt, localMatrix, localRhs, hasCapPressure, useTotalMassEquation ); kernelType::template launch< POLICY >( stencilWrapper.size(), kernel ); } }; @@ -243,4 +730,6 @@ class FaceBasedAssemblyKernelFactory } // namesace immiscible multiphasekernels -} // namespace geos \ No newline at end of file +} // namespace geos + +#endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_MULTIPHASEKERNELS_HPP \ No newline at end of file From 1b190a89a9da28bffc84249c16b740d7da1f0ac5 Mon Sep 17 00:00:00 2001 From: rpiazza87 Date: Mon, 12 Aug 2024 14:40:59 -0700 Subject: [PATCH 013/104] x --- .../fluidFlow/ImmiscibleMultiphaseKernels.hpp | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp index c6f1a05c868..ec0adf08319 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp @@ -360,7 +360,7 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase * @param[inout] stack the stack variables * @param[in] NoOpFunc the function used to customize the computation of the flux */ - template< typename FUNC = multiPhaseBaseKernels::NoOpFunc > + template< typename FUNC = singlePhaseBaseKernels::NoOpFunc > // should change to multiphase GEOS_HOST_DEVICE void computeFlux( localIndex const iconn, StackVariables & stack, @@ -599,7 +599,7 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase * @param[in] iconn the connection index * @param[inout] stack the stack variables */ - template< typename FUNC = multiPhaseBaseKernels::NoOpFunc > + template< typename FUNC = singlePhaseBaseKernels::NoOpFunc > // should change to multiphase GEOS_HOST_DEVICE void complete( localIndex const iconn, StackVariables & stack, @@ -615,13 +615,18 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase globalIndex const globalRow = m_dofNumber[m_seri( iconn, i )][m_sesri( iconn, i )][m_sei( iconn, i )]; localIndex const localRow = LvArray::integerConversion< localIndex >( globalRow - m_rankOffset ); GEOS_ASSERT_GE( localRow, 0 ); - GEOS_ASSERT_GT( m_localMatrix.numRows(), localRow ); - - RAJA::atomicAdd( parallelDeviceAtomic{}, &m_localRhs[localRow], stack.localFlux[i * numEqn] ); - m_localMatrix.addToRowBinarySearchUnsorted< parallelDeviceAtomic >( localRow, - stack.dofColIndices.data(), - stack.localFluxJacobian[i * numEqn].dataIfContiguous(), // fix numbering - stack.stencilSize * numDof ); + GEOS_ASSERT_GT( m_localMatrix.numRows(), localRow + numEqn); + + for( integer ic = 0; ic < numEqn; ++ic ) + { + RAJA::atomicAdd( parallelDeviceAtomic{}, &m_localRhs[localRow + ic], + stack.localFlux[i * numEqn + ic] ); + m_localMatrix.addToRowBinarySearchUnsorted< parallelDeviceAtomic > + ( localRow + ic, + stack.dofColIndices.data(), + stack.localFluxJacobian[i * numEqn + ic].dataIfContiguous(), + stack.stencilSize * numDof ); + } // call the lambda to assemble additional terms, such as thermal terms kernelOp( i, localRow ); From 33c6c0f0abfc2e1e95326f564c189eaf8cfdc852 Mon Sep 17 00:00:00 2001 From: rpiazza87 Date: Mon, 12 Aug 2024 14:53:06 -0700 Subject: [PATCH 014/104] x --- .../fluidFlow/ImmiscibleMultiphaseFlow.cpp | 31 +++---------------- .../fluidFlow/ImmiscibleMultiphaseFlow.hpp | 3 ++ 2 files changed, 7 insertions(+), 27 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index 507ab656c42..d0a6f3d80af 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -626,8 +626,11 @@ void ImmiscibleMultiphaseFlow::assembleFluxTerms( real64 const dt, { fluxApprox.forAllStencils( mesh, [&]( auto & stencil ) { - FaceBasedAssemblyKernelFactory::createAndLaunch< parallelDevicePolicy<> >( dofManager.rankOffset(), + FaceBasedAssemblyKernelFactory::createAndLaunch< parallelDevicePolicy<> >( m_numPhases, + dofManager.rankOffset(), dofKey, + m_hasCapPressure, + m_useTotalMassEquation, getName(), mesh.getElemManager(), stencilWrapper, @@ -639,32 +642,6 @@ void ImmiscibleMultiphaseFlow::assembleFluxTerms( real64 const dt, } -void ImmiscibleMultiphaseFlow::setupDofs( DomainPartition const & domain, - DofManager & dofManager ) const -{ - GEOS_UNUSED_VAR(domain, dofManager); - //// add a field for the cell-centered degrees of freedom - //dofManager.addField( viewKeyStruct::elemDofFieldString(), - // FieldLocation::Elem, - // m_numDofPerCell, - // getMeshTargets() ); - - //// this call with instruct GEOS to reorder the dof numbers - //dofManager.setLocalReorderingType( viewKeyStruct::elemDofFieldString(), - // DofManager::LocalReorderingType::ReverseCutHillMcKee ); - - //// for the volume balance equation, disable global coupling - //// this equation is purely local (not coupled to neighbors or other physics) - //dofManager.disableGlobalCouplingForEquation( viewKeyStruct::elemDofFieldString(), - // m_numComponents ); - - - //NumericalMethodsManager const & numericalMethodManager = domain.getNumericalMethodManager(); - //FiniteVolumeManager const & fvManager = numericalMethodManager.getFiniteVolumeManager(); - //FluxApproximationBase const & fluxApprox = fvManager.getFluxApproximation( m_discretizationName ); - //dofManager.addCoupling( viewKeyStruct::elemDofFieldString(), fluxApprox ); -} - // Ryan: Looks like this will need to be overwritten as well... // I have left the CompositionalMultiphaseFVM implementation for reference void ImmiscibleMultiphaseFlow::setupDofs( DomainPartition const & domain, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp index 34d603abadb..fec9c186808 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp @@ -239,6 +239,9 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase /// flag to determine whether or not to apply capillary pressure integer m_hasCapPressure; + /// flag to determine whether or not to use total mass formulation + integer m_useTotalMassEquation; + struct viewKeyStruct : public FlowSolverBase::viewKeyStruct { static constexpr char const * capPressureNamesString() { return "capPressureNames"; } From cc35e5972463152f7d319258dda879cf038c30cb Mon Sep 17 00:00:00 2001 From: Ammara-14 Date: Fri, 2 Aug 2024 12:06:38 -0700 Subject: [PATCH 015/104] add temperature to input file --- src/coreComponents/LvArray | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreComponents/LvArray b/src/coreComponents/LvArray index e7bf1096d57..ec26694afbc 160000 --- a/src/coreComponents/LvArray +++ b/src/coreComponents/LvArray @@ -1 +1 @@ -Subproject commit e7bf1096d57558be720f177141c40e4ab69b3f5e +Subproject commit ec26694afbcdd137533b6f04ce8f8c264ff8c1fb From 297669c30095604ef48899376c9be107a46765b1 Mon Sep 17 00:00:00 2001 From: Ammara-14 Date: Thu, 8 Aug 2024 15:59:21 -0700 Subject: [PATCH 016/104] Initial implementation of assembleAccumulationTerm --- .../fluidFlow/ImmiscibleMultiphaseFlow.cpp | 199 +++++++++++------- .../ImmiscibleMultiphaseFlowFields.hpp | 11 +- 2 files changed, 128 insertions(+), 82 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index d0a6f3d80af..db70db94679 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -48,82 +48,23 @@ using namespace dataRepository; using namespace constitutive; using namespace fields::immiscibleMultiphaseFlow; -// Fluid model for isothermal T = 175 oC -real64 co2_viscosity(real64 P) -{ - P = P / 1000000.0; // check whether GEOS uses Pa or MPa - return ( -1.5596 * pow(10, -10) * pow(P, 3) + 1.94571 * pow(10, -8) * pow(P, 2) + 6.77304 * pow(10, -8) * P + 0.0000214166); // [Pa.s] -} - -real64 co2_dviscosity(real64 P) -{ - P = P / 1000000.0; // check whether GEOS uses Pa or MPa - return ( -4.6788 * pow(10, -10) * pow(P, 2) + 3.89142 * pow(10, -8) * P + 6.77304 * pow(10, -8)); // [Pa.s/MPa] -} - -real64 co2_density(real64 P) -{ - P = P / 1000000.0; // check whether GEOS uses Pa or MPa - return ( -0.0000126691 * pow(P, 3) - 0.118131 * pow(P, 2) + 19.6211 * P - 52.0635 ); // [kg/m3] -} - -real64 co2_ddensity(real64 P) -{ - P = P / 1000000.0; // check whether GEOS uses Pa or MPa - return ( -0.0000380073 * pow(P, 2) - 0.236262 * P + 19.6211 ); // [kg/m3.MPa] -} - -real64 water_viscosity(real64 P) -{ - return ( 0.000164 ); // [Pa.s] -} - -real64 water_dviscosity(real64 P) -{ - return ( 0.0 ); // [Pa.s/MPa] -} - -real64 water_density(real64 P) -{ - P = P / 1000000.0; // check whether GEOS uses Pa or MPa - return ( 0.55125 * P + 893.06044); // [kg/m3] +real64 computeDensityL ( real64 P ) { + return (1.0e-6 * (P * P)); } -real64 water_ddensity(real64 P) -{ - return ( 0.55125 ); // [kg/m3.MPa] +real64 computedDensitydPL ( real64 P ) { + return (1.0e-6 * 2.0 * (P)); } -// Rock-Fluid model -real64 co2_relperm(real64 S) -{ - return ( pow(1 - S, 2) ); // [-] -} - -real64 co2_drelperm(real64 S) -{ - return ( 2.0 * (1 - S) ); // [-] +real64 computeDensityV ( real64 P ) { + return (1.0e-8 * (P * P)); } -real64 water_relperm(real64 S) -{ - return ( pow(S, 6) ); // [-] -} - -real64 water_drelperm(real64 S) -{ - return ( 6.0 * pow(S, 5) ); // [-] +real64 computedDensitydPV ( real64 P ) { + return (1.0e-8 * 2.0 * (P)); } -real64 co2_cappress(real64 S) -{ - return ( 0.00049309 * pow(S, -2.34806) ); // [MPa] check whether GEOS uses Pa or MPa -} -real64 co2_dcappress(real64 S) -{ - return ( -0.00021 * pow(S, -1.34806) ); // [MPa] check whether GEOS uses Pa or MPa -} ImmiscibleMultiphaseFlow::ImmiscibleMultiphaseFlow( const string & name, Group * const parent ) @@ -580,6 +521,9 @@ void ImmiscibleMultiphaseFlow::assembleSystem( real64 const GEOS_UNUSED_PARAM( t localRhs ); } + +// The assembleAccumulationTerm below is Added by Ammar. + void ImmiscibleMultiphaseFlow::assembleAccumulationTerm( DomainPartition & domain, DofManager const & dofManager, CRSMatrixView< real64, globalIndex const > const & localMatrix, @@ -587,21 +531,114 @@ void ImmiscibleMultiphaseFlow::assembleAccumulationTerm( DomainPartition & domai { GEOS_MARK_FUNCTION; + // I need to pass this: ObjectManagerBase & dataGroup + // GEOS_UNUSED_VAR( domain, dofManager, localMatrix, localRhs ); + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel const & mesh, + arrayView1d< string const > const & regionNames ) + { + mesh.getElemManager().forElementSubRegions( regionNames, + [&]( localIndex const, + ElementSubRegionBase const & subRegion ) + { + string const dofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); + string const & solidName = subRegion.getReference< string >( viewKeyStruct::solidNamesString() ); + + // MultiFluidBase const & fluid = getConstitutiveModel< MultiFluidBase >( subRegion, fluidName ); + CoupledSolidBase const & solid = getConstitutiveModel< CoupledSolidBase >( subRegion, solidName ); + + //arrayView1d< real64 const > const pres = dataGroup.getField< fields::flow::pressure >(); + integer const m_numofPhases = 2; + globalIndex const m_rankOffset = dofManager.rankOffset(); + arrayView1d< globalIndex const > const m_dofNumber = subRegion.getReference< array1d< globalIndex > >( dofKey ); + arrayView1d< integer const > const m_elemGhostRank= subRegion.ghostRank(); + arrayView1d< real64 const > const m_volume = subRegion.getElementVolume(); + arrayView2d< real64 const > const m_porosity = solid.getPorosity(); + arrayView2d< real64 const > const m_dPoro_dPres = solid.getDporosity_dPressure(); + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const m_phaseVolFrac= subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); + arrayView3d< real64 const, immiscibleFlow::USD_PHASE_DS > const m_dPhaseVolFrac = subRegion.template getField< fields::immiscibleMultiphaseFlow::dPhaseVolumeFraction >(); + //arrayView3d< real64 const, immiscibleFlow::USD_PHASE > m_phaseDens = fluid.phaseDensity(); + //arrayView4d< real64 const, immiscibleFlow::USD_PHASE_DS > m_dPhaseDens = fluid.dPhaseDensity(); + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const m_phaseMass_n = subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseMass_n >(); + CRSMatrixView< real64, globalIndex const > m_localMatrix_2 = localMatrix; + arrayView1d< real64 > m_localRhs = localRhs; + //BitFlags< ElementBasedAssemblyKernelFlags > m_kernelFlags = kernelFlags; + GEOS_MARK_FUNCTION; + + integer const numElems = subRegion.size(); + forAll< parallelDevicePolicy<> >( numElems, [=] GEOS_HOST_DEVICE ( localIndex const ei ) + { + if( m_elemGhostRank( ei ) >= 0 ) + { + return; + } + + // setup + globalIndex dofIndices[2]{}; + real64 localResidual[2]{}; + real64 localJacobian[2][2]{}; + + real64 const poreVolume = m_volume[ei] * m_porosity[ei][0]; + real64 const dPoreVolume_dPres = m_volume[ei] * m_dPoro_dPres[ei][0]; + + localIndex localRow = m_dofNumber[ei] - m_rankOffset; + + for( integer idof = 0; idof < m_numDofPerCell; ++idof ) + { + dofIndices[idof] = m_dofNumber[ei] + idof; + } + + // compute accumulation + + + for( integer ip = 0; ip < m_numofPhases; ++ip ) + { + + real64 const dummyPressure = 1.0e6; + + real64 m_phaseDens = computeDensityV ( dummyPressure ); + real64 dPhaseDens = computedDensitydPV ( dummyPressure ); + + if( ip == 1) + { + m_phaseDens = computeDensityL ( dummyPressure ); + dPhaseDens = computedDensitydPL ( dummyPressure ); + } + + real64 const phaseMass = poreVolume * m_phaseVolFrac[ei][ip] * m_phaseDens; + real64 const phaseMass_n = m_phaseMass_n[ei][ip]; + + localResidual[ip] += phaseMass - phaseMass_n; + + real64 const dPhaseMass_dP = dPoreVolume_dPres * m_phaseVolFrac[ei][ip] * m_phaseDens + + poreVolume * m_phaseVolFrac[ei][ip] * dPhaseDens; + localJacobian[ip][0] += dPhaseMass_dP; + + real64 const dPhaseMass_dS = poreVolume * m_phaseDens; + // Ammar:- not quite clear on how to fill jacobian for dRdS?? + localJacobian[ip][ip + 1] += dPhaseMass_dS; + } + + // complete + + integer const numRows = m_numofPhases + 1; + + for( integer i = 0; i < numRows; ++i ) + { + m_localRhs[localRow + i] += localResidual[i]; + m_localMatrix_2.addToRow< serialAtomic >( localRow + i, + dofIndices, + localJacobian[i], + m_numDofPerCell ); + } + + } ); + + } ); + } ); + - GEOS_UNUSED_VAR( domain, dofManager, localMatrix, localRhs ); - - // forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - // MeshLevel const & mesh, - // arrayView1d< string const > const & regionNames ) - // { - // mesh.getElemManager().forElementSubRegions( regionNames, - // [&]( localIndex const, - // ElementSubRegionBase const & subRegion ) - // { - // string const dofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); - // string const & solidName = subRegion.getReference< string >( viewKeyStruct::solidNamesString() ); - // } ); - // } ); } void ImmiscibleMultiphaseFlow::assembleFluxTerms( real64 const dt, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp index 3cb4fc7a6df..796b2f347e0 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp @@ -77,13 +77,22 @@ DECLARE_FIELD( phaseMobility, WRITE_AND_READ, "Phase mobility" ); +DECLARE_FIELD( dPhaseVolumeFraction, + "dPhaseVolumeFraction", + array3dLayoutPhase_dS, + 0, + NOPLOT, + NO_WRITE, + "Derivative of phase volume fraction with respect to pressure, temperature, global component density" ); + DECLARE_FIELD( dPhaseMobility, "dPhaseMobility", array3dLayoutPhase_dS, 0, NOPLOT, NO_WRITE, - "Derivative of phase volume fraction with respect to pressure, temperature, global component density" ); + "Derivative of phase mobility with respect to pressure, temperature, global component density" ); + DECLARE_FIELD( phaseOutflux, "phaseOutflux", From dc73aa27805f605803f7fc99727688a4d8bc23ce Mon Sep 17 00:00:00 2001 From: Ammara-14 Date: Tue, 13 Aug 2024 18:49:51 -0700 Subject: [PATCH 017/104] Few fixes in the accumulation term assumbly and added fields for the phase properties reflecting the comments from the meeting on Aug-13-2024 --- .../fluidFlow/ImmiscibleMultiphaseFlow.cpp | 89 ++++++++++--------- .../ImmiscibleMultiphaseFlowFields.hpp | 39 +++++++- 2 files changed, 84 insertions(+), 44 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index db70db94679..e3766d9ea03 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -522,7 +522,7 @@ void ImmiscibleMultiphaseFlow::assembleSystem( real64 const GEOS_UNUSED_PARAM( t } -// The assembleAccumulationTerm below is Added by Ammar. +// This part of the code "assembleAccumulationTerm" is added by Ammar along with the comments. void ImmiscibleMultiphaseFlow::assembleAccumulationTerm( DomainPartition & domain, DofManager const & dofManager, @@ -531,8 +531,6 @@ void ImmiscibleMultiphaseFlow::assembleAccumulationTerm( DomainPartition & domai { GEOS_MARK_FUNCTION; - // I need to pass this: ObjectManagerBase & dataGroup - // GEOS_UNUSED_VAR( domain, dofManager, localMatrix, localRhs ); forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, MeshLevel const & mesh, @@ -545,31 +543,35 @@ void ImmiscibleMultiphaseFlow::assembleAccumulationTerm( DomainPartition & domai string const dofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); string const & solidName = subRegion.getReference< string >( viewKeyStruct::solidNamesString() ); + // The line below needs to be used once we have a fluid model // MultiFluidBase const & fluid = getConstitutiveModel< MultiFluidBase >( subRegion, fluidName ); CoupledSolidBase const & solid = getConstitutiveModel< CoupledSolidBase >( subRegion, solidName ); - //arrayView1d< real64 const > const pres = dataGroup.getField< fields::flow::pressure >(); - integer const m_numofPhases = 2; - globalIndex const m_rankOffset = dofManager.rankOffset(); - arrayView1d< globalIndex const > const m_dofNumber = subRegion.getReference< array1d< globalIndex > >( dofKey ); - arrayView1d< integer const > const m_elemGhostRank= subRegion.ghostRank(); - arrayView1d< real64 const > const m_volume = subRegion.getElementVolume(); - arrayView2d< real64 const > const m_porosity = solid.getPorosity(); - arrayView2d< real64 const > const m_dPoro_dPres = solid.getDporosity_dPressure(); - arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const m_phaseVolFrac= subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); - arrayView3d< real64 const, immiscibleFlow::USD_PHASE_DS > const m_dPhaseVolFrac = subRegion.template getField< fields::immiscibleMultiphaseFlow::dPhaseVolumeFraction >(); + arrayView1d< real64 const > const pres = subRegion.getField< fields::flow::pressure >(); + integer const numofPhases = 2; + globalIndex const rankOffset = dofManager.rankOffset(); + arrayView1d< globalIndex const > const dofNumber = subRegion.getReference< array1d< globalIndex > >( dofKey ); + arrayView1d< integer const > const elemGhostRank= subRegion.ghostRank(); + arrayView1d< real64 const > const volume = subRegion.getElementVolume(); + arrayView2d< real64 const > const porosity = solid.getPorosity(); + arrayView2d< real64 const > const dPoro_dPres = solid.getDporosity_dPressure(); + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac= subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); + // The two lines below need to be used once we have a fluid model //arrayView3d< real64 const, immiscibleFlow::USD_PHASE > m_phaseDens = fluid.phaseDensity(); //arrayView4d< real64 const, immiscibleFlow::USD_PHASE_DS > m_dPhaseDens = fluid.dPhaseDensity(); - arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const m_phaseMass_n = subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseMass_n >(); - CRSMatrixView< real64, globalIndex const > m_localMatrix_2 = localMatrix; - arrayView1d< real64 > m_localRhs = localRhs; + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > phaseDens = subRegion.getField< fields::immiscibleMultiphaseFlow::phaseDensity>(); + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > dPhaseDens = subRegion.getField< fields::immiscibleMultiphaseFlow::dPhaseDensity>(); + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const PhaseMass_n = subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseMass_n >(); + + // The line below is to be used if we want to use the total mass flux formulation //BitFlags< ElementBasedAssemblyKernelFlags > m_kernelFlags = kernelFlags; GEOS_MARK_FUNCTION; integer const numElems = subRegion.size(); - forAll< parallelDevicePolicy<> >( numElems, [=] GEOS_HOST_DEVICE ( localIndex const ei ) + forAll< parallelDevicePolicy<> >( + numElems, [=] GEOS_HOST_DEVICE ( localIndex const ei ) { - if( m_elemGhostRank( ei ) >= 0 ) + if( elemGhostRank( ei ) >= 0 ) { return; } @@ -579,58 +581,59 @@ void ImmiscibleMultiphaseFlow::assembleAccumulationTerm( DomainPartition & domai real64 localResidual[2]{}; real64 localJacobian[2][2]{}; - real64 const poreVolume = m_volume[ei] * m_porosity[ei][0]; - real64 const dPoreVolume_dPres = m_volume[ei] * m_dPoro_dPres[ei][0]; + real64 const poreVolume = volume[ei] * porosity[ei][0]; + real64 const dPoreVolume_dPres = volume[ei] * dPoro_dPres[ei][0]; - localIndex localRow = m_dofNumber[ei] - m_rankOffset; + localIndex localRow = dofNumber[ei] - rankOffset; - for( integer idof = 0; idof < m_numDofPerCell; ++idof ) + for( integer idof = 0; idof < 2; ++idof ) { - dofIndices[idof] = m_dofNumber[ei] + idof; + dofIndices[idof] = dofNumber[ei] + idof; } // compute accumulation - for( integer ip = 0; ip < m_numofPhases; ++ip ) + for( integer ip = 0; ip < numofPhases; ++ip ) { - real64 const dummyPressure = 1.0e6; + // The few lines of code below are to be used if we want to use free functions for the phase density (to test the derivatives) + // real64 const pressure = pres[ei]; - real64 m_phaseDens = computeDensityV ( dummyPressure ); - real64 dPhaseDens = computedDensitydPV ( dummyPressure ); + // real64 phaseDens = computeDensityV ( pressure ); + // real64 dPhaseDens = computedDensitydPV ( pressure ); - if( ip == 1) - { - m_phaseDens = computeDensityL ( dummyPressure ); - dPhaseDens = computedDensitydPL ( dummyPressure ); - } + // if( ip == 1) + // { + // phaseDens = computeDensityL ( pressure ); + // dPhaseDens = computedDensitydPL ( pressure ); + //} - real64 const phaseMass = poreVolume * m_phaseVolFrac[ei][ip] * m_phaseDens; - real64 const phaseMass_n = m_phaseMass_n[ei][ip]; + real64 const phaseMass = poreVolume * phaseVolFrac[ei][ip] * phaseDens[ei][ip]; + real64 const phaseMass_n = PhaseMass_n[ei][ip]; localResidual[ip] += phaseMass - phaseMass_n; - real64 const dPhaseMass_dP = dPoreVolume_dPres * m_phaseVolFrac[ei][ip] * m_phaseDens - + poreVolume * m_phaseVolFrac[ei][ip] * dPhaseDens; + real64 const dPhaseMass_dP = dPoreVolume_dPres * phaseVolFrac[ei][ip] * phaseDens[ei][ip] + + poreVolume * phaseVolFrac[ei][ip] * dPhaseDens[ei][ip]; localJacobian[ip][0] += dPhaseMass_dP; - real64 const dPhaseMass_dS = poreVolume * m_phaseDens; - // Ammar:- not quite clear on how to fill jacobian for dRdS?? - localJacobian[ip][ip + 1] += dPhaseMass_dS; + real64 const dPhaseMass_dS = poreVolume * phaseDens[ei][ip]; + + localJacobian[ip][1] += dPhaseMass_dS; } // complete - integer const numRows = m_numofPhases + 1; + integer const numRows = numofPhases + 1; for( integer i = 0; i < numRows; ++i ) { - m_localRhs[localRow + i] += localResidual[i]; - m_localMatrix_2.addToRow< serialAtomic >( localRow + i, + localRhs[localRow + i] += localResidual[i]; + localMatrix.addToRow< serialAtomic >( localRow + i, dofIndices, localJacobian[i], - m_numDofPerCell ); + 2); } } ); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp index 796b2f347e0..dcf303e6eca 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp @@ -109,10 +109,47 @@ DECLARE_FIELD( phaseCFLNumber, LEVEL_0, NO_WRITE, "Phase CFL number" ); -} +DECLARE_FIELD( phaseDensity, + "phaseDensity", + array2dLayoutPhase, + 1000.0, + NOPLOT, + WRITE_AND_READ, + "Phase density" ); + + +DECLARE_FIELD( dPhaseDensity, + "dPhaseDensity", + array2dLayoutPhase, + 0.0, + NOPLOT, + WRITE_AND_READ, + "Phase density derivative with respect to P" ); + +DECLARE_FIELD( phaseViscosity, + "phaseViscosity", + array2dLayoutPhase, + 1.0e-4, + NOPLOT, + WRITE_AND_READ, + "Phase density" ); + + +DECLARE_FIELD( dPhaseViscosity, + "dPhaseViscosity", + array2dLayoutPhase, + 0.0, + NOPLOT, + WRITE_AND_READ, + "Phase density derivative with respect to P" ); + + +} } } + + #endif // GEOS_PHYSICSSOLVERS_FLUIDFLOW_IMMISCIBLEMULTIPHASEFLOWFIELDS_HPP_ From f6d14dc0ea2152eb5c66940dee8d270b4ffadf51 Mon Sep 17 00:00:00 2001 From: rpiazza87 Date: Mon, 19 Aug 2024 16:13:52 -0700 Subject: [PATCH 018/104] update datalayout --- src/coreComponents/common/DataLayouts.hpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/coreComponents/common/DataLayouts.hpp b/src/coreComponents/common/DataLayouts.hpp index d1c892754ee..40b64ada6df 100644 --- a/src/coreComponents/common/DataLayouts.hpp +++ b/src/coreComponents/common/DataLayouts.hpp @@ -232,6 +232,15 @@ static constexpr int USD_PHASE = LvArray::typeManipulation::getStrideOneDimensio /// Phase property compositional derivative unit stride dimension static constexpr int USD_PHASE_DS = LvArray::typeManipulation::getStrideOneDimension( LAYOUT_PHASE_DS{} ); +/// indices of pressure and saturation derivatives +struct DerivativeOffset +{ + /// index of derivative wrt pressure + static integer constexpr dP = 0; + /// index of first derivative wrt compositions + static integer constexpr dS = 1; +}; + } // namespace immiscibleFlow namespace compflow From 477d87e35caa2f380010a2ea73de0b0d53a840d2 Mon Sep 17 00:00:00 2001 From: rpiazza87 Date: Mon, 19 Aug 2024 16:23:35 -0700 Subject: [PATCH 019/104] updated solver files --- .../physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp | 5 +---- .../physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index e3766d9ea03..a5a5c3491a2 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -22,8 +22,6 @@ #include "FlowSolverBaseFields.hpp" #include "physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp" #include "physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp" -#include "physicsSolvers/fluidFlow/IsothermalCompositionalMultiphaseBaseKernels.hpp" -#include "physicsSolvers/fluidFlow/IsothermalCompositionalMultiphaseFVMKernels.hpp" #include "constitutive/ConstitutiveManager.hpp" #include "constitutive/capillaryPressure/CapillaryPressureFields.hpp" @@ -678,8 +676,7 @@ void ImmiscibleMultiphaseFlow::assembleFluxTerms( real64 const dt, localMatrix.toViewConstSizes(), localRhs.toView() ); } ); - } ); - + } ); } // Ryan: Looks like this will need to be overwritten as well... diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp index fec9c186808..7cf3a8c1b17 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp @@ -239,7 +239,7 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase /// flag to determine whether or not to apply capillary pressure integer m_hasCapPressure; - /// flag to determine whether or not to use total mass formulation + /// flag to determine whether or not to use total velocity formulation integer m_useTotalMassEquation; struct viewKeyStruct : public FlowSolverBase::viewKeyStruct From 05261648ade90fc46a75a0eaebe4eb340002c032 Mon Sep 17 00:00:00 2001 From: rpiazza87 Date: Mon, 19 Aug 2024 16:29:08 -0700 Subject: [PATCH 020/104] update kernel --- .../fluidFlow/ImmiscibleMultiphaseKernels.hpp | 136 ++++++++---------- 1 file changed, 60 insertions(+), 76 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp index ec0adf08319..310f7e34c07 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp @@ -24,17 +24,19 @@ #include "common/GEOS_RAJA_Interface.hpp" #include "constitutive/fluid/singlefluid/SingleFluidBase.hpp" // get correct fluid model #include "constitutive/fluid/singlefluid/SingleFluidFields.hpp" -#include "constitutive/fluid/singlefluid/SlurryFluidBase.hpp" -#include "constitutive/fluid/singlefluid/SlurryFluidFields.hpp" +#include "constitutive/capillaryPressure/CapillaryPressureFields.hpp" +#include "constitutive/capillaryPressure/CapillaryPressureBase.hpp" #include "constitutive/permeability/PermeabilityBase.hpp" #include "constitutive/permeability/PermeabilityFields.hpp" +#include "constitutive/relativePermeability/RelativePermeabilityBase.hpp" +#include "constitutive/relativePermeability/RelativePermeabilityFields.hpp" #include "fieldSpecification/AquiferBoundaryCondition.hpp" #include "finiteVolume/BoundaryStencil.hpp" #include "finiteVolume/FluxApproximationBase.hpp" #include "linearAlgebra/interfaces/InterfaceTypes.hpp" #include "physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp" #include "physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp" -#include "physicsSolvers/fluidFlow/SinglePhaseBaseKernels.hpp" // create for multiphase for kernels +#include "physicsSolvers/fluidFlow/SinglePhaseBaseKernels.hpp" // check need of multiphase equivalent #include "physicsSolvers/fluidFlow/StencilAccessors.hpp" namespace geos @@ -69,17 +71,11 @@ class FaceBasedAssemblyKernelBase using ImmiscibleMultiphaseFlowAccessors = StencilAccessors< fields::ghostRank, fields::flow::pressure, - fields::flow::pressure_n, - fields::flow::phaseVolumeFraction, - fields::flow::phaseVolumeFraction_n, fields::flow::gravityCoefficient, - fields::flow::phaseMobility, - fields::flow::dPhaseMobility >; // TODO: fix derivatives of mobility - - using ImmiscibleMultiphaseFluidAccessors = - StencilMaterialAccessors< MultiFluidBase, - fields::multifluid::phaseDensity, - fields::multifluid::dPhaseDensity >; + fields::immiscibleMultiphaseFlow::phaseDensity, + fields::immiscibleMultiphaseFlow::dPhaseDensity, + fields::immiscibleMultiphaseFlow::phaseMobility, + fields::immiscibleMultiphaseFlow::dPhaseMobility >; using CapPressureAccessors = StencilMaterialAccessors< CapillaryPressureBase, @@ -89,7 +85,9 @@ class FaceBasedAssemblyKernelBase using PermeabilityAccessors = StencilMaterialAccessors< PermeabilityBase, fields::permeability::permeability, - fields::permeability::dPerm_dPressure >; + fields::permeability::dPerm_dPressure >; + + using Deriv = immiscibleFlow::DerivativeOffset; /** * @brief Constructor for the kernel interface @@ -97,7 +95,6 @@ class FaceBasedAssemblyKernelBase * @param[in] rankOffset the offset of my MPI rank * @param[in] dofNumberAccessor accessor for the dof numbers * @param[in] multiPhaseFlowAccessors accessor for wrappers registered by the solver - * @param[in] multiPhaseFluidAccessors accessor for wrappers registered by the multiphase fluid model * @param[in] capPressureAccessors accessor for wrappers registered by the capillary pressure model * @param[in] permeabilityAccessors accessor for wrappers registered by the permeability model * @param[in] dt time step size @@ -107,8 +104,7 @@ class FaceBasedAssemblyKernelBase FaceBasedAssemblyKernelBase( integer const numPhases, globalIndex const rankOffset, DofNumberAccessor const & dofNumberAccessor, - ImmiscibleMultiphaseFlowAccessors const & multiPhaseFlowAccessors, - ImmiscibleMultiphaseFluidAccessors const & multiPhaseFluidAccessors, + ImmiscibleMultiphaseFlowAccessors const & multiPhaseFlowAccessors, CapPressureAccessors const & capPressureAccessors, PermeabilityAccessors const & permeabilityAccessors, real64 const & dt, @@ -125,11 +121,10 @@ class FaceBasedAssemblyKernelBase m_ghostRank( multiPhaseFlowAccessors.get( fields::ghostRank {} ) ), m_gravCoef( multiPhaseFlowAccessors.get( fields::flow::gravityCoefficient {} ) ), m_pres( multiPhaseFlowAccessors.get( fields::flow::pressure {} ) ), - m_mob( multiPhaseFlowAccessors.get( fields::flow::phaseMobility {} ) ), - m_dMob_dPres( multiPhaseFlowAccessors.get( fields::flow::dPhaseMobility {} ) ), - m_dMob_dSat( multiPhaseFlowAccessors.get( fields::flow::dPhaseMobility {} ) ), - m_dens( multiPhaseFluidAccessors.get( fields::multifluid::phaseDensity {} ) ), - m_dDens_dPres( multiPhaseFluidAccessors.get( fields::multifluid::dPhaseDensity {} ) ), + m_mob( multiPhaseFlowAccessors.get( fields::immiscibleMultiphaseFlow::phaseMobility {} ) ), + m_dMob( multiPhaseFlowAccessors.get( fields::immiscibleMultiphaseFlow::dPhaseMobility {} ) ), + m_dens( multiPhaseFlowAccessors.get( fields::immiscibleMultiphaseFlow::phaseDensity {} ) ), + m_dDens_dPres( multiPhaseFlowAccessors.get( fields::immiscibleMultiphaseFlow::dPhaseDensity {} ) ), m_phaseCapPressure( capPressureAccessors.get( fields::cappres::phaseCapPressure {} ) ), m_dPhaseCapPressure_dPhaseVolFrac( capPressureAccessors.get( fields::cappres::dPhaseCapPressure_dPhaseVolFraction {} ) ), m_localMatrix( localMatrix ), @@ -163,21 +158,18 @@ class FaceBasedAssemblyKernelBase // Primary and secondary variables /// Views on pressure ElementViewConst< arrayView1d< real64 const > > const m_pres; - /// Views on saturation - ElementViewConst< arrayView1d< real64 const > > const m_phaseVolFraction; /// Views on fluid mobility - ElementViewConst< arrayView2d< real64 const > > const m_mob; - ElementViewConst< arrayView2d< real64 const > > const m_dMob_dPres; - ElementViewConst< arrayView2d< real64 const > > const m_dMob_dSat; + ElementViewConst< arrayView2d< real64 const, immiscibleFlow::USD_PHASE > > const m_mob; + ElementViewConst< arrayView3d< real64 const, immiscibleFlow::USD_PHASE_DS > > const m_dMob; /// Views on fluid density - ElementViewConst< arrayView2d< real64 const > > const m_dens; - ElementViewConst< arrayView2d< real64 const > > const m_dDens_dPres; + ElementViewConst< arrayView2d< real64 const, immiscibleFlow::USD_PHASE > > const m_dens; + ElementViewConst< arrayView2d< real64 const, immiscibleFlow::USD_PHASE > > const m_dDens_dPres; /// Views on capillary pressure - ElementViewConst< arrayView2d< real64 const > > const m_phaseCapPressure; - ElementViewConst< arrayView2d< real64 const > > const m_dPhaseCapPressure_dPhaseVolFrac; + ElementViewConst< arrayView3d< real64 const, cappres::USD_CAPPRES > > const m_phaseCapPressure; + ElementViewConst< arrayView4d< real64 const, cappres::USD_CAPPRES_DS > > const m_dPhaseCapPressure_dPhaseVolFrac; // Residual and jacobian @@ -239,7 +231,6 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase STENCILWRAPPER const & stencilWrapper, DofNumberAccessor const & dofNumberAccessor, ImmiscibleMultiphaseFlowAccessors const & multiPhaseFlowAccessors, - ImmiscibleMultiphaseFluidAccessors const & multiPhaseFluidAccessors, CapPressureAccessors const & capPressureAccessors, PermeabilityAccessors const & permeabilityAccessors, real64 const & dt, @@ -250,8 +241,7 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase : FaceBasedAssemblyKernelBase( numPhases, rankOffset, dofNumberAccessor, - multiPhaseFlowAccessors, - multiPhaseFluidAccessors, + multiPhaseFlowAccessors, capPressureAccessors, permeabilityAccessors, dt, @@ -383,18 +373,12 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase // clear working arrays real64 densMean[m_numPhases]{}; real64 dDensMean_dP[m_numPhases][2]{}; - // real64 densMean = 0.0; - // real64 dDensMean_dP[2]{0.0, 0.0}; - real64 presGrad[m_numPhases]{}; /// check need for vector + real64 presGrad[m_numPhases]{}; real64 dPresGrad_dP[m_numPhases][2]{}; - // real64 presGrad = 0.0; - // real64 dPresGrad_dP[2]{0.0, 0.0}; real64 gravHead[m_numPhases]{}; real64 dGravHead_dP[m_numPhases][2]{}; - // real64 gravHead = 0.0; - // real64 dGravHead_dP[2]{0.0, 0.0}; real64 capGrad[m_numPhases]{}; real64 dCapGrad_dP[m_numPhases][2]{}; @@ -403,8 +387,6 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase real64 fluxVal[m_numPhases]{}; real64 dFlux_dP[m_numPhases][2]{}; real64 dFlux_dS[m_numPhases][2]{}; - // real64 fluxVal = 0.0; - // real64 dFlux_dP[2]{0.0, 0.0}; real64 mobility[m_numPhases]{}; real64 dMob_dP[m_numPhases][2]{}; @@ -421,17 +403,16 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase // loop over phases for( integer ip = 0; ip < m_numPhases; ++ip ) { - // calculate quantities on primary connected cells for( integer ke = 0; ke < 2; ++ke ) { // density - real64 const density = m_dens[seri[ke]][sesri[ke]][sei[ke]][ip]; - real64 const dDens_dP = m_dDens_dPres[seri[ke]][sesri[ke]][sei[ke]][ip]; + real64 const density = m_dens[seri[ke]][sesri[ke]][sei[ke]][0][ip]; // r = rho1 || rho2 + real64 const dDens_dP = m_dDens_dPres[seri[ke]][sesri[ke]][sei[ke]][0][ip]; // dr/dP = dr1/dP1 || dr2/dP // average density and derivatives densMean[ip] += 0.5 * density; // rho = (rho1 + rho2) / 2 - dDensMean_dP[ip][ke] = 0.5 * dDens_dP; // drho/dP = { (drho1/dP)/2 , (drho2/dP)/2 } + dDensMean_dP[ip][ke] = 0.5 * dDens_dP; // drho/dP = { (dr1/dP1)/2 , (dr2/dP2)/2 } } //***** calculation of flux ***** @@ -452,7 +433,7 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase real64 const pressure = m_pres[er][esr][ei]; // P = P1 || P2 presGrad[ip] += trans[ke] * pressure; // DPv = T (P1 - P2) dPresGrad_dTrans += signPotDiff[ke] * pressure; // dDPv/dT = (P1 - P2) - dPresGrad_dP[ip][ke] = trans[ke]; // dDPv/dP = {T , -T} + dPresGrad_dP[ip][ke] = trans[ke]; // dDPv/dP = { T , -T } real64 const gravD = trans[ke] * m_gravCoef[er][esr][ei]; // D = T g z1 || -T g z2 real64 const pot = trans[ke] * pressure - densMean[ip] * gravD; // Phi = T P1 - rho T g z1 || -T P2 + rho T g z2 @@ -462,15 +443,15 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase for( integer i = 0; i < 2; ++i ) { - dGravHead_dP[ip][i] += dDensMean_dP[ip][i] * gravD; // dDPg/dP = {drho1/dP * T g (z1 - z2) , drho2/dP * T g (z1 - z2)} + dGravHead_dP[ip][i] += dDensMean_dP[ip][i] * gravD; // dDPg/dP = {drho/dP1 * T g (z1 - z2) , drho/dP2 * T g (z1 - z2)} } if ( m_hasCapPressure ) // check sign convention { - real64 const capPres = m_phaseCapPressure[er][esr][ei]; // Pc = Pc1 || Pc2 - dCapGrad_dTrans -= signPotDiff[ke] * capPres; // dDPc/dT = (-Pc1 + Pc2) - pot -= trans[ke] * capPres; // Phi = T P1 - rho T g z1 - T Pc1 || -T P2 + rho T g z2 + T Pc2 - capGrad[ip] -= trans[ke] * capPres; // DPc = T (-Pc1 + Pc2) + real64 const capPres = m_phaseCapPressure[er][esr][ei][0][ip]; // Pc = Pc1 || Pc2 + dCapGrad_dTrans -= signPotDiff[ke] * capPres; // dDPc/dT = (-Pc1 + Pc2) + pot -= trans[ke] * capPres; // Phi = T P1 - rho T g z1 - T Pc1 || -T P2 + rho T g z2 + T Pc2 + capGrad[ip] -= trans[ke] * capPres; // DPc = T (-Pc1 + Pc2) } potScale = fmax( potScale, fabs( pot ) ); // maxPhi = Phi1 > Phi2 ? Phi1 : Phi2 @@ -479,11 +460,14 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase for( integer ke = 0; ke < 2; ++ke ) { dPresGrad_dP[ip][ke] += dTrans_dP[ke] * dPresGrad_dTrans; // dDPv/dP = { T + dT/dP1 * (P1 - P2) , -T + dT/dP2 * (P1 - P2)} - dGravHead_dP[ip][ke] += dTrans_dP[ke] * dGravHead_dTrans; // dDPg/dP = { drho1/dP * T g (z1 - z2) + dT/dP1 * rho g (z1 - z2) , - // drho2/dP * T g (z1 - z2) + dT/dP2 * rho g (z1 - z2) } + dGravHead_dP[ip][ke] += dTrans_dP[ke] * dGravHead_dTrans; // dDPg/dP = { drho/dP1 * T g (z1 - z2) + dT/dP1 * rho g (z1 - z2) , + // drho/dP2 * T g (z1 - z2) + dT/dP2 * rho g (z1 - z2) } if ( m_hasCapPressure ) { - dCapGrad_dP[ip][ke] += dTrans_dP[ke] * dCapGrad_dTrans; // dDPc/dP = { dT/dP1 * (-Pc1 + Pc2) , dT/dP2 * (-Pc1 + Pc2) } + real64 const dCapPres_dS = m_dPhaseCapPressure_dPhaseVolFrac[seri[ke]][sesri[ke]][sei[ke]][0][ip][ip]; // dPc/dS = dPc1/dS1 || dPc2/dS2 + dCapGrad_dP[ip][ke] += dTrans_dP[ke] * dCapGrad_dTrans; // dDPc/dP = { dT/dP1 * (-Pc1 + Pc2) , + // dT/dP2 * (-Pc1 + Pc2) } + dCapGrad_dS[ip][ke] -= trans[ke] * dCapPres_dS; // dDPc/dS = { -T * dPc1/dS1 , T * dPc2/dS2 } } } @@ -504,24 +488,22 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase real64 const alpha = ( potGrad + upwAbsTol ) / ( 2 * upwAbsTol ); // alpha = (DPhi + abstol) / abstol / 2 // choose upstream cell - // real64 mobility{}; - // real64 dMob_dP[2]{}; if( alpha <= 0.0 || alpha >= 1.0 ) // no smoothing needed { localIndex const k_up = 1 - localIndex( fmax( fmin( alpha, 1.0 ), 0.0 ) ); // 1 upwind -> k_up = 0 || 2 upwind -> k_up = 1 - mobility[ip] = m_mob[seri[k_up]][sesri[k_up]][sei[k_up]][ip]; // M = Mupstream - dMob_dP[ip][k_up] = m_dMob_dPres[seri[k_up]][sesri[k_up]][sei[k_up]][ip]; // dM/dP = {dM/dP1 , 0} OR {0 , dM/dP2} - dMob_dS[ip][k_up] = m_dMob_dSat[seri[k_up]][sesri[k_up]][sei[k_up]][ip]; // dM/dS = {dM/dS1 , 0} OR {0 , dM/dS2} + mobility[ip] = m_mob[seri[k_up]][sesri[k_up]][sei[k_up]][0][ip]; // M = Mupstream + dMob_dP[ip][k_up] = m_dMob[seri[k_up]][sesri[k_up]][sei[k_up]][0][ip][Deriv::dP]; // dM/dP = {dM/dP1 , 0} OR {0 , dM/dP2} + dMob_dS[ip][k_up] = m_dMob[seri[k_up]][sesri[k_up]][sei[k_up]][0][ip][Deriv::dS]; // dM/dS = {dM/dS1 , 0} OR {0 , dM/dS2} } else // perform smoothing { real64 const mobWeights[2] = { alpha, 1.0 - alpha }; for( integer ke = 0; ke < 2; ++ke ) { - mobility[ip] += mobWeights[ke] * m_mob[seri[ke]][sesri[ke]][sei[ke]][ip]; // M = alpha * M1 + (1 - alpha) * M2 - dMob_dP[ip][ke] = mobWeights[ke] * m_dMob_dPres[seri[ke]][sesri[ke]][sei[ke]][ip]; // dM/dP = {alpha * dM1/dP1 , (1 - alpha) * dM2/dP2} - dMob_dS[ip][ke] = mobWeights[ke] * m_dMob_dSat[seri[ke]][sesri[ke]][sei[ke]][ip]; // dM/dP = {alpha * dM1/dS1 , (1 - alpha) * dM2/dS2} + mobility[ip] += mobWeights[ke] * m_mob[seri[ke]][sesri[ke]][sei[ke]][0][ip]; // M = alpha * M1 + (1 - alpha) * M2 + dMob_dP[ip][ke] = mobWeights[ke] * m_dMob[seri[ke]][sesri[ke]][sei[ke]][0][ip][Deriv::dP]; // dM/dP = {alpha * dM1/dP1 , (1 - alpha) * dM2/dP2} + dMob_dS[ip][ke] = mobWeights[ke] * m_dMob[seri[ke]][sesri[ke]][sei[ke]][0][ip][Deriv::dS]; // dM/dP = {alpha * dM1/dS1 , (1 - alpha) * dM2/dS2} } } @@ -535,8 +517,8 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase // gravitational head depends only on the two cells connected (same as mean density) for( integer ke = 0; ke < 2; ++ke ) { - dFlux_dP[ip][ke] -= dGravHead_dP[ip][ke]; // dF/dP = { T + dT/dP1 * (P1 - P2) - drho1/dP * T g (z1 - z2) - dT/dP1 * rho g (z1 - z2) , - // -T + dT/dP2 * (P1 - P2) - drho2/dP * T g (z1 - z2) - dT/dP2 * rho g (z1 - z2) } + dFlux_dP[ip][ke] -= dGravHead_dP[ip][ke]; // dF/dP = { T + dT/dP1 * (P1 - P2) - drho/dP1 * T g (z1 - z2) - dT/dP1 * rho g (z1 - z2) , + // -T + dT/dP2 * (P1 - P2) - drho/dP2 * T g (z1 - z2) - dT/dP2 * rho g (z1 - z2) } } // capillary pressure contribution @@ -544,8 +526,10 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase { for( integer ke = 0; ke < 2; ++ke ) { - dFlux_dP[ip][ke] += dCapGrad_dP[ip][ke]; // dF/dP = { T + dT/dP1 * (P1 - P2) - drho1/dP * T g (z1 - z2) - dT/dP1 * rho g (z1 - z2) + dT/dP1 * (-Pc1 + Pc2) , - // -T + dT/dP2 * (P1 - P2) - drho2/dP * T g (z1 - z2) - dT/dP2 * rho g (z1 - z2) + dT/dP2 * (-Pc1 + Pc2) } + dFlux_dP[ip][ke] += dCapGrad_dP[ip][ke]; // dF/dP = { T + dT/dP1 * (P1 - P2) - drho/dP1 * T g (z1 - z2) - dT/dP1 * rho g (z1 - z2) + dT/dP1 * (-Pc1 + Pc2) , + // -T + dT/dP2 * (P1 - P2) - drho/dP2 * T g (z1 - z2) - dT/dP2 * rho g (z1 - z2) + dT/dP2 * (-Pc1 + Pc2) } + + dFlux_dS[ip][ke] += dCapGrad_dS[ip][ke]; // dF/dS = { T * -dPc/dS1 , T * dPc/dS2 } } } @@ -554,8 +538,10 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase for( integer ke = 0; ke < 2; ++ke ) { - dFlux_dP[ip][ke] *= mobility[ip]; // dF/dP = { M [ T + dT/dP1 * (P1 - P2) - drho1/dP * T g (z1 - z2) - dT/dP1 * rho g (z1 - z2) + dT/dP1 * (-Pc1 + Pc2)] , - // M [-T + dT/dP2 * (P1 - P2) - drho2/dP * T g (z1 - z2) - dT/dP2 * rho g (z1 - z2) + dT/dP2 * (-Pc1 + Pc2)] } + dFlux_dP[ip][ke] *= mobility[ip]; // dF/dP = { M [ T + dT/dP1 * (P1 - P2) - drho/dP1 * T g (z1 - z2) - dT/dP1 * rho g (z1 - z2) + dT/dP1 * (-Pc1 + Pc2)] , + // M [-T + dT/dP2 * (P1 - P2) - drho/dP2 * T g (z1 - z2) - dT/dP2 * rho g (z1 - z2) + dT/dP2 * (-Pc1 + Pc2)] } + + dFlux_dS[ip][ke] *= mobility[ip]; // dF/dS = { M [T * -dPc/dS1] , M [T * dPc/dS2] } } // add contribution from upstream cell mobility derivatives @@ -564,7 +550,7 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase dFlux_dP[ip][ke] += dMob_dP[ip][ke] * potGrad; // dF/dP = { M [ T + dT/dP1 * (P1 - P2) - drho1/dP * T g (z1 - z2) - dT/dP1 * rho g (z1 - z2) + dT/dP1 * (-Pc1 + Pc2)] + dM/dP1 * DPhi , // M [-T + dT/dP2 * (P1 - P2) - drho2/dP * T g (z1 - z2) - dT/dP2 * rho g (z1 - z2) + dT/dP2 * (-Pc1 + Pc2)] + dM/dP2 * DPhi } - dFlux_dS[ip][ke] += dMob_dS[ip][ke] * potGrad; // dF/dS = { dM/dS1 * DPhi , dM/dS2 * DPhi } + dFlux_dS[ip][ke] += dMob_dS[ip][ke] * potGrad; // dF/dS = { M [T * -dPc/dS1] + dM/dS1 * DPhi , M [T * dPc/dS2] + dM/dS2 * DPhi } } // populate local flux vector and derivatives @@ -698,7 +684,7 @@ class FaceBasedAssemblyKernelFactory template< typename POLICY, typename STENCILWRAPPER > static void createAndLaunch( integer const numPhases, - globalIndex const rankOffset, // add capillary pressure and total mass equation flags + globalIndex const rankOffset, string const & dofKey, integer const hasCapPressure, integer const useTotalMassEquation, @@ -717,13 +703,12 @@ class FaceBasedAssemblyKernelFactory dofNumberAccessor.setName( solverName + "/accessors/" + dofKey ); using kernelType = FaceBasedAssemblyKernel< NUM_EQN, NUM_DOF, STENCILWRAPPER >; - typename kernelType::ImmiscibleMultiPhaseFlowAccessors flowAccessors( elemManager, solverName ); - typename kernelType::ImmiscibleMultiPhaseFluidAccessors fluidAccessors( elemManager, solverName ); + typename kernelType::ImmiscibleMultiPhaseFlowAccessors flowAccessors( elemManager, solverName ); typename kernelType::CapPressureAccessors capPressureAccessors( elemManager, solverName ); typename kernelType::PermeabilityAccessors permAccessors( elemManager, solverName ); kernelType kernel( numPhases, rankOffset, stencilWrapper, dofNumberAccessor, - flowAccessors, fluidAccessors, capPressureAccessors, permAccessors, + flowAccessors, capPressureAccessors, permAccessors, dt, localMatrix, localRhs, hasCapPressure, useTotalMassEquation ); kernelType::template launch< POLICY >( stencilWrapper.size(), kernel ); } @@ -731,7 +716,6 @@ class FaceBasedAssemblyKernelFactory - } // namesace immiscible multiphasekernels From 40e191a663a1c599d244e1d0e3a87ece8711ff71 Mon Sep 17 00:00:00 2001 From: rpiazza87 Date: Mon, 19 Aug 2024 18:08:50 -0700 Subject: [PATCH 021/104] added phase mobility kernel --- .../fluidFlow/ImmiscibleMultiphaseFlow.cpp | 27 ++- .../fluidFlow/ImmiscibleMultiphaseKernels.hpp | 155 ++++++++++++++++++ 2 files changed, 165 insertions(+), 17 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index a5a5c3491a2..6e34cb6072e 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -271,24 +271,17 @@ void ImmiscibleMultiphaseFlow::updateFluidState( ElementSubRegionBase & subRegio void ImmiscibleMultiphaseFlow::updatePhaseMobility( ObjectManagerBase & dataGroup ) const { GEOS_MARK_FUNCTION; - - GEOS_UNUSED_VAR( dataGroup ); - /// Matteo: looks like you will to create a new update function for the mobility. I have left the code as an example. - // // note that the phase mobility computed here also includes phase density - // string const & fluidName = dataGroup.getReference< string >( viewKeyStruct::fluidNamesString() ); - // MultiFluidBase const & fluid = getConstitutiveModel< MultiFluidBase >( dataGroup, fluidName ); - - // string const & relpermName = dataGroup.getReference< string >( viewKeyStruct::relPermNamesString() ); - // RelativePermeabilityBase const & relperm = getConstitutiveModel< RelativePermeabilityBase >( dataGroup, relpermName ); - - // isothermalCompositionalMultiphaseFVMKernels:: - // PhaseMobilityKernelFactory:: - // createAndLaunch< parallelDevicePolicy<> >( m_numComponents, - // m_numPhases, - // dataGroup, - // fluid, - // relperm ); + // note that the phase mobility computed here also includes phase density + string const & relpermName = dataGroup.getReference< string >( viewKeyStruct::relPermNamesString() ); + RelativePermeabilityBase const & relperm = getConstitutiveModel< RelativePermeabilityBase >( dataGroup, relpermName ); + + immiscibleMultiphaseKernels:: + PhaseMobilityKernelFactory:: + createAndLaunch< parallelDevicePolicy<> >( m_numPhases, + dataGroup, + relperm ); + } void ImmiscibleMultiphaseFlow::initializeFluidState( MeshLevel & mesh, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp index 310f7e34c07..912a9ce8509 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp @@ -714,6 +714,161 @@ class FaceBasedAssemblyKernelFactory } }; +/******************************** PhaseMobilityKernel ********************************/ + +/** + * @class PhaseMobilityKernel + * @tparam NUM_PHASE number of fluid phases + * @brief Define the interface for the property kernel in charge of computing the phase mobilities + */ +template< integer NUM_PHASE > +class PhaseMobilityKernel +{ +public: + + //using Base = isothermalCompositionalMultiphaseBaseKernels::PropertyKernelBase< NUM_COMP >; + + /// Compile time value for the number of phases + static constexpr integer numPhase = NUM_PHASE; + + /** + * @brief Constructor + * @param[in] subRegion the element subregion + * @param[in] fluid the fluid model + * @param[in] relperm the relperm model + */ + PhaseMobilityKernel( ObjectManagerBase & subRegion, + RelativePermeabilityBase const & relperm ) + : + m_phaseDens( subRegion.getField< fields::immiscibleMultiphaseFlow::phaseDensity >() ), + m_dPhaseDens( subRegion.getField< fields::immiscibleMultiphaseFlow::dPhaseDensity>() ), + m_phaseVisc( subRegion.getField< fields::immiscibleMultiphaseFlow::phaseViscosity >() ), + m_dPhaseVisc( subRegion.getField< fields::immiscibleMultiphaseFlow::dPhaseViscosity >() ), + m_phaseRelPerm( relperm.phaseRelPerm() ), + m_dPhaseRelPerm_dPhaseVolFrac( relperm.dPhaseRelPerm_dPhaseVolFraction() ), + m_phaseMob( subRegion.getField< fields::immiscibleMultiphaseFlow::phaseMobility >() ), + m_dPhaseMob( subRegion.getField< fields::immiscibleMultiphaseFlow::dPhaseMobility >() ) + {} + + /** + * @brief Performs the kernel launch + * @tparam POLICY the policy used in the RAJA kernels + * @tparam KERNEL_TYPE the kernel type + * @param[in] numElems the number of elements + * @param[inout] kernelComponent the kernel component providing access to the compute function + */ + template< typename POLICY, typename KERNEL_TYPE > + static void + launch( localIndex const numElems, + KERNEL_TYPE const & kernelComponent ) + { + forAll< POLICY >( numElems, [=] GEOS_HOST_DEVICE ( localIndex const ei ) + { + kernelComponent.compute( ei ); + } ); + } + + /** + * @brief Compute the phase mobilities in an element + * @tparam FUNC the type of the function that can be used to customize the kernel + * @param[in] ei the element index + * @param[in] phaseMobilityKernelOp the function used to customize the kernel + */ + template< typename FUNC = NoOpFunc > + GEOS_HOST_DEVICE + void compute( localIndex const ei, + FUNC && phaseMobilityKernelOp = NoOpFunc{} ) const + { + using Deriv = immiscibleFlow::DerivativeOffset; + + arraySlice1d< real64, immiscibleFlow::USD_PHASE - 1 > const phaseMob = m_phaseMob[ei]; + arraySlice2d< real64, immiscibleFlow::USD_PHASE_DS - 1 > const dPhaseMob = m_dPhaseMob[ei]; + + for( integer ip = 0; ip < numPhase; ++ip ) + { + real64 const density = m_phaseDens[ei][0][ip]; + real64 const dDens_dP = m_dPhaseDens[ei][0][ip]; + real64 const viscosity = m_phaseVisc[ei][0][ip]; + real64 const dVisc_dP = m_dPhaseVisc[ei][0][ip]; + + real64 const relPerm = m_phaseRelPerm[ei][0][ip]; + + real64 const mobility = relPerm * density / viscosity; + + phaseMob[ip] = mobility; + dPhaseMob[ip][Deriv::dP] = mobility * (dDens_dP / density - dVisc_dP / viscosity); + + for( integer jp = 0; jp < numPhase; ++jp ) // check if we need numPhase or numPhase-1 derivatives + { + real64 const dRelPerm_dS = dPhaseRelPerm_dPhaseVolFrac[ei][0][ip][jp]; + dPhaseMob[ip][Deriv::dS+jp] = dRelPerm_dS * density / viscosity; + } + + // call the lambda in the phase loop to allow the reuse of the relperm, density, viscosity, and mobility + // possible use: assemble the derivatives wrt temperature + phaseMobilityKernelOp( ip, phaseMob[ip], dPhaseMob[ip] ); + } + } + +protected: + + // inputs + + /// Views on the phase densities + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > m_phaseDens; + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > m_dPhaseDens; + + /// Views on the phase viscosities + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > m_phaseVisc; + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > m_dPhaseVisc; + + /// Views on the phase relative permeabilities + arrayView3d< real64 const, relperm::USD_RELPERM > m_phaseRelPerm; + arrayView4d< real64 const, relperm::USD_RELPERM_DS > m_dPhaseRelPerm_dPhaseVolFrac; + + // outputs + + /// Views on the phase mobilities + arrayView2d< real64, immiscibleFlow::USD_PHASE > m_phaseMob; + arrayView3d< real64, immiscibleFlow::USD_PHASE_DS > m_dPhaseMob; +}; + +/** + * @class PhaseMobilityKernelFactory + */ +class PhaseMobilityKernelFactory +{ +public: + + /** + * @brief Create a new kernel and launch + * @tparam POLICY the policy used in the RAJA kernel + * @param[in] numPhase the number of fluid phases + * @param[in] subRegion the element subregion + * @param[in] relperm the relperm model + */ + template< typename POLICY > + static void + createAndLaunch( integer const numPhase, + ObjectManagerBase & subRegion, + RelativePermeabilityBase const & relperm ) + { + if( numPhase == 2 ) + { + PhaseMobilityKernel< 2 > kernel( subRegion, relperm ); + PhaseMobilityKernel< 2 >::template launch< POLICY >( subRegion.size(), kernel ); + } + else if( numPhase == 3 ) + { + PhaseMobilityKernel< 3 > kernel( subRegion, relperm ); + PhaseMobilityKernel< 3 >::template launch< POLICY >( subRegion.size(), kernel ); + } + } + +}; + + + } // namesace immiscible multiphasekernels From cb15c3005b789175f121113395aa5831f9132edb Mon Sep 17 00:00:00 2001 From: rpiazza87 Date: Tue, 20 Aug 2024 14:58:59 -0700 Subject: [PATCH 022/104] updated kernels, apply BC and setupDOF --- src/coreComponents/common/DataLayouts.hpp | 5 +- .../fluidFlow/ImmiscibleMultiphaseFlow.cpp | 136 +++++++++++++++--- .../ImmiscibleMultiphaseFlowFields.hpp | 8 ++ .../fluidFlow/ImmiscibleMultiphaseKernels.hpp | 92 ++++++------ 4 files changed, 175 insertions(+), 66 deletions(-) diff --git a/src/coreComponents/common/DataLayouts.hpp b/src/coreComponents/common/DataLayouts.hpp index 40b64ada6df..e09fe788d65 100644 --- a/src/coreComponents/common/DataLayouts.hpp +++ b/src/coreComponents/common/DataLayouts.hpp @@ -21,6 +21,7 @@ #define GEOS_COMMON_DATALAYOUTS_HPP_ #include "common/GeosxConfig.hpp" +#include "common/DataTypes.hpp" #include "LvArray/src/Array.hpp" #include "RAJA/RAJA.hpp" @@ -236,9 +237,9 @@ static constexpr int USD_PHASE_DS = LvArray::typeManipulation::getStrideOneDimen struct DerivativeOffset { /// index of derivative wrt pressure - static integer constexpr dP = 0; + static int constexpr dP = 0; /// index of first derivative wrt compositions - static integer constexpr dS = 1; + static int constexpr dS = 1; }; } // namespace immiscibleFlow diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index 6e34cb6072e..9d3594d71f8 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -23,6 +23,9 @@ #include "physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp" #include "physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp" +#include "physicsSolvers/fluidFlow/IsothermalCompositionalMultiphaseBaseKernels.hpp" // should be removed eventually +#include "physicsSolvers/fluidFlow/IsothermalCompositionalMultiphaseFVMKernels.hpp" + #include "constitutive/ConstitutiveManager.hpp" #include "constitutive/capillaryPressure/CapillaryPressureFields.hpp" #include "constitutive/capillaryPressure/capillaryPressureSelector.hpp" @@ -69,7 +72,8 @@ ImmiscibleMultiphaseFlow::ImmiscibleMultiphaseFlow( const string & name, : FlowSolverBase( name, parent ), m_numPhases( 2 ), - m_hasCapPressure( 0 ) + m_hasCapPressure( 0 ), + m_useTotalMassEquation ( 0 ) { this->registerWrapper( viewKeyStruct::inputTemperatureString(), &m_inputTemperature ). setInputFlag( InputFlags::REQUIRED ). @@ -640,9 +644,7 @@ void ImmiscibleMultiphaseFlow::assembleFluxTerms( real64 const dt, DofManager const & dofManager, CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) const -{ - GEOS_UNUSED_VAR( dt, domain, dofManager, localMatrix, localRhs ); - +{ GEOS_MARK_FUNCTION; NumericalMethodsManager const & numericalMethodManager = domain.getNumericalMethodManager(); @@ -657,6 +659,8 @@ void ImmiscibleMultiphaseFlow::assembleFluxTerms( real64 const dt, { fluxApprox.forAllStencils( mesh, [&]( auto & stencil ) { + typename TYPEOFREF( stencil ) ::KernelWrapper stencilWrapper = stencil.createKernelWrapper(); + immiscibleMultiphaseKernels:: FaceBasedAssemblyKernelFactory::createAndLaunch< parallelDevicePolicy<> >( m_numPhases, dofManager.rankOffset(), dofKey, @@ -678,26 +682,20 @@ void ImmiscibleMultiphaseFlow::setupDofs( DomainPartition const & domain, DofManager & dofManager ) const { GEOS_UNUSED_VAR(domain, dofManager); - //// add a field for the cell-centered degrees of freedom - //dofManager.addField( viewKeyStruct::elemDofFieldString(), - // FieldLocation::Elem, - // m_numDofPerCell, - // getMeshTargets() ); + // add a field for the cell-centered degrees of freedom + dofManager.addField( viewKeyStruct::elemDofFieldString(), + FieldLocation::Elem, + m_numDofPerCell, + getMeshTargets() ); //// this call with instruct GEOS to reorder the dof numbers //dofManager.setLocalReorderingType( viewKeyStruct::elemDofFieldString(), // DofManager::LocalReorderingType::ReverseCutHillMcKee ); - //// for the volume balance equation, disable global coupling - //// this equation is purely local (not coupled to neighbors or other physics) - //dofManager.disableGlobalCouplingForEquation( viewKeyStruct::elemDofFieldString(), - // m_numComponents ); - - - //NumericalMethodsManager const & numericalMethodManager = domain.getNumericalMethodManager(); - //FiniteVolumeManager const & fvManager = numericalMethodManager.getFiniteVolumeManager(); - //FluxApproximationBase const & fluxApprox = fvManager.getFluxApproximation( m_discretizationName ); - //dofManager.addCoupling( viewKeyStruct::elemDofFieldString(), fluxApprox ); + NumericalMethodsManager const & numericalMethodManager = domain.getNumericalMethodManager(); + FiniteVolumeManager const & fvManager = numericalMethodManager.getFiniteVolumeManager(); + FluxApproximationBase const & fluxApprox = fvManager.getFluxApproximation( m_discretizationName ); + dofManager.addCoupling( viewKeyStruct::elemDofFieldString(), fluxApprox ); } void ImmiscibleMultiphaseFlow::applyBoundaryConditions( real64 const time_n, @@ -713,14 +711,110 @@ void ImmiscibleMultiphaseFlow::applyBoundaryConditions( real64 const time_n, applyDirichletBC( time_n, dt, dofManager, domain, localMatrix.toViewConstSizes(), localRhs.toView() ); } -void ImmiscibleMultiphaseFlow::applyDirichletBC( real64 const time, +namespace +{ +char const bcLogMessage[] = + "CompositionalMultiphaseBase {}: at time {}s, " + "the <{}> boundary condition '{}' is applied to the element set '{}' in subRegion '{}'. " + "\nThe scale of this boundary condition is {} and multiplies the value of the provided function (if any). " + "\nThe total number of target elements (including ghost elements) is {}. " + "\nNote that if this number is equal to zero for all subRegions, the boundary condition will not be applied on this element set."; +} + +void ImmiscibleMultiphaseFlow::applyDirichletBC( real64 const time_n, real64 const dt, DofManager const & dofManager, DomainPartition & domain, CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) const { - GEOS_UNUSED_VAR( time, dt, dofManager, domain, localMatrix, localRhs ); + GEOS_MARK_FUNCTION; + + // // Only validate BC at the beginning of Newton loop + // if( m_nonlinearSolverParameters.m_numNewtonIterations == 0 ) + // { + // bool const bcConsistent = validateDirichletBC( domain, time_n + dt ); + // GEOS_ERROR_IF( !bcConsistent, GEOS_FMT( "CompositionalMultiphaseBase {}: inconsistent boundary conditions", getDataContext() ) ); + // } + + FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + arrayView1d< string const > const & ) + { + + // 1. Apply pressure Dirichlet BCs, store in a separate field + applyFieldValue< ElementSubRegionBase >( time_n, dt, mesh, bcLogMessage, + fields::flow::pressure::key(), fields::flow::bcPressure::key() ); + // 2. Apply saturation BC (phase volume fraction) and store in a separate field + applyFieldValue< ElementSubRegionBase >( time_n, dt, mesh, bcLogMessage, + fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key(), fields::immiscibleMultiphaseFlow::bcPhaseVolumeFraction::key() ); + + globalIndex const rankOffset = dofManager.rankOffset(); + string const dofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); + + // 3. Call constitutive update, back-calculate target global component densities and apply to the system + fsManager.apply< ElementSubRegionBase >( time_n + dt, + mesh, + fields::flow::pressure::key(), + [&] ( FieldSpecificationBase const &, + string const &, + SortedArrayView< localIndex const > const & targetSet, + ElementSubRegionBase & subRegion, + string const & ) + { + + arrayView1d< real64 const > const bcPres = + subRegion.getReference< array1d< real64 > >( fields::flow::bcPressure::key() ); + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const bcPhaseVolFraction = + subRegion.getReference< array2d< real64, immiscibleFlow::LAYOUT_PHASE > >( fields::immiscibleMultiphaseFlow::bcPhaseVolumeFraction::key() ); + + arrayView1d< integer const > const ghostRank = + subRegion.getReference< array1d< integer > >( ObjectManagerBase::viewKeyStruct::ghostRankString() ); + arrayView1d< globalIndex const > const dofNumber = + subRegion.getReference< array1d< globalIndex > >( dofKey ); + arrayView1d< real64 const > const pres = + subRegion.getReference< array1d< real64 > >( fields::flow::pressure::key() ); + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFraction = + subRegion.getReference< array2d< real64, immiscibleFlow::LAYOUT_PHASE > >( fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key() ); + + integer const numPhase = m_numPhases; + forAll< parallelDevicePolicy<> >( targetSet.size(), [=] GEOS_HOST_DEVICE ( localIndex const a ) + { + localIndex const ei = targetSet[a]; + if( ghostRank[ei] >= 0 ) + { + return; + } + + globalIndex const dofIndex = dofNumber[ei]; + localIndex const localRow = dofIndex - rankOffset; + real64 rhsValue; + + // 3.1. Apply pressure value to the matrix/rhs + FieldSpecificationEqual::SpecifyFieldValue( dofIndex, + rankOffset, + localMatrix, + rhsValue, + bcPres[ei], + pres[ei] ); + localRhs[localRow] = rhsValue; + + // 3.2. For each phase, apply target saturation value + for( integer ip = 0; ip < numPhase; ++ip ) + { + FieldSpecificationEqual::SpecifyFieldValue( dofIndex + ip + 1, + rankOffset, + localMatrix, + rhsValue, + bcPhaseVolFraction[ei][ip], + phaseVolFraction[ei][ip] ); + localRhs[localRow + ip + 1] = rhsValue; + } + } ); + } ); + } ); } void ImmiscibleMultiphaseFlow::resetStateToBeginningOfStep( DomainPartition & domain ) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp index dcf303e6eca..0cde6c89fad 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp @@ -53,6 +53,14 @@ DECLARE_FIELD( phaseVolumeFraction_n, WRITE_AND_READ, "Phase volume fraction at the previous converged time step" ); +DECLARE_FIELD( bcPhaseVolumeFraction, + "bcPhaseVolumeFraction", + array2dLayoutPhase, + 0, + LEVEL_0, + WRITE_AND_READ, + "Boundary condition phase volume fraction" ); + DECLARE_FIELD( phaseMass, "phaseMass", array2dLayoutPhase, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp index 912a9ce8509..63e562674cb 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp @@ -71,11 +71,13 @@ class FaceBasedAssemblyKernelBase using ImmiscibleMultiphaseFlowAccessors = StencilAccessors< fields::ghostRank, fields::flow::pressure, - fields::flow::gravityCoefficient, - fields::immiscibleMultiphaseFlow::phaseDensity, - fields::immiscibleMultiphaseFlow::dPhaseDensity, + fields::flow::gravityCoefficient, fields::immiscibleMultiphaseFlow::phaseMobility, - fields::immiscibleMultiphaseFlow::dPhaseMobility >; + fields::immiscibleMultiphaseFlow::dPhaseMobility >; + + using MultiphaseFluidAccessors = + StencilAccessors< fields::immiscibleMultiphaseFlow::phaseDensity, + fields::immiscibleMultiphaseFlow::dPhaseDensity >; using CapPressureAccessors = StencilMaterialAccessors< CapillaryPressureBase, @@ -104,7 +106,8 @@ class FaceBasedAssemblyKernelBase FaceBasedAssemblyKernelBase( integer const numPhases, globalIndex const rankOffset, DofNumberAccessor const & dofNumberAccessor, - ImmiscibleMultiphaseFlowAccessors const & multiPhaseFlowAccessors, + ImmiscibleMultiphaseFlowAccessors const & multiPhaseFlowAccessors, + MultiphaseFluidAccessors const & fluidAccessors, CapPressureAccessors const & capPressureAccessors, PermeabilityAccessors const & permeabilityAccessors, real64 const & dt, @@ -123,15 +126,15 @@ class FaceBasedAssemblyKernelBase m_pres( multiPhaseFlowAccessors.get( fields::flow::pressure {} ) ), m_mob( multiPhaseFlowAccessors.get( fields::immiscibleMultiphaseFlow::phaseMobility {} ) ), m_dMob( multiPhaseFlowAccessors.get( fields::immiscibleMultiphaseFlow::dPhaseMobility {} ) ), - m_dens( multiPhaseFlowAccessors.get( fields::immiscibleMultiphaseFlow::phaseDensity {} ) ), - m_dDens_dPres( multiPhaseFlowAccessors.get( fields::immiscibleMultiphaseFlow::dPhaseDensity {} ) ), + m_dens( fluidAccessors.get( fields::immiscibleMultiphaseFlow::phaseDensity {} ) ), + m_dDens_dPres( fluidAccessors.get( fields::immiscibleMultiphaseFlow::dPhaseDensity {} ) ), m_phaseCapPressure( capPressureAccessors.get( fields::cappres::phaseCapPressure {} ) ), m_dPhaseCapPressure_dPhaseVolFrac( capPressureAccessors.get( fields::cappres::dPhaseCapPressure_dPhaseVolFraction {} ) ), m_localMatrix( localMatrix ), m_localRhs( localRhs ), m_hasCapPressure ( hasCapPressure ), m_useTotalMassEquation ( useTotalMassEquation ) - {} + {GEOS_UNUSED_VAR(m_useTotalMassEquation);} protected: @@ -231,6 +234,7 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase STENCILWRAPPER const & stencilWrapper, DofNumberAccessor const & dofNumberAccessor, ImmiscibleMultiphaseFlowAccessors const & multiPhaseFlowAccessors, + MultiphaseFluidAccessors const & fluidAccessors, CapPressureAccessors const & capPressureAccessors, PermeabilityAccessors const & permeabilityAccessors, real64 const & dt, @@ -241,7 +245,8 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase : FaceBasedAssemblyKernelBase( numPhases, rankOffset, dofNumberAccessor, - multiPhaseFlowAccessors, + multiPhaseFlowAccessors, + fluidAccessors, capPressureAccessors, permeabilityAccessors, dt, @@ -371,26 +376,26 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase for( k[1] = k[0] + 1; k[1] < stack.numFluxElems; ++k[1] ) { // clear working arrays - real64 densMean[m_numPhases]{}; - real64 dDensMean_dP[m_numPhases][2]{}; + real64 densMean[numEqn]{}; + real64 dDensMean_dP[numEqn][2]{}; - real64 presGrad[m_numPhases]{}; - real64 dPresGrad_dP[m_numPhases][2]{}; + real64 presGrad[numEqn]{}; + real64 dPresGrad_dP[numEqn][2]{}; - real64 gravHead[m_numPhases]{}; - real64 dGravHead_dP[m_numPhases][2]{}; + real64 gravHead[numEqn]{}; + real64 dGravHead_dP[numEqn][2]{}; - real64 capGrad[m_numPhases]{}; - real64 dCapGrad_dP[m_numPhases][2]{}; - real64 dCapGrad_dS[m_numPhases][2]{}; + real64 capGrad[numEqn]{}; + real64 dCapGrad_dP[numEqn][2]{}; + real64 dCapGrad_dS[numEqn][2]{}; - real64 fluxVal[m_numPhases]{}; - real64 dFlux_dP[m_numPhases][2]{}; - real64 dFlux_dS[m_numPhases][2]{}; + real64 fluxVal[numEqn]{}; + real64 dFlux_dP[numEqn][2]{}; + real64 dFlux_dS[numEqn][2]{}; - real64 mobility[m_numPhases]{}; - real64 dMob_dP[m_numPhases][2]{}; - real64 dMob_dS[m_numPhases][2]{}; + real64 mobility[numEqn]{}; + real64 dMob_dP[numEqn][2]{}; + real64 dMob_dS[numEqn][2]{}; real64 const trans[2] = { stack.transmissibility[connectionIndex][0], stack.transmissibility[connectionIndex][1] }; real64 const dTrans_dP[2] = { stack.dTrans_dPres[connectionIndex][0], stack.dTrans_dPres[connectionIndex][1] }; @@ -407,8 +412,8 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase for( integer ke = 0; ke < 2; ++ke ) { // density - real64 const density = m_dens[seri[ke]][sesri[ke]][sei[ke]][0][ip]; // r = rho1 || rho2 - real64 const dDens_dP = m_dDens_dPres[seri[ke]][sesri[ke]][sei[ke]][0][ip]; // dr/dP = dr1/dP1 || dr2/dP + real64 const density = m_dens[seri[ke]][sesri[ke]][sei[ke]][ip]; // r = rho1 || rho2 + real64 const dDens_dP = m_dDens_dPres[seri[ke]][sesri[ke]][sei[ke]][ip]; // dr/dP = dr1/dP1 || dr2/dP // average density and derivatives densMean[ip] += 0.5 * density; // rho = (rho1 + rho2) / 2 @@ -436,7 +441,7 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase dPresGrad_dP[ip][ke] = trans[ke]; // dDPv/dP = { T , -T } real64 const gravD = trans[ke] * m_gravCoef[er][esr][ei]; // D = T g z1 || -T g z2 - real64 const pot = trans[ke] * pressure - densMean[ip] * gravD; // Phi = T P1 - rho T g z1 || -T P2 + rho T g z2 + real64 pot = trans[ke] * pressure - densMean[ip] * gravD; // Phi = T P1 - rho T g z1 || -T P2 + rho T g z2 gravHead[ip] += densMean[ip] * gravD; // DPg = rho (T g z1 - T g z2) = T rho g (z1 - z2) dGravHead_dTrans += signPotDiff[ke] * densMean[ip] * m_gravCoef[er][esr][ei]; // dDPg/dT = rho g z1 - rho g z2 = rho g (z1 - z2) @@ -474,7 +479,7 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase // *** upwinding *** // compute potential gradient - real64 const potGrad = presGrad[ip] - gravHead[ip]; // DPhi = T (P1 - P2) - T rho g (z1 - z2) + real64 potGrad = presGrad[ip] - gravHead[ip]; // DPhi = T (P1 - P2) - T rho g (z1 - z2) if ( m_hasCapPressure ) { potGrad += capGrad[ip]; // DPhi = T (P1 - P2) - T rho g (z1 - z2) + T (-Pc1 + Pc2) @@ -492,18 +497,18 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase { localIndex const k_up = 1 - localIndex( fmax( fmin( alpha, 1.0 ), 0.0 ) ); // 1 upwind -> k_up = 0 || 2 upwind -> k_up = 1 - mobility[ip] = m_mob[seri[k_up]][sesri[k_up]][sei[k_up]][0][ip]; // M = Mupstream - dMob_dP[ip][k_up] = m_dMob[seri[k_up]][sesri[k_up]][sei[k_up]][0][ip][Deriv::dP]; // dM/dP = {dM/dP1 , 0} OR {0 , dM/dP2} - dMob_dS[ip][k_up] = m_dMob[seri[k_up]][sesri[k_up]][sei[k_up]][0][ip][Deriv::dS]; // dM/dS = {dM/dS1 , 0} OR {0 , dM/dS2} + mobility[ip] = m_mob[seri[k_up]][sesri[k_up]][sei[k_up]][ip]; // M = Mupstream + dMob_dP[ip][k_up] = m_dMob[seri[k_up]][sesri[k_up]][sei[k_up]][ip][Deriv::dP]; // dM/dP = {dM/dP1 , 0} OR {0 , dM/dP2} + dMob_dS[ip][k_up] = m_dMob[seri[k_up]][sesri[k_up]][sei[k_up]][ip][Deriv::dS]; // dM/dS = {dM/dS1 , 0} OR {0 , dM/dS2} } else // perform smoothing { real64 const mobWeights[2] = { alpha, 1.0 - alpha }; for( integer ke = 0; ke < 2; ++ke ) { - mobility[ip] += mobWeights[ke] * m_mob[seri[ke]][sesri[ke]][sei[ke]][0][ip]; // M = alpha * M1 + (1 - alpha) * M2 - dMob_dP[ip][ke] = mobWeights[ke] * m_dMob[seri[ke]][sesri[ke]][sei[ke]][0][ip][Deriv::dP]; // dM/dP = {alpha * dM1/dP1 , (1 - alpha) * dM2/dP2} - dMob_dS[ip][ke] = mobWeights[ke] * m_dMob[seri[ke]][sesri[ke]][sei[ke]][0][ip][Deriv::dS]; // dM/dP = {alpha * dM1/dS1 , (1 - alpha) * dM2/dS2} + mobility[ip] += mobWeights[ke] * m_mob[seri[ke]][sesri[ke]][sei[ke]][ip]; // M = alpha * M1 + (1 - alpha) * M2 + dMob_dP[ip][ke] = mobWeights[ke] * m_dMob[seri[ke]][sesri[ke]][sei[ke]][ip][Deriv::dP]; // dM/dP = {alpha * dM1/dP1 , (1 - alpha) * dM2/dP2} + dMob_dS[ip][ke] = mobWeights[ke] * m_dMob[seri[ke]][sesri[ke]][sei[ke]][ip][Deriv::dS]; // dM/dP = {alpha * dM1/dS1 , (1 - alpha) * dM2/dS2} } } @@ -585,7 +590,7 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase * @param[in] iconn the connection index * @param[inout] stack the stack variables */ - template< typename FUNC = singlePhaseBaseKernels::NoOpFunc > // should change to multiphase + template< typename FUNC = singlePhaseBaseKernels::NoOpFunc > // should change to multiphase GEOS_HOST_DEVICE void complete( localIndex const iconn, StackVariables & stack, @@ -703,12 +708,13 @@ class FaceBasedAssemblyKernelFactory dofNumberAccessor.setName( solverName + "/accessors/" + dofKey ); using kernelType = FaceBasedAssemblyKernel< NUM_EQN, NUM_DOF, STENCILWRAPPER >; - typename kernelType::ImmiscibleMultiPhaseFlowAccessors flowAccessors( elemManager, solverName ); + typename kernelType::ImmiscibleMultiphaseFlowAccessors flowAccessors( elemManager, solverName ); + typename kernelType::MultiphaseFluidAccessors fluidAccessors( elemManager, solverName ); typename kernelType::CapPressureAccessors capPressureAccessors( elemManager, solverName ); typename kernelType::PermeabilityAccessors permAccessors( elemManager, solverName ); kernelType kernel( numPhases, rankOffset, stencilWrapper, dofNumberAccessor, - flowAccessors, capPressureAccessors, permAccessors, + flowAccessors, fluidAccessors, capPressureAccessors, permAccessors, dt, localMatrix, localRhs, hasCapPressure, useTotalMassEquation ); kernelType::template launch< POLICY >( stencilWrapper.size(), kernel ); } @@ -726,7 +732,7 @@ class PhaseMobilityKernel { public: - //using Base = isothermalCompositionalMultiphaseBaseKernels::PropertyKernelBase< NUM_COMP >; + //using Base = MultiphaseFluidAccessors::PropertyKernelBase< NUM_COMP >; /// Compile time value for the number of phases static constexpr integer numPhase = NUM_PHASE; @@ -786,10 +792,10 @@ class PhaseMobilityKernel for( integer ip = 0; ip < numPhase; ++ip ) { - real64 const density = m_phaseDens[ei][0][ip]; - real64 const dDens_dP = m_dPhaseDens[ei][0][ip]; - real64 const viscosity = m_phaseVisc[ei][0][ip]; - real64 const dVisc_dP = m_dPhaseVisc[ei][0][ip]; + real64 const density = m_phaseDens[ei][ip]; + real64 const dDens_dP = m_dPhaseDens[ei][ip]; + real64 const viscosity = m_phaseVisc[ei][ip]; + real64 const dVisc_dP = m_dPhaseVisc[ei][ip]; real64 const relPerm = m_phaseRelPerm[ei][0][ip]; @@ -800,7 +806,7 @@ class PhaseMobilityKernel for( integer jp = 0; jp < numPhase; ++jp ) // check if we need numPhase or numPhase-1 derivatives { - real64 const dRelPerm_dS = dPhaseRelPerm_dPhaseVolFrac[ei][0][ip][jp]; + real64 const dRelPerm_dS = m_dPhaseRelPerm_dPhaseVolFrac[ei][0][ip][jp]; dPhaseMob[ip][Deriv::dS+jp] = dRelPerm_dS * density / viscosity; } From 2d4f8971d222d8b0dbf377172ab1789a96a27d47 Mon Sep 17 00:00:00 2001 From: Ammara-14 Date: Wed, 21 Aug 2024 17:37:55 -0700 Subject: [PATCH 023/104] made minor fixes to make the code compile in release mode - thanks to Bertrand Denel for pointing them out --- .../physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index 9d3594d71f8..9ccee0eabe0 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -501,7 +501,7 @@ void ImmiscibleMultiphaseFlow::assembleSystem( real64 const GEOS_UNUSED_PARAM( t CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) { - GEOS_MARK_FUNCTION; // TODO Ralph + GEOS_MARK_FUNCTION; assembleAccumulationTerm( domain, dofManager, @@ -517,7 +517,7 @@ void ImmiscibleMultiphaseFlow::assembleSystem( real64 const GEOS_UNUSED_PARAM( t } -// This part of the code "assembleAccumulationTerm" is added by Ammar along with the comments. + void ImmiscibleMultiphaseFlow::assembleAccumulationTerm( DomainPartition & domain, DofManager const & dofManager, @@ -560,7 +560,7 @@ void ImmiscibleMultiphaseFlow::assembleAccumulationTerm( DomainPartition & domai // The line below is to be used if we want to use the total mass flux formulation //BitFlags< ElementBasedAssemblyKernelFlags > m_kernelFlags = kernelFlags; - GEOS_MARK_FUNCTION; + integer const numElems = subRegion.size(); forAll< parallelDevicePolicy<> >( @@ -620,7 +620,7 @@ void ImmiscibleMultiphaseFlow::assembleAccumulationTerm( DomainPartition & domai // complete - integer const numRows = numofPhases + 1; + integer const numRows = numofPhases; for( integer i = 0; i < numRows; ++i ) { From 3ecbf3d9cc2fb3119a764f805051ad7f6fcb0425 Mon Sep 17 00:00:00 2001 From: DENEL Bertrand Date: Mon, 16 Sep 2024 19:44:53 -0500 Subject: [PATCH 024/104] Added first version of a simplified two phase fluid model --- .../constitutive/CMakeLists.txt | 3 + .../fluid/twophasefluid/TwoPhaseFluid.cpp | 299 +++++++++++++++ .../fluid/twophasefluid/TwoPhaseFluid.hpp | 353 ++++++++++++++++++ .../twophasefluid/TwoPhaseFluidFields.hpp | 84 +++++ .../constitutiveTests/CMakeLists.txt | 5 +- .../constitutiveTests/testTwoPhaseFluid.cpp | 287 ++++++++++++++ 6 files changed, 1029 insertions(+), 2 deletions(-) create mode 100644 src/coreComponents/constitutive/fluid/twophasefluid/TwoPhaseFluid.cpp create mode 100644 src/coreComponents/constitutive/fluid/twophasefluid/TwoPhaseFluid.hpp create mode 100644 src/coreComponents/constitutive/fluid/twophasefluid/TwoPhaseFluidFields.hpp create mode 100644 src/coreComponents/unitTests/constitutiveTests/testTwoPhaseFluid.cpp diff --git a/src/coreComponents/constitutive/CMakeLists.txt b/src/coreComponents/constitutive/CMakeLists.txt index cae2dbc2e7f..79a03c56b53 100644 --- a/src/coreComponents/constitutive/CMakeLists.txt +++ b/src/coreComponents/constitutive/CMakeLists.txt @@ -102,6 +102,8 @@ set( constitutive_headers fluid/singlefluid/SingleFluidSelector.hpp fluid/singlefluid/SlurryFluidSelector.hpp fluid/singlefluid/ThermalCompressibleSinglePhaseFluid.hpp + fluid/twophasefluid/TwoPhaseFluid.hpp + fluid/twophasefluid/TwoPhaseFluidFields.hpp permeability/CarmanKozenyPermeability.hpp permeability/ConstantPermeability.hpp permeability/ExponentialDecayPermeability.hpp @@ -243,6 +245,7 @@ set( constitutive_sources fluid/singlefluid/SingleFluidBase.cpp fluid/singlefluid/SlurryFluidBase.cpp fluid/singlefluid/ThermalCompressibleSinglePhaseFluid.cpp + fluid/twophasefluid/TwoPhaseFluid.cpp permeability/CarmanKozenyPermeability.cpp permeability/ConstantPermeability.cpp permeability/ExponentialDecayPermeability.cpp diff --git a/src/coreComponents/constitutive/fluid/twophasefluid/TwoPhaseFluid.cpp b/src/coreComponents/constitutive/fluid/twophasefluid/TwoPhaseFluid.cpp new file mode 100644 index 00000000000..56325f2ef12 --- /dev/null +++ b/src/coreComponents/constitutive/fluid/twophasefluid/TwoPhaseFluid.cpp @@ -0,0 +1,299 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 Total, S.A + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2018-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/** + * @file TwoPhaseFluid.cpp + */ + +#include "TwoPhaseFluid.hpp" +#include "TwoPhaseFluidFields.hpp" + +#include "functions/FunctionManager.hpp" + + +namespace geos +{ + +using namespace dataRepository; + +namespace constitutive +{ + + +TwoPhaseFluid::TwoPhaseFluid( string const & name, Group * const parent ) + : ConstitutiveBase( name, parent ) +{ + registerWrapper( viewKeyStruct::phaseNamesString(), &m_phaseNames ). + setRTTypeName( rtTypes::CustomTypes::groupNameRefArray ). + setInputFlag( InputFlags::OPTIONAL ). + setDescription( "List of fluid phases" ); + + // 1) First option: specify PVT tables from one file per phase, read the files line by line, and populate the internal TableFunctions + registerWrapper( viewKeyStruct::tableFilesString(), &m_tableFiles ). + setInputFlag( InputFlags::OPTIONAL ). + setRestartFlags( RestartFlags::NO_WRITE ). + setDescription( "List of filenames with input PVT tables (one per phase)" ); + + // 2) Second option: specify TableFunction names for each phase, + registerWrapper( viewKeyStruct::densityTableNamesString(), &m_densityTableNames ). + setRTTypeName( rtTypes::CustomTypes::groupNameRefArray ). + setInputFlag( InputFlags::OPTIONAL ). + setDescription( "List of density TableFuncion names from the Function block. \n" + "The user must provide one TableFunction par phase, respecting the order provided in \"phaseNames\"." ); + + registerWrapper( viewKeyStruct::viscosityTableNamesString(), &m_viscosityTableNames ). + setRTTypeName( rtTypes::CustomTypes::groupNameRefArray ). + setInputFlag( InputFlags::OPTIONAL ). + setDescription( "List of viscosity TableFuncion names from the Function block. \n" + "The user must provide one TableFunction par phase, respecting the order provided in \"phaseNames\"." ); + + registerField( fields::twophasefluid::phaseDensity{}, &m_phaseDensity.value ); + registerField( fields::twophasefluid::dPhaseDensity{}, &m_phaseDensity.derivs ); + registerField( fields::twophasefluid::phaseDensity_n{}, &m_phaseDensity_n ); + + registerField( fields::twophasefluid::phaseViscosity{}, &m_phaseViscosity.value ); + registerField( fields::twophasefluid::dPhaseViscosity{}, &m_phaseViscosity.derivs ); +} + + +std::unique_ptr< ConstitutiveBase > +TwoPhaseFluid::deliverClone( string const & name, Group * const parent ) const +{ + return ConstitutiveBase::deliverClone( name, parent ); +} + + +void TwoPhaseFluid::resizeFields( localIndex const size, localIndex const numPts ) +{ + // Assume sole dependency on pressure, i.e. one derivative + m_phaseDensity.value.resize( size, numPts, 2 ); + m_phaseDensity.derivs.resize( size, numPts, 2, 1 ); + + m_phaseDensity_n.resize( size, numPts, 2 ); + + m_phaseViscosity.value.resize( size, numPts, 2 ); + m_phaseViscosity.derivs.resize( size, numPts, 2, 1 ); +} + + +void TwoPhaseFluid::allocateConstitutiveData( dataRepository::Group & parent, + localIndex const numConstitutivePointsPerParentIndex ) +{ + ConstitutiveBase::allocateConstitutiveData( parent, numConstitutivePointsPerParentIndex ); + resizeFields( parent.size(), numConstitutivePointsPerParentIndex ); +} + + +void TwoPhaseFluid::postInputInitialization() +{ + ConstitutiveBase::postInputInitialization(); + + // Input relationships can be provided either as text files or TableFunctions. + m_tableFiles.empty() ? readInputDataFromTableFunctions() : readInputDataFromFileTableFunctions(); + + + /* ??????? + // call to correctly set member array tertiary sizes on the 'main' material object + resizeFields( 0, 0 ); + + // set labels on array wrappers for plottable fields + setLabels(); + */ +} + + +void +TwoPhaseFluid::readTable( string const & fileName, + integer minRowLength, + array1d< array1d< real64 > > & data ) +{ + std::ifstream is( fileName ); + GEOS_ERROR_IF( !is.is_open(), + "TwoPhaseFluid: could not open file: " << fileName ); + + // Read line-by-line until eof + string str; + while( std::getline( is, str ) ) + { + // Remove whitespace and end-of-line characters, if any + str = stringutilities::trim( str, " \r" ); + + // Remove # and -- (Eclipse-style) comments + str = stringutilities::removeStringAndFollowingContent( str, "#" ); + str = stringutilities::removeStringAndFollowingContent( str, "--" ); + + // Skip empty or comment-only strings + if( str.empty() ) + continue; + + // Add and read a new line entry + array1d< real64 > newLine = stringutilities::fromStringToArray< real64 >( str ); + if( !newLine.empty() ) + { + data.emplace_back( std::move( newLine ) ); + } + } + + is.close(); + + for( localIndex i = 0; i < data.size(); ++i ) + { + GEOS_ERROR_IF( data[i].size() < minRowLength, + "TwoPhaseFluid: too few entries in row " << i << " of table " << fileName + << ", minimum " << std::to_string( minRowLength ) << " required" ); + } +} + + +void TwoPhaseFluid::fillData( integer const ip, + array1d< array1d< real64 > > const & tableValues ) +{ + array1d< array1d< real64 > > pressureCoords( 1 ); + pressureCoords[0].resize( tableValues.size() ); + array1d< real64 > density( tableValues.size() ); + array1d< real64 > viscosity( tableValues.size() ); + + for( localIndex i = 0; i < tableValues.size(); ++i ) + { + GEOS_THROW_IF_NE_MSG( tableValues[i].size(), 3, + getFullName() << ": three columns (pressure, density, and viscosity) are expected", + InputError ); + + pressureCoords[0][i] = tableValues[i][0]; + density[i] = tableValues[i][1]; + viscosity[i] = tableValues[i][2]; + } + + string const densityTableName = getName() + "DensityPhase" + GEOS_FMT( "{}", ip ); + string const viscosityTableName = getName() + "ViscosityPhase" + GEOS_FMT( "{}", ip ); + m_densityTableNames.emplace_back( densityTableName ); + m_viscosityTableNames.emplace_back( viscosityTableName ); + + FunctionManager & functionManager = FunctionManager::getInstance(); + + TableFunction & tableDensity = + dynamicCast< TableFunction & >( *functionManager.createChild( "TableFunction", densityTableName ) ); + tableDensity.setTableCoordinates( pressureCoords, { units::Pressure } ); + tableDensity.setTableValues( density, units::Density ); + tableDensity.setInterpolationMethod( TableFunction::InterpolationType::Linear ); + + TableFunction & tableViscosity = + dynamicCast< TableFunction & >( *functionManager.createChild( "TableFunction", viscosityTableName ) ); + tableViscosity.setTableCoordinates( pressureCoords, { units::Pressure } ); + tableViscosity.setTableValues( viscosity, units::Viscosity ); + tableViscosity.setInterpolationMethod( TableFunction::InterpolationType::Linear ); +} + + +void TwoPhaseFluid::readInputDataFromFileTableFunctions() +{ + // Check for ambiguous definition + GEOS_THROW_IF( !(m_densityTableNames.empty() && m_viscosityTableNames.empty()), + GEOS_FMT( "{}: input is redundant (both TableFunction names and text files)", getFullName() ), + InputError ); + + + // Check that we have exactly two table files (one per phase) + GEOS_THROW_IF_NE_MSG( m_tableFiles.size(), 2, + GEOS_FMT( "{}: expecting two table files (one per phase)", getFullName() ), + InputError ); + + array1d< array1d< real64 > > tableValues; + for( integer ip = 0; ip < 2; ++ip ) + { + tableValues.clear(); + readTable( m_tableFiles[ip], 3, tableValues ); + fillData( ip, tableValues ); + } +} + + +void TwoPhaseFluid::readInputDataFromTableFunctions() +{ + // Check for ambiguous definition + GEOS_THROW_IF( !m_tableFiles.empty(), + GEOS_FMT( "{}: input is redundant (both TableFunction names and text files)", getFullName() ), + InputError ); + + // Since we are considering a two phase fluid, we should have exactly 2 tables per property + GEOS_THROW_IF_NE_MSG( m_densityTableNames.size(), 2, + GEOS_FMT( "{}: one density table must be provided for each phase", getFullName() ), + InputError ); + + GEOS_THROW_IF_NE_MSG( m_viscosityTableNames.size(), 2, + GEOS_FMT( "{}: one viscosity table must be provided for each phase", getFullName() ), + InputError ); + + + FunctionManager const & functionManager = FunctionManager::getInstance(); + + for( integer iph = 0; iph < 2; ++iph ) + { + GEOS_THROW_IF( !functionManager.hasGroup( m_densityTableNames[iph] ), + GEOS_FMT( "{}: density table '{}' not found", getFullName(), m_densityTableNames[iph] ), + InputError ); + + GEOS_THROW_IF( !functionManager.hasGroup( m_viscosityTableNames[iph] ), + GEOS_FMT( "{}: viscosity table '{}' not found", getFullName(), m_viscosityTableNames[iph] ), + InputError ); + } +} + + +void TwoPhaseFluid::initializePostSubGroups() +{ + ConstitutiveBase::initializePostSubGroups(); + + FunctionManager const & functionManager = FunctionManager::getInstance(); + for( integer iph = 0; iph < 2; ++iph ) + { + // Grab the tables by name from the function manager, + // then add them in a list to create their table wrappers when needed + TableFunction const & densityTable = functionManager.getGroup< TableFunction const >( m_densityTableNames[iph] ); + m_densityTables.emplace_back( &densityTable ); + m_densityTableKernels.emplace_back( m_densityTables[iph]->createKernelWrapper() ); + + TableFunction const & viscosityTable = functionManager.getGroup< TableFunction const >( m_viscosityTableNames[iph] ); + m_viscosityTables.emplace_back( &viscosityTable ); + m_viscosityTableKernels.emplace_back( m_viscosityTables[iph]->createKernelWrapper() ); + } +} + + +TwoPhaseFluid::KernelWrapper +TwoPhaseFluid::createKernelWrapper() +{ + return KernelWrapper( m_densityTableKernels, + m_viscosityTableKernels, + m_phaseDensity.toView(), + m_phaseViscosity.toView()); +} + + +TwoPhaseFluid::KernelWrapper::KernelWrapper( + arrayView1d< TableFunction::KernelWrapper const > densityTables, + arrayView1d< TableFunction::KernelWrapper const > viscosityTables, + PhaseProp::ViewType phaseDensity, + PhaseProp::ViewType phaseViscosity ) + : m_densityTables( std::move( densityTables )), + m_viscosityTables( std::move( viscosityTables )), + m_phaseDensity( std::move( phaseDensity )), + m_phaseViscosity( std::move( phaseViscosity )) {} + + +REGISTER_CATALOG_ENTRY( ConstitutiveBase, TwoPhaseFluid, string const &, Group * const ) + +} // namespace constitutive +} // namespace geos diff --git a/src/coreComponents/constitutive/fluid/twophasefluid/TwoPhaseFluid.hpp b/src/coreComponents/constitutive/fluid/twophasefluid/TwoPhaseFluid.hpp new file mode 100644 index 00000000000..f870ac0c73e --- /dev/null +++ b/src/coreComponents/constitutive/fluid/twophasefluid/TwoPhaseFluid.hpp @@ -0,0 +1,353 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 Total, S.A + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2018-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/** + * @file TwoPhaseFluid.hpp + */ + +#ifndef GEOS_CONSTITUTIVE_FLUID_TWOPHASEFLUID_TWOPHASEFLUID_HPP_ +#define GEOS_CONSTITUTIVE_FLUID_TWOPHASEFLUID_TWOPHASEFLUID_HPP_ + +#include "common/DataLayouts.hpp" +#include "functions/TableFunction.hpp" +#include "constitutive/ConstitutiveBase.hpp" + +#include "constitutive/fluid/multifluid/Layouts.hpp" +#include "constitutive/fluid/multifluid/MultiFluidUtils.hpp" + +#include "constitutive/ConstitutivePassThruHandler.hpp" + + +namespace geos +{ +namespace constitutive +{ + +class TwoPhaseFluid : public ConstitutiveBase +{ +public: + + TwoPhaseFluid( string const & name, + Group * const parent ); + + virtual std::unique_ptr< ConstitutiveBase > + deliverClone( string const & name, + Group * const parent ) const override; + + virtual void allocateConstitutiveData( dataRepository::Group & parent, + localIndex const numConstitutivePointsPerParentIndex ) override; + + /** + * @name Static Factory Catalog members and functions + */ + ///@{ + + /// string name to use for this class in the catalog + static constexpr auto m_catalogNameString = "TwoPhaseFluid"; + + /** + * @brief Static catalog string + * @return A string that is used to register/lookup this class in the registry + */ + static std::string catalogName() { return m_catalogNameString; } + + /** + * @brief Get catalog name + * @return Name string + */ + virtual string getCatalogName() const override { return catalogName(); } + + ///@} + + + + /** + * @brief Getter for the fluid phase names + * @return an array storing the phase names + */ + arrayView1d< string const > phaseNames() const { return m_phaseNames; } + + struct viewKeyStruct : ConstitutiveBase::viewKeyStruct + { + static constexpr char const * tableFilesString() { return "tableFiles"; } + static constexpr char const * phaseNamesString() { return "phaseNames"; } + static constexpr char const * densityTableNamesString() { return "densityTableNames"; } + static constexpr char const * viscosityTableNamesString() { return "viscosityTableNames"; } + }; + + arrayView3d< real64 const, multifluid::USD_PHASE > phaseDensity_n() const + { return m_phaseDensity_n; } + + arrayView3d< real64 const, multifluid::USD_PHASE > phaseDensity() const + { return m_phaseDensity.value; } + + arrayView4d< real64 const, multifluid::USD_PHASE_DC > dPhaseDensity() const + { return m_phaseDensity.derivs; } + + arrayView3d< real64 const, multifluid::USD_PHASE > phaseViscosity() const + { return m_phaseViscosity.value; } + + arrayView4d< real64 const, multifluid::USD_PHASE_DC > dPhaseViscosity() const + { return m_phaseViscosity.derivs; } + + using PhaseProp = MultiFluidVar< real64, 3, constitutive::multifluid::LAYOUT_PHASE, constitutive::multifluid::LAYOUT_PHASE_DC >; + + + class KernelWrapper + { +public: + + /// @cond DO_NOT_DOCUMENT + /// We need these SMFs to avoid host-device errors with CUDA. + KernelWrapper() = default; + KernelWrapper( KernelWrapper const & ) = default; + KernelWrapper & operator=( KernelWrapper const & ) = default; + KernelWrapper & operator=( KernelWrapper && ) = default; + /// @endcond + + /** + * @brief Get number of elements in this wrapper. + * @return number of elements + */ + GEOS_HOST_DEVICE + GEOS_FORCE_INLINE + localIndex numElems() const { return m_phaseDensity.value.size( 0 ); } + + /** + * @brief Get number of gauss points per element. + * @return number of gauss points per element + */ + GEOS_HOST_DEVICE + GEOS_FORCE_INLINE + localIndex numGauss() const { return m_phaseDensity.value.size( 1 ); } + + + GEOS_HOST_DEVICE + void compute( real64 const pressure, + PhaseProp::SliceType const phaseDensity, + PhaseProp::SliceType const phaseViscosity ) const; + + GEOS_HOST_DEVICE + void update( localIndex const k, + localIndex const q, + real64 const pressure ) const; + +private: + + friend class TwoPhaseFluid; + + /** + * @brief Constructor for the class doing in-kernel two-phase fluid updates + * @param[in] densityTables density tables + * @param[in] viscosityTables viscosity tables + * @param[in] phaseDensity phase densities (+ derivatives) in the cell + * @param[in] phaseViscosity phase viscosities (+ derivatives) in the cell + */ + KernelWrapper( + arrayView1d< TableFunction::KernelWrapper const > densityTables, + arrayView1d< TableFunction::KernelWrapper const > viscosityTables, + PhaseProp::ViewType phaseDensity, + PhaseProp::ViewType phaseViscosity ); + + +protected: + + KernelWrapper( + arrayView1d< TableFunction::KernelWrapper const > densityTables, + arrayView1d< TableFunction::KernelWrapper const > viscosityTables + ); + + /// Table kernel wrappers to interpolate in the two phase (\rho vs p) tables + arrayView1d< TableFunction::KernelWrapper const > m_densityTables; + + /// Table kernel wrappers to interpolate in the two phase (\mu vs p) tables + arrayView1d< TableFunction::KernelWrapper const > m_viscosityTables; + + /** + * @brief Utility function to compute densities as a function of pressure (keeping derivatives) + * @param[in] pressure pressure in the cell + * @param[out] phaseDensity the phase density in the cell (+ derivatives) + */ + GEOS_HOST_DEVICE + void computeDensities( real64 const pressure, + PhaseProp::SliceType const & phaseDensity ) const; + + /** + * @brief Utility function to compute viscosities as a function of pressure (keeping derivatives) + * @param[in] pressure pressure in the cell + * @param[out] phaseViscosity the phase viscosities in the cell (+ derivatives) + */ + GEOS_HOST_DEVICE + void computeViscosities( real64 const pressure, + PhaseProp::SliceType const & phaseViscosity ) const; + + /// Views on the phase properties + PhaseProp::ViewType m_phaseDensity; + PhaseProp::ViewType m_phaseViscosity; + + }; //class KernelWrapper + + + array1d< string > m_phaseNames; + + + path_array m_tableFiles; + + /// Names of the density tables (one per phase) + array1d< string > m_densityTableNames; + + /// Names of the viscosity tables (one per phase) + array1d< string > m_viscosityTableNames; + + PhaseProp m_phaseDensity; + PhaseProp m_phaseViscosity; + + /// Backup data + array3d< real64, multifluid::LAYOUT_PHASE > m_phaseDensity_n; + + + virtual void resizeFields( localIndex const size, localIndex const numPts ); + + virtual void postInputInitialization() override; + + virtual void initializePostSubGroups() override; + + /// Table kernel wrappers to interpolate (\rho vs p) tables + array1d< TableFunction const * > m_densityTables; + /// Table kernel wrappers of m_densityTables + array1d< TableFunction::KernelWrapper > m_densityTableKernels; + + /// Table kernel wrappers to interpolate (\mu vs p) tables + array1d< TableFunction const * > m_viscosityTables; + /// Table kernel wrappers of m_viscosityTables + array1d< TableFunction::KernelWrapper > m_viscosityTableKernels; + + KernelWrapper createKernelWrapper(); + + +private: + void readInputDataFromTableFunctions(); + void readInputDataFromFileTableFunctions(); + + /** + * @brief Fill the fluid data (pressure, density, viscosity) + * @param[in] ip the index of the phase + * @param[in] tableValues the values in the fluid table + */ + void fillData( integer const ip, + array1d< array1d< real64 > > const & tableValues ); + + /** + * @brief Read a table from file and check its row length + * @param[in] fileName the name of the file + * @param[in] minRowLength the expected minimum row length (typically 3: pressure, density, viscosity) + * @param[out] data the data from the table + */ + static void + readTable( string const & fileName, + integer minRowLength, + array1d< array1d< real64 > > & data ); +}; + + +GEOS_HOST_DEVICE +GEOS_FORCE_INLINE +void TwoPhaseFluid::KernelWrapper:: + computeDensities( real64 const pressure, + PhaseProp::SliceType const & phaseDensity ) const +{ + using Deriv = constitutive::multifluid::DerivativeOffset; + + LvArray::forValuesInSlice( phaseDensity.derivs, []( real64 & val ) { val = 0.0; } ); + + for( integer iph = 0; iph < 2; ++iph ) + { + // interpolate in the table to get the phase density and derivatives + real64 dPhaseDens_dPres = 0.0; + + phaseDensity.value[iph] = m_densityTables[iph].compute( &pressure, &dPhaseDens_dPres ); + phaseDensity.derivs[iph][Deriv::dP] = dPhaseDens_dPres; + } +} + + +GEOS_HOST_DEVICE +GEOS_FORCE_INLINE +void TwoPhaseFluid::KernelWrapper:: + computeViscosities( real64 const pressure, + PhaseProp::SliceType const & phaseViscosity ) const +{ + using Deriv = constitutive::multifluid::DerivativeOffset; + + LvArray::forValuesInSlice( phaseViscosity.derivs, []( real64 & val ) { val = 0.0; } ); + + for( integer iph = 0; iph < 2; ++iph ) + { + // interpolate in the table to get the phase viscosity and derivatives + real64 dPhaseVisc_dPres = 0.0; + phaseViscosity.value[iph] = m_viscosityTables[iph].compute( &pressure, &dPhaseVisc_dPres ); + phaseViscosity.derivs[iph][Deriv::dP] = dPhaseVisc_dPres; + } +} + + +GEOS_HOST_DEVICE +GEOS_FORCE_INLINE +void TwoPhaseFluid::KernelWrapper:: + compute( real64 const pressure, + PhaseProp::SliceType const phaseDensity, + PhaseProp::SliceType const phaseViscosity ) const +{ + computeDensities( pressure, + phaseDensity ); + + computeViscosities( pressure, + phaseViscosity ); +} + + +GEOS_HOST_DEVICE +GEOS_FORCE_INLINE +void TwoPhaseFluid::KernelWrapper:: + update( localIndex const k, + localIndex const q, + real64 const pressure + ) const +{ + compute( pressure, + m_phaseDensity( k, q ), + m_phaseViscosity( k, q ) ); +} + + +template< typename LAMBDA > +void constitutiveUpdatePassThru( TwoPhaseFluid const & fluid, + LAMBDA && lambda ) +{ + ConstitutivePassThruHandler< TwoPhaseFluid >::execute( fluid, std::forward< LAMBDA >( lambda ) ); +} + + +template< typename LAMBDA > +void constitutiveUpdatePassThru( TwoPhaseFluid & fluid, + LAMBDA && lambda ) +{ + ConstitutivePassThruHandler< TwoPhaseFluid >::execute( fluid, std::forward< LAMBDA >( lambda ) ); +} + +} // namespace constitutive +} // namespace geos + +#endif // GEOS_CONSTITUTIVE_FLUID_TWOPHASEFLUID_TWOPHASEFLUID_HPP_ diff --git a/src/coreComponents/constitutive/fluid/twophasefluid/TwoPhaseFluidFields.hpp b/src/coreComponents/constitutive/fluid/twophasefluid/TwoPhaseFluidFields.hpp new file mode 100644 index 00000000000..9191deebd5d --- /dev/null +++ b/src/coreComponents/constitutive/fluid/twophasefluid/TwoPhaseFluidFields.hpp @@ -0,0 +1,84 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 Total, S.A + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2018-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/** + * @file TwoPhaseFluidFields.hpp + */ + +#ifndef GEOS_CONSTITUTIVE_FLUID_TWOPHASEFLUIDFIELDS_HPP_ +#define GEOS_CONSTITUTIVE_FLUID_TWOPHASEFLUIDFIELDS_HPP_ + +#include "constitutive/fluid/multifluid/Layouts.hpp" +#include "mesh/MeshFields.hpp" + + +namespace geos +{ + +namespace fields +{ + +namespace twophasefluid +{ + +using array3dLayoutPhase = array3d< real64, constitutive::multifluid::LAYOUT_PHASE >; +using array4dLayoutPhase_d = array4d< real64, constitutive::multifluid::LAYOUT_PHASE_DC >; + +DECLARE_FIELD( phaseDensity, + "phaseDensity", + array3dLayoutPhase, + 0, + LEVEL_0, + WRITE_AND_READ, + "Phase density" ); + +DECLARE_FIELD( phaseDensity_n, + "phaseDensity_n", + array3dLayoutPhase, + 0, + NOPLOT, + WRITE_AND_READ, + "Phase density at the previous converged time step" ); + +DECLARE_FIELD( dPhaseDensity, + "dPhaseDensity", + array4dLayoutPhase_d, + 0, + NOPLOT, + NO_WRITE, + "Derivative of phase density with respect to pressure" ); + +DECLARE_FIELD( phaseViscosity, + "phaseViscosity", + array3dLayoutPhase, + 0, + LEVEL_0, + WRITE_AND_READ, + "Phase viscosity" ); + +DECLARE_FIELD( dPhaseViscosity, + "dPhaseViscosity", + array4dLayoutPhase_d, + 0, + NOPLOT, + NO_WRITE, + "Derivative of phase viscosity with respect to pressure" ); + +} // namespace twophasefluid + +} // namespace constitutive +} // namespace geos + +#endif // GEOS_CONSTITUTIVE_FLUID_TWOPHASEFLUIDFIELDS_HPP_ diff --git a/src/coreComponents/unitTests/constitutiveTests/CMakeLists.txt b/src/coreComponents/unitTests/constitutiveTests/CMakeLists.txt index 24fb4d17cef..46bbeba7853 100644 --- a/src/coreComponents/unitTests/constitutiveTests/CMakeLists.txt +++ b/src/coreComponents/unitTests/constitutiveTests/CMakeLists.txt @@ -8,7 +8,8 @@ set( gtest_geosx_tests testMultiFluidDeadOil.cpp testMultiFluidLiveOil.cpp testRelPerm.cpp - testRelPermHysteresis.cpp ) + testRelPermHysteresis.cpp + testTwoPhaseFluid.cpp ) set( gtest_triaxial_xmls testTriaxial_druckerPragerExtended.xml @@ -110,4 +111,4 @@ foreach(test ${gtest_reactivefluid_xmls}) get_filename_component( test_name ${test} NAME_WE ) geos_add_test( NAME ${test_name} COMMAND testReactiveFluid -i ${CMAKE_CURRENT_LIST_DIR}/${test} ) -endforeach() \ No newline at end of file +endforeach() diff --git a/src/coreComponents/unitTests/constitutiveTests/testTwoPhaseFluid.cpp b/src/coreComponents/unitTests/constitutiveTests/testTwoPhaseFluid.cpp new file mode 100644 index 00000000000..b25c569b5d4 --- /dev/null +++ b/src/coreComponents/unitTests/constitutiveTests/testTwoPhaseFluid.cpp @@ -0,0 +1,287 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 Total, S.A + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2018-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +#include "mainInterface/GeosxState.hpp" +#include "mainInterface/initialization.hpp" + +#include "constitutive/fluid/twophasefluid/TwoPhaseFluid.hpp" +#include "constitutive/fluid/twophasefluid/TwoPhaseFluidFields.hpp" + +// Only for fill +#include "unitTests/constitutiveTests/MultiFluidTest.hpp" + +// Only for initializeTable +#include "unitTests/constitutiveTests/constitutiveTestHelpers.hpp" + + +using namespace geos; +using namespace geos::testing; +using namespace geos::constitutive; +using namespace geos::dataRepository; /// Only for group definition + + +static constexpr char const * tableContentPhase0 = "# Pg(Pa) Dens(kg/m3) Visc(Pa.s)\n" + "0.22 0.40203 40203\n" + "0.3 0.31311 31311\n" + "0.5 0.22423 22423\n" + "0.6 0.15011 15011\n" + "0.8 0.04224 4224\n" + "1.0 0.00603 603"; + +static constexpr char const * tableContentPhase1 = "# Pg(Pa) Dens(kg/m3) Visc(Pa.s)\n" + "1.22 0.40203 0.22\n" + "1.3 0.31311 0.22\n" + "1.5 0.22423 0.22\n" + "1.6 0.15011 0.22\n" + "1.8 0.04224 0.22\n" + "2.0 0.00603 0.22"; + +template< bool FROM_TABLE > +class TwoPhaseFluidTest : public ConstitutiveTestBase< TwoPhaseFluid > +{ +public: + + TwoPhaseFluidTest() + { + if constexpr (!FROM_TABLE) + { + writeTableToFile( "phase0.txt", tableContentPhase0 ); + writeTableToFile( "phase1.txt", tableContentPhase1 ); + } + + m_parent.resize( 1 ); + string const fluidName = GEOS_FMT( "fluid{}", (FROM_TABLE ? "Tables" : "Files")); + m_model = makeTwoPhaseFluid( fluidName, m_parent ); + + m_parent.initialize(); + m_parent.initializePostInitialConditions(); + } + + ~TwoPhaseFluidTest() + { + if constexpr (!FROM_TABLE) + { + removeFile( "phase0.txt" ); + removeFile( "phase1.txt" ); + } + } + + constitutive::TwoPhaseFluid & getFluid() const { return *m_model; } + + dataRepository::Group & getParent() { return m_parent; } + + + void testDerivatives( constitutive::TwoPhaseFluid & fluid, + dataRepository::Group * parent, + real64 const pressure, + real64 const perturbParameter, + real64 const relTol, + real64 const absTol = std::numeric_limits< real64 >::max() ) + { + auto const & phaseNames = fluid.getReference< string_array >( TwoPhaseFluid::viewKeyStruct::phaseNamesString() ); + + arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > phaseDensity; + arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > phaseViscosity; + arrayView4d< real64 const, constitutive::multifluid::USD_PHASE_DC > dPhaseDensity_dPressure; + arrayView4d< real64 const, constitutive::multifluid::USD_PHASE_DC > dPhaseViscosity_dPressure; + + // create a clone of the fluid to run updates on + string const fluidCopyName = fluid.getName() + "Copy"; + std::unique_ptr< constitutive::ConstitutiveBase > fluidCopyPtr = fluid.deliverClone( fluidCopyName, parent ); + constitutive::TwoPhaseFluid & fluidCopy = dynamicCast< constitutive::TwoPhaseFluid & >( *fluidCopyPtr ); + fluidCopy.initializePostSubGroups(); + + fluid.allocateConstitutiveData( fluid.getParent(), 1 ); + fluidCopy.allocateConstitutiveData( fluid.getParent(), 1 ); + + // extract data views from both fluids +#define GET_FLUID_DATA( FLUID, TRAIT ) \ + FLUID.getReference< TRAIT::type >( TRAIT::key() )[0][0] + + constitutive::MultiFluidVarSlice< real64, 1, constitutive::multifluid::USD_PHASE - 2, constitutive::multifluid::USD_PHASE_DC - 2 > phaseVisc { + GET_FLUID_DATA( fluid, fields::twophasefluid::phaseViscosity ), + GET_FLUID_DATA( fluid, fields::twophasefluid::dPhaseViscosity ) + }; + + constitutive::MultiFluidVarSlice< real64, 1, constitutive::multifluid::USD_PHASE - 2, constitutive::multifluid::USD_PHASE_DC - 2 > phaseDens { + GET_FLUID_DATA( fluid, fields::twophasefluid::phaseDensity ), + GET_FLUID_DATA( fluid, fields::twophasefluid::dPhaseDensity ) + }; + + auto const & phaseDensCopy = GET_FLUID_DATA( fluidCopy, fields::twophasefluid::phaseDensity ); + auto const & phaseViscCopy = GET_FLUID_DATA( fluidCopy, fields::twophasefluid::phaseViscosity ); +#undef GET_FLUID_DATA + + + // set the original fluid state to current + constitutive::constitutiveUpdatePassThru( fluid, [&] ( auto & castedFluid ) + { + typename TYPEOFREF( castedFluid ) ::KernelWrapper fluidWrapper = castedFluid.createKernelWrapper(); + fluidWrapper.update( 0, 0, pressure ); + } ); + + // now perturb variables and update the copied fluid's state + constitutive::constitutiveUpdatePassThru( fluidCopy, [&] ( auto & castedFluid ) + { + using Deriv = constitutive::multifluid::DerivativeOffset; + + typename TYPEOFREF( castedFluid ) ::KernelWrapper fluidWrapper = castedFluid.createKernelWrapper(); + + // to be able to use the checkDerivative utility function, we have to invert the layout + auto dPhaseDens = invertLayout( phaseDens.derivs.toSliceConst(), 2, 1 ); + auto dPhaseVisc = invertLayout( phaseVisc.derivs.toSliceConst(), 2, 1 ); + + // update pressure and check derivatives + real64 const dP = perturbParameter * (pressure + perturbParameter); + fluidWrapper.update( 0, 0, pressure + dP ); + + checkDerivative( phaseDensCopy.toSliceConst(), phaseDens.value.toSliceConst(), dPhaseDens[Deriv::dP].toSliceConst(), + dP, relTol, absTol, "phaseDens", "Pressure", phaseNames ); + checkDerivative( phaseViscCopy.toSliceConst(), phaseVisc.value.toSliceConst(), dPhaseVisc[Deriv::dP].toSliceConst(), + dP, relTol, absTol, "phaseVisc", "Pressure", phaseNames ); + } ); + } // void testDerivatives + + +protected: + static void writeTableToFile( string const & fileName, char const * content ) + { + std::ofstream os( fileName ); + ASSERT_TRUE( os.is_open() ); + os << content; + os.close(); + } + + static void removeFile( string const & fileName ) + { + int const ret = std::remove( fileName.c_str() ); + ASSERT_TRUE( ret == 0 ); + } + + +private: + static TwoPhaseFluid * makeTwoPhaseFluid( string const & name, Group & parent ); + +}; // class TwoPhaseFluidTest + + +template<> +TwoPhaseFluid * TwoPhaseFluidTest< true >::makeTwoPhaseFluid( string const & name, Group & parent ) +{ + // 1D table with linear interpolation + localIndex constexpr Naxis = 6; + localIndex constexpr NaxisSingle = 1; + + array1d< real64_array > densityCoordPhase0( 1 ); + fill< Naxis >( densityCoordPhase0[0], { 0.22, 0.3, 0.5, 0.6, 0.8, 1.0 } ); + real64_array densityValuesPhase0; + fill< Naxis >( densityValuesPhase0, { 0.40203, 0.31311, 0.22423, 0.15011, 0.04224, 0.00603 } ); + + array1d< real64_array > densityCoordPhase1( 1 ); + fill< Naxis >( densityCoordPhase1[0], { 1.22, 1.3, 1.5, 1.6, 1.8, 2.0 } ); + real64_array densityValuesPhase1; + fill< Naxis >( densityValuesPhase1, { 0.40203, 0.31311, 0.22423, 0.15011, 0.04224, 0.00603 } ); + + + array1d< real64_array > viscosityCoordPhase0( 1 ); + fill< Naxis >( viscosityCoordPhase0[0], { 0.22, 0.3, 0.5, 0.6, 0.8, 1.0 } ); + real64_array viscosityValuesPhase0; + fill< Naxis >( viscosityValuesPhase0, { 40203, 31311, 22423, 15011, 4224, 603 } ); + + array1d< real64_array > viscosityCoordPhase1( 1 ); + fill< NaxisSingle >( viscosityCoordPhase1[0], { 0.22 } ); + real64_array viscosityValuesPhase1; + fill< NaxisSingle >( viscosityValuesPhase1, { 45 } ); + + initializeTable( "densityTablePhase0", densityCoordPhase0, densityValuesPhase0 ); + initializeTable( "densityTablePhase1", densityCoordPhase1, densityValuesPhase1 ); + initializeTable( "viscosityTablePhase0", viscosityCoordPhase0, viscosityValuesPhase0 ); + initializeTable( "viscosityTablePhase1", viscosityCoordPhase1, viscosityValuesPhase1 ); + + + // 2) Set up the constitutive model + TwoPhaseFluid & fluid = parent.registerGroup< TwoPhaseFluid >( name ); + + string_array & phaseNames = fluid.getReference< string_array >( TwoPhaseFluid::viewKeyStruct::phaseNamesString() ); + fill< 2 >( phaseNames, {"oil", "water"} ); + + string_array & densityTableNames = fluid.getReference< string_array >( TwoPhaseFluid::viewKeyStruct::densityTableNamesString() ); + fill< 2 >( densityTableNames, {"densityTablePhase0", "densityTablePhase1"} ); + + string_array & viscosityTableNames = fluid.getReference< string_array >( TwoPhaseFluid::viewKeyStruct::viscosityTableNamesString() ); + fill< 2 >( viscosityTableNames, {"viscosityTablePhase0", "viscosityTablePhase1"} ); + + fluid.postInputInitializationRecursive(); + //fluid.initialize(); // to test all the checks???... this one is redoing the postInput + return &fluid; +} + + +template<> +TwoPhaseFluid * TwoPhaseFluidTest< false >::makeTwoPhaseFluid( string const & name, Group & parent ) +{ + TwoPhaseFluid & fluid = parent.registerGroup< TwoPhaseFluid >( name ); + + path_array & tableNames = fluid.getReference< path_array >( TwoPhaseFluid::viewKeyStruct::tableFilesString() ); + fill< 2 >( tableNames, {"phase0.txt", "phase1.txt"} ); + + fluid.postInputInitializationRecursive(); + return &fluid; +} + + + +using TwoPhaseFluidTestFromFiles = TwoPhaseFluidTest< false >; +using TwoPhaseFluidTestFromTables = TwoPhaseFluidTest< true >; + + +TEST_F( TwoPhaseFluidTestFromTables, testNumericalDerivative_initFromTables ) +{ + auto & fluid = getFluid(); + real64 constexpr eps = sqrt( std::numeric_limits< real64 >::epsilon()); + real64 constexpr relTol = 1.0e-8; + real64 constexpr absTol = 1.0e-8; + + for( real64 const pressure : { 0.55, 1.0, 10.0 } ) + { + testDerivatives( fluid, &getParent(), pressure, eps, relTol, absTol ); + } +} + + +TEST_F( TwoPhaseFluidTestFromFiles, testNumericalDerivative_initFromFiles ) +{ + auto & fluid = getFluid(); + real64 constexpr eps = sqrt( std::numeric_limits< real64 >::epsilon()); + real64 constexpr relTol = 1.0e-8; + real64 constexpr absTol = 1.0e-8; + + for( real64 const pressure : { 0.55, 1.0, 10.0 } ) + { + testDerivatives( fluid, &getParent(), pressure, eps, relTol, absTol ); + } +} + + +int main( int argc, char * * argv ) +{ + ::testing::InitGoogleTest( &argc, argv ); + + geos::GeosxState state( geos::basicSetup( argc, argv ) ); + int const result = RUN_ALL_TESTS(); + geos::basicCleanup(); + + return result; +} From 549629d6bd905cb8753062d746b4b388e9d824e7 Mon Sep 17 00:00:00 2001 From: DENEL Bertrand Date: Mon, 16 Sep 2024 20:09:50 -0500 Subject: [PATCH 025/104] Started modifications to use twoPhaseFluid model in the flow solver. --- .../fluidFlow/ImmiscibleMultiphaseFlow.cpp | 28 ++++++++++++++----- .../fluidFlow/ImmiscibleMultiphaseKernels.hpp | 18 +++++++++++- 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index 9ccee0eabe0..a2ceae9d613 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -36,6 +36,8 @@ #include "constitutive/ConstitutivePassThru.hpp" +#include "constitutive/fluid/twophasefluid/TwoPhaseFluid.hpp" + #include #if defined( __INTEL_COMPILER ) @@ -48,6 +50,7 @@ namespace geos using namespace dataRepository; using namespace constitutive; using namespace fields::immiscibleMultiphaseFlow; +using namespace immiscibleMultiphaseKernels; real64 computeDensityL ( real64 P ) { return (1.0e-6 * (P * P)); @@ -204,15 +207,26 @@ void ImmiscibleMultiphaseFlow::initializePreSubGroups() } ); } + void ImmiscibleMultiphaseFlow::updateFluidModel( ObjectManagerBase & dataGroup ) const { GEOS_MARK_FUNCTION; - // arrayView1d< real64 const > const pres = dataGroup.getField< fields::flow::pressure >(); - // arrayView1d< real64 const > const temp = dataGroup.getField< fields::flow::temperature >(); - GEOS_UNUSED_VAR( dataGroup ); + arrayView1d< real64 const > const pres = dataGroup.getField< fields::flow::pressure >(); + + TwoPhaseFluid & fluid = getConstitutiveModel< TwoPhaseFluid >( dataGroup, dataGroup.getReference< string >( viewKeyStruct::fluidNamesString() ) ); + + constitutiveUpdatePassThru( fluid, [&] ( auto & castedFluid ) + { + using FluidType = TYPEOFREF( castedFluid ); + typename FluidType::KernelWrapper fluidWrapper = castedFluid.createKernelWrapper(); + + FluidUpdateKernel::launch< parallelDevicePolicy<> >( dataGroup.size(),fluidWrapper, pres ); + } ); } + + void ImmiscibleMultiphaseFlow::updateRelPermModel( ObjectManagerBase & dataGroup ) const { GEOS_MARK_FUNCTION; @@ -518,7 +532,6 @@ void ImmiscibleMultiphaseFlow::assembleSystem( real64 const GEOS_UNUSED_PARAM( t - void ImmiscibleMultiphaseFlow::assembleAccumulationTerm( DomainPartition & domain, DofManager const & dofManager, CRSMatrixView< real64, globalIndex const > const & localMatrix, @@ -537,9 +550,10 @@ void ImmiscibleMultiphaseFlow::assembleAccumulationTerm( DomainPartition & domai { string const dofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); string const & solidName = subRegion.getReference< string >( viewKeyStruct::solidNamesString() ); + string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); // The line below needs to be used once we have a fluid model - // MultiFluidBase const & fluid = getConstitutiveModel< MultiFluidBase >( subRegion, fluidName ); + TwoPhaseFluid const & fluid = getConstitutiveModel< TwoPhaseFluid >( subRegion, fluidName ); CoupledSolidBase const & solid = getConstitutiveModel< CoupledSolidBase >( subRegion, solidName ); arrayView1d< real64 const > const pres = subRegion.getField< fields::flow::pressure >(); @@ -552,8 +566,8 @@ void ImmiscibleMultiphaseFlow::assembleAccumulationTerm( DomainPartition & domai arrayView2d< real64 const > const dPoro_dPres = solid.getDporosity_dPressure(); arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac= subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); // The two lines below need to be used once we have a fluid model - //arrayView3d< real64 const, immiscibleFlow::USD_PHASE > m_phaseDens = fluid.phaseDensity(); - //arrayView4d< real64 const, immiscibleFlow::USD_PHASE_DS > m_dPhaseDens = fluid.dPhaseDensity(); + arrayView3d< real64 const, multifluid::USD_PHASE > m_phaseDens = fluid.phaseDensity(); + arrayView4d< real64 const, multifluid::USD_PHASE_DC > m_dPhaseDens = fluid.dPhaseDensity(); arrayView2d< real64 const, immiscibleFlow::USD_PHASE > phaseDens = subRegion.getField< fields::immiscibleMultiphaseFlow::phaseDensity>(); arrayView2d< real64 const, immiscibleFlow::USD_PHASE > dPhaseDens = subRegion.getField< fields::immiscibleMultiphaseFlow::dPhaseDensity>(); arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const PhaseMass_n = subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseMass_n >(); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp index 63e562674cb..2d2090bd77e 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp @@ -874,7 +874,23 @@ class PhaseMobilityKernelFactory }; - +struct FluidUpdateKernel +{ + template< typename POLICY, typename FLUID_WRAPPER > + static void + launch( localIndex const size, + FLUID_WRAPPER const & fluidWrapper, + arrayView1d< real64 const > const & pres ) + { + forAll< POLICY >( size, [=] GEOS_HOST_DEVICE ( localIndex const k ) + { + for( localIndex q = 0; q < fluidWrapper.numGauss(); ++q ) + { + fluidWrapper.update( k, q, pres[k] ); + } + } ); + } +}; } // namesace immiscible multiphasekernels From 02287f74c7f361c1a197509ea6efcc56ced6041e Mon Sep 17 00:00:00 2001 From: Randolph Settgast Date: Tue, 17 Sep 2024 15:48:25 -0700 Subject: [PATCH 026/104] changes from commit that was removed --- host-configs/Stanford/ubuntu22.cmake | 44 +++++++++++++++++++ .../immiscible_2phaseFlow_1d.xml | 7 +++ 2 files changed, 51 insertions(+) create mode 100644 host-configs/Stanford/ubuntu22.cmake diff --git a/host-configs/Stanford/ubuntu22.cmake b/host-configs/Stanford/ubuntu22.cmake new file mode 100644 index 00000000000..39bca094e3e --- /dev/null +++ b/host-configs/Stanford/ubuntu22.cmake @@ -0,0 +1,44 @@ +# file: your-platform.cmake + +# detect host and name the configuration file +site_name(HOST_NAME) +set(CONFIG_NAME "ubuntu22" CACHE PATH "") +message("CONFIG_NAME = ${CONFIG_NAME}") + +# set paths to C, C++, and Fortran compilers. Note that while GEOS does not contain any Fortran code, +# some of the third-party libraries do contain Fortran code. Thus a Fortran compiler must be specified. +set(CMAKE_C_COMPILER "/usr/bin/gcc" CACHE PATH "") +set(CMAKE_CXX_COMPILER "/usr/bin/g++" CACHE PATH "") +set(CMAKE_Fortran_COMPILER "/usr/bin/gfortran" CACHE PATH "") +set(ENABLE_FORTRAN OFF CACHE BOOL "" FORCE) + +# enable MPI and set paths to compilers and executable. +# Note that the MPI compilers are wrappers around standard serial compilers. +# Therefore, the MPI compilers must wrap the appropriate serial compilers specified +# in CMAKE_C_COMPILER, CMAKE_CXX_COMPILER, and CMAKE_Fortran_COMPILER. +set(ENABLE_MPI ON CACHE BOOL "") +set(MPI_C_COMPILER "/usr/bin/mpicc" CACHE PATH "") +set(MPI_CXX_COMPILER "/usr/bin/mpicxx" CACHE PATH "") +set(MPI_Fortran_COMPILER "/usr/bin/mpifort" CACHE PATH "") +set(MPIEXEC "/usr/bin/mpirun" CACHE PATH "") + +# define the path to blas and lapack +#set( BLAS_LIBRARIES /home/rpiazza/lib/lapack-3.11.0-linux-x86_64/libblas.so CACHE PATH "" FORCE ) +#set( LAPACK_LIBRARIES /home/rpiazza/lib/lapack-3.11.0-linux-x86_64/liblapack.so CACHE PATH "" FORCE ) + +# disable CUDA and OpenMP +set(ENABLE_CUDA OFF CACHE BOOL "" FORCE) +set(ENABLE_OPENMP OFF CACHE BOOL "" FORCE) + +# enable PVTPackage +set(ENABLE_PVTPackage ON CACHE BOOL "" FORCE) + +# enable tests +set(ENABLE_GTEST_DEATH_TESTS ON CACHE BOOL "" FORCE ) + +# define the path to your compiled installation directory +set(GEOS_TPL_DIR "/home/rpiazza/two-phase/thirdPartyLibs/install-ubuntu22-debug" CACHE PATH "") +#set(GEOSX_TPL_DIR "${GEOSX_TPL_DIR}" CACHE PATH "" FORCE) +# let GEOS define some third party libraries information for you +#include(${CMAKE_CURRENT_LIST_DIR}/tpls.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/../tpls.cmake) diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscible_2phaseFlow_1d.xml b/inputFiles/immiscibleMultiphaseFlow/immiscible_2phaseFlow_1d.xml index ecbf73253af..35fec304eda 100644 --- a/inputFiles/immiscibleMultiphaseFlow/immiscible_2phaseFlow_1d.xml +++ b/inputFiles/immiscibleMultiphaseFlow/immiscible_2phaseFlow_1d.xml @@ -84,6 +84,13 @@ compressibility="5e-10" viscosibility="0.0"/> + + Date: Wed, 18 Sep 2024 19:24:50 -0500 Subject: [PATCH 027/104] Fixed fluid initialization in flow solver, updated xml input file. --- .../immiscible_2phaseFlow_1d.xml | 34 +++++++++++-- .../fluidFlow/ImmiscibleMultiphaseFlow.cpp | 24 ++++++--- .../fluidFlow/ImmiscibleMultiphaseKernels.hpp | 50 ++++++++++--------- 3 files changed, 75 insertions(+), 33 deletions(-) diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscible_2phaseFlow_1d.xml b/inputFiles/immiscibleMultiphaseFlow/immiscible_2phaseFlow_1d.xml index 35fec304eda..d7f3553331c 100644 --- a/inputFiles/immiscibleMultiphaseFlow/immiscible_2phaseFlow_1d.xml +++ b/inputFiles/immiscibleMultiphaseFlow/immiscible_2phaseFlow_1d.xml @@ -72,11 +72,39 @@ + materialList="{ fluid, rock, relperm }"/> + + + + + + + + + + - + + - + scale="3e6"/> + + + + diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index 9a71df6e7dc..6d1ab967999 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -293,16 +293,51 @@ void ImmiscibleMultiphaseFlow::updateCapPressureModel( ObjectManagerBase & dataG } } + void ImmiscibleMultiphaseFlow::updateFluidState( ElementSubRegionBase & subRegion ) const { GEOS_MARK_FUNCTION; updateFluidModel( subRegion ); + updatePhaseMass( subRegion ); updateRelPermModel( subRegion ); updatePhaseMobility( subRegion ); updateCapPressureModel( subRegion ); } + +void ImmiscibleMultiphaseFlow::updatePhaseMass( ElementSubRegionBase & subRegion ) const +{ + GEOS_MARK_FUNCTION; + + string const & solidName = subRegion.getReference< string >( viewKeyStruct::solidNamesString() ); + string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); + + TwoPhaseFluid const & fluid = getConstitutiveModel< TwoPhaseFluid >( subRegion, fluidName ); + CoupledSolidBase const & solid = getConstitutiveModel< CoupledSolidBase >( subRegion, solidName ); + + integer const numofPhases = 2; + arrayView1d< real64 const > const volume = subRegion.getElementVolume(); + arrayView2d< real64 const > const porosity = solid.getPorosity(); + + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac= subRegion.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); + arrayView3d< real64 const, multifluid::USD_PHASE > phaseDens = fluid.phaseDensity(); + arrayView2d< real64, immiscibleFlow::USD_PHASE > const phaseMass = subRegion.getField< fields::immiscibleMultiphaseFlow::phaseMass >(); + + // Might be needed for geomechanics????? if so, need to change the accumulation as well? + //arrayView1d< real64 > const deltaVolume = subRegion.getField< fields::flow::deltaVolume >(); + + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const ei ) + { + real64 const poreVolume = volume[ei] * porosity[ei][0]; + for( integer ip = 0; ip < 2; ++ip ) + { + phaseMass[ei][ip] = poreVolume * phaseVolFrac[ei][ip] * phaseDens[ei][0][ip]; + } + }); +} + + void ImmiscibleMultiphaseFlow::updatePhaseMobility( ObjectManagerBase & dataGroup ) const { GEOS_MARK_FUNCTION; @@ -431,6 +466,8 @@ void ImmiscibleMultiphaseFlow::initializeFluidState( MeshLevel & mesh, arrayView1d< real64 > const initTemp = subRegion.template getField< fields::flow::initialTemperature >(); initPres.setValues< parallelDevicePolicy<> >( pres ); initTemp.setValues< parallelDevicePolicy<> >( temp ); + + // TODO: Missing updatePhaseMass? } ); } @@ -620,19 +657,6 @@ void ImmiscibleMultiphaseFlow::assembleAccumulationTerm( DomainPartition & domai for( integer ip = 0; ip < numofPhases; ++ip ) { - - // The few lines of code below are to be used if we want to use free functions for the phase density (to test the derivatives) - // real64 const pressure = pres[ei]; - - // real64 phaseDens = computeDensityV ( pressure ); - // real64 dPhaseDens = computedDensitydPV ( pressure ); - - // if( ip == 1) - // { - // phaseDens = computeDensityL ( pressure ); - // dPhaseDens = computedDensitydPL ( pressure ); - //} - real64 const phaseMass = poreVolume * phaseVolFrac[ei][ip] * phaseDens[ei][0][ip]; real64 const phaseMass_n = PhaseMass_n[ei][ip]; @@ -1052,7 +1076,11 @@ void ImmiscibleMultiphaseFlow::saveConvergedState( ElementSubRegionBase & subReg subRegion.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction_n >(); phaseVolFrac_n.setValues< parallelDevicePolicy<> >( phaseVolFrac ); - + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseMass = + subRegion.getField< fields::immiscibleMultiphaseFlow::phaseMass >(); + arrayView2d< real64, immiscibleFlow::USD_PHASE > const phaseMass_n = + subRegion.getField< fields::immiscibleMultiphaseFlow::phaseMass_n >(); + phaseMass_n.setValues< parallelDevicePolicy<> >( phaseMass ); } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp index 83e0e0739c9..ce5164eb16b 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp @@ -206,6 +206,12 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase */ void updateFluidModel( ObjectManagerBase & dataGroup ) const; + /** + * @brief Function to update fluid mass + * @param subRegion subregion that contains the fields + */ + void updatePhaseMass( ElementSubRegionBase & subRegion ) const; + /** * @brief Update all relevant relperm models using current values of phase volume fraction * @param dataGroup the group storing the required fields From 98e2c14641938c9a265d2053d2a0756a92f75ffa Mon Sep 17 00:00:00 2001 From: DENEL Bertrand Date: Thu, 3 Oct 2024 18:54:29 -0500 Subject: [PATCH 038/104] Applied uncrustify formatting. --- .../fluidFlow/ImmiscibleMultiphaseFlow.cpp | 292 +++++++++--------- .../fluidFlow/ImmiscibleMultiphaseFlow.hpp | 4 +- .../ImmiscibleMultiphaseFlowFields.hpp | 2 +- .../fluidFlow/ImmiscibleMultiphaseKernels.hpp | 174 ++++++----- 4 files changed, 238 insertions(+), 234 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index 6d1ab967999..a0f0be788a2 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -53,23 +53,6 @@ using namespace constitutive; using namespace fields::immiscibleMultiphaseFlow; using namespace immiscibleMultiphaseKernels; -real64 computeDensityL ( real64 P ) { - return (1.0e-6 * (P * P)); -} - -real64 computedDensitydPL ( real64 P ) { - return (1.0e-6 * 2.0 * (P)); -} - -real64 computeDensityV ( real64 P ) { - return (1.0e-8 * (P * P)); -} - -real64 computedDensitydPV ( real64 P ) { - return (1.0e-8 * 2.0 * (P)); -} - - ImmiscibleMultiphaseFlow::ImmiscibleMultiphaseFlow( const string & name, Group * const parent ) @@ -181,7 +164,6 @@ void ImmiscibleMultiphaseFlow::setConstitutiveNames( ElementSubRegionBase & subR - string & relPermName = subRegion.registerWrapper< string >( viewKeyStruct::relPermNamesString() ). setPlotLevel( PlotLevel::NOPLOT ). setRestartFlags( RestartFlags::NO_WRITE ). @@ -236,8 +218,8 @@ void ImmiscibleMultiphaseFlow::updateFluidModel( ObjectManagerBase & dataGroup ) { using FluidType = TYPEOFREF( castedFluid ); typename FluidType::KernelWrapper fluidWrapper = castedFluid.createKernelWrapper(); - - FluidUpdateKernel::launch< parallelDevicePolicy<> >( dataGroup.size(),fluidWrapper, pres ); + + FluidUpdateKernel::launch< parallelDevicePolicy<> >( dataGroup.size(), fluidWrapper, pres ); } ); } @@ -323,18 +305,18 @@ void ImmiscibleMultiphaseFlow::updatePhaseMass( ElementSubRegionBase & subRegion arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac= subRegion.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); arrayView3d< real64 const, multifluid::USD_PHASE > phaseDens = fluid.phaseDensity(); arrayView2d< real64, immiscibleFlow::USD_PHASE > const phaseMass = subRegion.getField< fields::immiscibleMultiphaseFlow::phaseMass >(); - + // Might be needed for geomechanics????? if so, need to change the accumulation as well? //arrayView1d< real64 > const deltaVolume = subRegion.getField< fields::flow::deltaVolume >(); - + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const ei ) { - real64 const poreVolume = volume[ei] * porosity[ei][0]; - for( integer ip = 0; ip < 2; ++ip ) - { - phaseMass[ei][ip] = poreVolume * phaseVolFrac[ei][ip] * phaseDens[ei][0][ip]; - } - }); + real64 const poreVolume = volume[ei] * porosity[ei][0]; + for( integer ip = 0; ip < 2; ++ip ) + { + phaseMass[ei][ip] = poreVolume * phaseVolFrac[ei][ip] * phaseDens[ei][0][ip]; + } + } ); } @@ -344,17 +326,18 @@ void ImmiscibleMultiphaseFlow::updatePhaseMobility( ObjectManagerBase & dataGrou // note that the phase mobility computed here also includes phase density string const & fluidName = dataGroup.getReference< string >( viewKeyStruct::fluidNamesString() ); - TwoPhaseFluid const & fluid = getConstitutiveModel< TwoPhaseFluid >( dataGroup, fluidName ); + TwoPhaseFluid const & fluid = getConstitutiveModel< TwoPhaseFluid >( dataGroup, fluidName ); string const & relpermName = dataGroup.getReference< string >( viewKeyStruct::relPermNamesString() ); RelativePermeabilityBase const & relperm = getConstitutiveModel< RelativePermeabilityBase >( dataGroup, relpermName ); immiscibleMultiphaseKernels:: - PhaseMobilityKernelFactory:: - createAndLaunch< parallelDevicePolicy<> >( m_numPhases, - dataGroup, - fluid, - relperm ); } + PhaseMobilityKernelFactory:: + createAndLaunch< parallelDevicePolicy<> >( m_numPhases, + dataGroup, + fluid, + relperm ); +} void ImmiscibleMultiphaseFlow::initializeFluidState( MeshLevel & mesh, DomainPartition & GEOS_UNUSED_PARAM( domain ), @@ -371,7 +354,7 @@ void ImmiscibleMultiphaseFlow::initializeFluidState( MeshLevel & mesh, updateFluidModel( subRegion ); } ); - + // for some reason CUDA does not want the host_device lambda to be defined inside the generic lambda // I need the exact type of the subRegion for updateSolidflowProperties to work well. mesh.getElemManager().forElementSubRegions< CellElementSubRegion, @@ -571,7 +554,7 @@ void ImmiscibleMultiphaseFlow::assembleSystem( real64 const GEOS_UNUSED_PARAM( t CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) { - GEOS_MARK_FUNCTION; + GEOS_MARK_FUNCTION; assembleAccumulationTerm( domain, dofManager, @@ -611,80 +594,80 @@ void ImmiscibleMultiphaseFlow::assembleAccumulationTerm( DomainPartition & domai TwoPhaseFluid const & fluid = getConstitutiveModel< TwoPhaseFluid >( subRegion, fluidName ); CoupledSolidBase const & solid = getConstitutiveModel< CoupledSolidBase >( subRegion, solidName ); - //arrayView1d< real64 const > const pres = subRegion.getField< fields::flow::pressure >(); - integer const numofPhases = 2; - globalIndex const rankOffset = dofManager.rankOffset(); - arrayView1d< globalIndex const > const dofNumber = subRegion.getReference< array1d< globalIndex > >( dofKey ); - arrayView1d< integer const > const elemGhostRank= subRegion.ghostRank(); - arrayView1d< real64 const > const volume = subRegion.getElementVolume(); - arrayView2d< real64 const > const porosity = solid.getPorosity(); - arrayView2d< real64 const > const dPoro_dPres = solid.getDporosity_dPressure(); - arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac= subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); - arrayView3d< real64 const, multifluid::USD_PHASE > phaseDens = fluid.phaseDensity(); - arrayView4d< real64 const, multifluid::USD_PHASE_DC > dPhaseDens = fluid.dPhaseDensity(); - arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const PhaseMass_n = subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseMass_n >(); - - // The line below is to be used if we want to use the total mass flux formulation - //BitFlags< ElementBasedAssemblyKernelFlags > m_kernelFlags = kernelFlags; - - - integer const numElems = subRegion.size(); - forAll< parallelDevicePolicy<> >( - numElems, [=] GEOS_HOST_DEVICE ( localIndex const ei ) - { - if( elemGhostRank( ei ) >= 0 ) + //arrayView1d< real64 const > const pres = subRegion.getField< fields::flow::pressure >(); + integer const numofPhases = 2; + globalIndex const rankOffset = dofManager.rankOffset(); + arrayView1d< globalIndex const > const dofNumber = subRegion.getReference< array1d< globalIndex > >( dofKey ); + arrayView1d< integer const > const elemGhostRank= subRegion.ghostRank(); + arrayView1d< real64 const > const volume = subRegion.getElementVolume(); + arrayView2d< real64 const > const porosity = solid.getPorosity(); + arrayView2d< real64 const > const dPoro_dPres = solid.getDporosity_dPressure(); + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac= subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); + arrayView3d< real64 const, multifluid::USD_PHASE > phaseDens = fluid.phaseDensity(); + arrayView4d< real64 const, multifluid::USD_PHASE_DC > dPhaseDens = fluid.dPhaseDensity(); + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const PhaseMass_n = subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseMass_n >(); + + // The line below is to be used if we want to use the total mass flux formulation + //BitFlags< ElementBasedAssemblyKernelFlags > m_kernelFlags = kernelFlags; + + + integer const numElems = subRegion.size(); + forAll< parallelDevicePolicy<> >( + numElems, [=] GEOS_HOST_DEVICE ( localIndex const ei ) { - return; - } + if( elemGhostRank( ei ) >= 0 ) + { + return; + } - // setup - globalIndex dofIndices[2]{}; - real64 localResidual[2]{}; - real64 localJacobian[2][2]{}; + // setup + globalIndex dofIndices[2]{}; + real64 localResidual[2]{}; + real64 localJacobian[2][2]{}; - real64 const poreVolume = volume[ei] * porosity[ei][0]; - real64 const dPoreVolume_dPres = volume[ei] * dPoro_dPres[ei][0]; + real64 const poreVolume = volume[ei] * porosity[ei][0]; + real64 const dPoreVolume_dPres = volume[ei] * dPoro_dPres[ei][0]; - localIndex localRow = dofNumber[ei] - rankOffset; - - for( integer idof = 0; idof < 2; ++idof ) - { - dofIndices[idof] = dofNumber[ei] + idof; - } + localIndex localRow = dofNumber[ei] - rankOffset; - // compute accumulation + for( integer idof = 0; idof < 2; ++idof ) + { + dofIndices[idof] = dofNumber[ei] + idof; + } + // compute accumulation - for( integer ip = 0; ip < numofPhases; ++ip ) - { - real64 const phaseMass = poreVolume * phaseVolFrac[ei][ip] * phaseDens[ei][0][ip]; - real64 const phaseMass_n = PhaseMass_n[ei][ip]; - localResidual[ip] += phaseMass - phaseMass_n; + for( integer ip = 0; ip < numofPhases; ++ip ) + { + real64 const phaseMass = poreVolume * phaseVolFrac[ei][ip] * phaseDens[ei][0][ip]; + real64 const phaseMass_n = PhaseMass_n[ei][ip]; + + localResidual[ip] += phaseMass - phaseMass_n; - real64 const dPhaseMass_dP = dPoreVolume_dPres * phaseVolFrac[ei][ip] * phaseDens[ei][0][ip] + real64 const dPhaseMass_dP = dPoreVolume_dPres * phaseVolFrac[ei][ip] * phaseDens[ei][0][ip] + poreVolume * phaseVolFrac[ei][ip] * dPhaseDens[ei][0][ip][0]; - localJacobian[ip][0] += dPhaseMass_dP; + localJacobian[ip][0] += dPhaseMass_dP; - real64 const dPhaseMass_dS = poreVolume * phaseDens[ei][0][ip]; - - localJacobian[ip][1] += dPhaseMass_dS; - } + real64 const dPhaseMass_dS = poreVolume * phaseDens[ei][0][ip]; - // complete - - integer const numRows = numofPhases; + localJacobian[ip][1] += dPhaseMass_dS; + } - for( integer i = 0; i < numRows; ++i ) - { - localRhs[localRow + i] += localResidual[i]; - localMatrix.addToRow< serialAtomic >( localRow + i, - dofIndices, - localJacobian[i], - 2); - } + // complete - } ); + integer const numRows = numofPhases; + + for( integer i = 0; i < numRows; ++i ) + { + localRhs[localRow + i] += localResidual[i]; + localMatrix.addToRow< serialAtomic >( localRow + i, + dofIndices, + localJacobian[i], + 2 ); + } + + } ); } ); } ); @@ -697,7 +680,7 @@ void ImmiscibleMultiphaseFlow::assembleFluxTerms( real64 const dt, DofManager const & dofManager, CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) const -{ +{ GEOS_MARK_FUNCTION; NumericalMethodsManager const & numericalMethodManager = domain.getNumericalMethodManager(); @@ -714,32 +697,32 @@ void ImmiscibleMultiphaseFlow::assembleFluxTerms( real64 const dt, { typename TYPEOFREF( stencil ) ::KernelWrapper stencilWrapper = stencil.createKernelWrapper(); immiscibleMultiphaseKernels:: - FaceBasedAssemblyKernelFactory::createAndLaunch< parallelDevicePolicy<> >( m_numPhases, - dofManager.rankOffset(), - dofKey, - m_hasCapPressure, - m_useTotalMassEquation, - getName(), - mesh.getElemManager(), - stencilWrapper, - dt, - localMatrix.toViewConstSizes(), - localRhs.toView() ); - } ); + FaceBasedAssemblyKernelFactory::createAndLaunch< parallelDevicePolicy<> >( m_numPhases, + dofManager.rankOffset(), + dofKey, + m_hasCapPressure, + m_useTotalMassEquation, + getName(), + mesh.getElemManager(), + stencilWrapper, + dt, + localMatrix.toViewConstSizes(), + localRhs.toView() ); + } ); } ); } // Ryan: Looks like this will need to be overwritten as well... // I have left the CompositionalMultiphaseFVM implementation for reference void ImmiscibleMultiphaseFlow::setupDofs( DomainPartition const & domain, - DofManager & dofManager ) const + DofManager & dofManager ) const { - GEOS_UNUSED_VAR(domain, dofManager); + GEOS_UNUSED_VAR( domain, dofManager ); // add a field for the cell-centered degrees of freedom dofManager.addField( viewKeyStruct::elemDofFieldString(), - FieldLocation::Elem, - m_numDofPerCell, - getMeshTargets() ); + FieldLocation::Elem, + m_numDofPerCell, + getMeshTargets() ); //// this call with instruct GEOS to reorder the dof numbers //dofManager.setLocalReorderingType( viewKeyStruct::elemDofFieldString(), @@ -802,8 +785,9 @@ void ImmiscibleMultiphaseFlow::applyDirichletBC( real64 const time_n, fields::flow::pressure::key(), fields::flow::bcPressure::key() ); // 2. Apply saturation BC (phase volume fraction) and store in a separate field //applyFieldValue< ElementSubRegionBase >( time_n, dt, mesh, bcLogMessage, - // fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key(), fields::immiscibleMultiphaseFlow::bcPhaseVolumeFraction::key() ); - + // fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key(), + // fields::immiscibleMultiphaseFlow::bcPhaseVolumeFraction::key() ); + globalIndex const rankOffset = dofManager.rankOffset(); string const dofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); @@ -816,13 +800,14 @@ void ImmiscibleMultiphaseFlow::applyDirichletBC( real64 const time_n, SortedArrayView< localIndex const > const & targetSet, ElementSubRegionBase & subRegion, string const & ) - { + { arrayView1d< real64 const > const bcPres = subRegion.getReference< array1d< real64 > >( fields::flow::bcPressure::key() ); //arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const bcPhaseVolFraction = - //subRegion.getReference< array2d< real64, immiscibleFlow::LAYOUT_PHASE > >( fields::immiscibleMultiphaseFlow::bcPhaseVolumeFraction::key() ); - + //subRegion.getReference< array2d< real64, immiscibleFlow::LAYOUT_PHASE > >( + // fields::immiscibleMultiphaseFlow::bcPhaseVolumeFraction::key() ); + arrayView1d< integer const > const ghostRank = subRegion.getReference< array1d< integer > >( ObjectManagerBase::viewKeyStruct::ghostRankString() ); arrayView1d< globalIndex const > const dofNumber = @@ -830,7 +815,8 @@ void ImmiscibleMultiphaseFlow::applyDirichletBC( real64 const time_n, arrayView1d< real64 const > const pres = subRegion.getReference< array1d< real64 > >( fields::flow::pressure::key() ); //arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFraction = - //subRegion.getReference< array2d< real64, immiscibleFlow::LAYOUT_PHASE > >( fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key() ); + //subRegion.getReference< array2d< real64, immiscibleFlow::LAYOUT_PHASE > >( + // fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key() ); integer const numPhase = m_numPhases; forAll< parallelDevicePolicy<> >( targetSet.size(), [=] GEOS_HOST_DEVICE ( localIndex const a ) @@ -866,15 +852,15 @@ void ImmiscibleMultiphaseFlow::applyDirichletBC( real64 const time_n, // localRhs[localRow + ip + 1] = rhsValue; // } } ); - } ); + } ); } ); } real64 ImmiscibleMultiphaseFlow::calculateResidualNorm( real64 const & GEOS_UNUSED_PARAM( time_n ), - real64 const & GEOS_UNUSED_PARAM( dt ), - DomainPartition const & domain, - DofManager const & dofManager, - arrayView1d< real64 const > const & localRhs ) + real64 const & GEOS_UNUSED_PARAM( dt ), + DomainPartition const & domain, + DofManager const & dofManager, + arrayView1d< real64 const > const & localRhs ) { GEOS_MARK_FUNCTION; integer constexpr numNorm = 1; // mass balance @@ -907,22 +893,22 @@ real64 ImmiscibleMultiphaseFlow::calculateResidualNorm( real64 const & GEOS_UNUS // step 1: compute the norm in the subRegion - real64 subRegionFlowResidualNorm[1]{}; - real64 subRegionFlowResidualNormalizer[1]{}; - + real64 subRegionFlowResidualNorm[1]{}; + real64 subRegionFlowResidualNormalizer[1]{}; + immiscibleMultiphaseKernels:: - ResidualNormKernelFactory::createAndLaunch< parallelDevicePolicy<> >( normType, - 2, - rankOffset, - dofKey, - localRhs, - subRegion, - solid, - m_nonlinearSolverParameters.m_minNormalizer, - subRegionFlowResidualNorm, - subRegionFlowResidualNormalizer ); - subRegionResidualNorm[0] = subRegionFlowResidualNorm[0]; - subRegionResidualNormalizer[0] = subRegionFlowResidualNormalizer[0]; + ResidualNormKernelFactory::createAndLaunch< parallelDevicePolicy<> >( normType, + 2, + rankOffset, + dofKey, + localRhs, + subRegion, + solid, + m_nonlinearSolverParameters.m_minNormalizer, + subRegionFlowResidualNorm, + subRegionFlowResidualNormalizer ); + subRegionResidualNorm[0] = subRegionFlowResidualNorm[0]; + subRegionResidualNormalizer[0] = subRegionFlowResidualNormalizer[0]; // step 2: first reduction across meshBodies/regions/subRegions if( normType == solverBaseKernels::NormType::Linf ) @@ -940,21 +926,21 @@ real64 ImmiscibleMultiphaseFlow::calculateResidualNorm( real64 const & GEOS_UNUS real64 residualNorm = 0.0; residualNorm = localResidualNorm[0]; -if( normType == solverBaseKernels::NormType::Linf ) - { - solverBaseKernels::LinfResidualNormHelper::computeGlobalNorm( localResidualNorm[0], residualNorm ); - } - else - { - solverBaseKernels::L2ResidualNormHelper::computeGlobalNorm( localResidualNorm[0], localResidualNormalizer[0], residualNorm ); - } + if( normType == solverBaseKernels::NormType::Linf ) + { + solverBaseKernels::LinfResidualNormHelper::computeGlobalNorm( localResidualNorm[0], residualNorm ); + } + else + { + solverBaseKernels::L2ResidualNormHelper::computeGlobalNorm( localResidualNorm[0], localResidualNormalizer[0], residualNorm ); + } + + if( getLogLevel() >= 1 && logger::internal::rank == 0 ) + { + std::cout << GEOS_FMT( " ( R{} ) = ( {:4.2e} )", coupledSolverAttributePrefix(), residualNorm ); + } - if( getLogLevel() >= 1 && logger::internal::rank == 0 ) - { - std::cout << GEOS_FMT( " ( R{} ) = ( {:4.2e} )", coupledSolverAttributePrefix(), residualNorm ); - } - return residualNorm; } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp index ce5164eb16b..65961ec2df8 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp @@ -88,7 +88,7 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase DofManager const & dofManager, CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) override; - + virtual real64 calculateResidualNorm( real64 const & time_n, real64 const & dt, @@ -106,7 +106,7 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase DomainPartition & domain, DofManager const & dofManager, CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) override; + arrayView1d< real64 > const & localRhs ) override; virtual void resetStateToBeginningOfStep( DomainPartition & domain ) override; diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp index 64752b84ecb..48d560815d9 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp @@ -59,7 +59,7 @@ DECLARE_FIELD( bcPhaseVolumeFraction, 0, LEVEL_0, WRITE_AND_READ, - "Boundary condition phase volume fraction" ); + "Boundary condition phase volume fraction" ); DECLARE_FIELD( phaseMass, "phaseMass", diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp index 2eb245b5aae..97690653236 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp @@ -44,7 +44,6 @@ #include "physicsSolvers/SolverBaseKernels.hpp" namespace geos - { namespace immiscibleMultiphaseKernels { @@ -75,26 +74,26 @@ class FaceBasedAssemblyKernelBase using ImmiscibleMultiphaseFlowAccessors = StencilAccessors< fields::ghostRank, fields::flow::pressure, - fields::flow::gravityCoefficient, + fields::flow::gravityCoefficient, fields::immiscibleMultiphaseFlow::phaseMobility, - fields::immiscibleMultiphaseFlow::dPhaseMobility >; + fields::immiscibleMultiphaseFlow::dPhaseMobility >; using MultiphaseFluidAccessors = StencilMaterialAccessors< constitutive::TwoPhaseFluid, fields::twophasefluid::phaseDensity, - fields::twophasefluid::dPhaseDensity >; + fields::twophasefluid::dPhaseDensity >; using CapPressureAccessors = StencilMaterialAccessors< CapillaryPressureBase, fields::cappres::phaseCapPressure, - fields::cappres::dPhaseCapPressure_dPhaseVolFraction >; + fields::cappres::dPhaseCapPressure_dPhaseVolFraction >; using PermeabilityAccessors = StencilMaterialAccessors< PermeabilityBase, fields::permeability::permeability, - fields::permeability::dPerm_dPressure >; + fields::permeability::dPerm_dPressure >; - using Deriv = immiscibleFlow::DerivativeOffset; + using Deriv = immiscibleFlow::DerivativeOffset; /** * @brief Constructor for the kernel interface @@ -111,8 +110,8 @@ class FaceBasedAssemblyKernelBase FaceBasedAssemblyKernelBase( integer const numPhases, globalIndex const rankOffset, DofNumberAccessor const & dofNumberAccessor, - ImmiscibleMultiphaseFlowAccessors const & multiPhaseFlowAccessors, - MultiphaseFluidAccessors const & fluidAccessors, + ImmiscibleMultiphaseFlowAccessors const & multiPhaseFlowAccessors, + MultiphaseFluidAccessors const & fluidAccessors, CapPressureAccessors const & capPressureAccessors, PermeabilityAccessors const & permeabilityAccessors, real64 const & dt, @@ -120,7 +119,7 @@ class FaceBasedAssemblyKernelBase arrayView1d< real64 > const & localRhs, integer const hasCapPressure, integer const useTotalMassEquation ) - : m_numPhases (numPhases), + : m_numPhases ( numPhases ), m_rankOffset( rankOffset ), m_dt( dt ), m_dofNumber( dofNumberAccessor.toNestedViewConst() ), @@ -130,7 +129,7 @@ class FaceBasedAssemblyKernelBase m_gravCoef( multiPhaseFlowAccessors.get( fields::flow::gravityCoefficient {} ) ), m_pres( multiPhaseFlowAccessors.get( fields::flow::pressure {} ) ), m_mob( multiPhaseFlowAccessors.get( fields::immiscibleMultiphaseFlow::phaseMobility {} ) ), - m_dMob( multiPhaseFlowAccessors.get( fields::immiscibleMultiphaseFlow::dPhaseMobility {} ) ), + m_dMob( multiPhaseFlowAccessors.get( fields::immiscibleMultiphaseFlow::dPhaseMobility {} ) ), m_dens( fluidAccessors.get( fields::twophasefluid::phaseDensity {} ) ), m_dDens_dPres( fluidAccessors.get( fields::twophasefluid::dPhaseDensity {} ) ), m_phaseCapPressure( capPressureAccessors.get( fields::cappres::phaseCapPressure {} ) ), @@ -139,7 +138,7 @@ class FaceBasedAssemblyKernelBase m_localRhs( localRhs ), m_hasCapPressure ( hasCapPressure ), m_useTotalMassEquation ( useTotalMassEquation ) - {GEOS_UNUSED_VAR(m_useTotalMassEquation);} + {GEOS_UNUSED_VAR( m_useTotalMassEquation );} protected: @@ -250,8 +249,8 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase : FaceBasedAssemblyKernelBase( numPhases, rankOffset, dofNumberAccessor, - multiPhaseFlowAccessors, - fluidAccessors, + multiPhaseFlowAccessors, + fluidAccessors, capPressureAccessors, permeabilityAccessors, dt, @@ -271,7 +270,7 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase */ struct StackVariables { - public: +public: /** * @brief Constructor for the stack variables @@ -336,7 +335,7 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase * @param[in] iconn the connection index * @param[in] stack the stack variables */ - + GEOS_HOST_DEVICE void setup( localIndex const iconn, StackVariables & stack ) const @@ -366,7 +365,8 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase StackVariables & stack, FUNC && kernelOp = NoOpFunc{} ) const { - // first, compute the transmissibilities at this face // get k and dk/dP from global arrays and place in stack + // first, compute the transmissibilities at this face // get k and dk/dP from global arrays + // and place in stack m_stencilWrapper.computeWeights( iconn, m_permeability, m_dPerm_dPres, @@ -384,7 +384,7 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase real64 densMean[numEqn]{}; real64 dDensMean_dP[numEqn][2]{}; - real64 presGrad[numEqn]{}; + real64 presGrad[numEqn]{}; real64 dPresGrad_dP[numEqn][2]{}; real64 gravHead[numEqn]{}; @@ -393,7 +393,7 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase real64 capGrad[numEqn]{}; real64 dCapGrad_dP[numEqn][2]{}; real64 dCapGrad_dS[numEqn][2]{}; - + real64 fluxVal[numEqn]{}; real64 dFlux_dP[numEqn][2]{}; real64 dFlux_dS[numEqn][2]{}; @@ -403,7 +403,7 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase real64 dMob_dS[numEqn][2]{}; real64 const trans[2] = { stack.transmissibility[connectionIndex][0], stack.transmissibility[connectionIndex][1] }; - real64 const dTrans_dP[2] = { stack.dTrans_dPres[connectionIndex][0], stack.dTrans_dPres[connectionIndex][1] }; + real64 const dTrans_dP[2] = { stack.dTrans_dPres[connectionIndex][0], stack.dTrans_dPres[connectionIndex][1] }; // cell indices localIndex const seri[2] = {m_seri( iconn, k[0] ), m_seri( iconn, k[1] )}; @@ -413,7 +413,7 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase // loop over phases for( integer ip = 0; ip < m_numPhases; ++ip ) { - // calculate quantities on primary connected cells + // calculate quantities on primary connected cells for( integer ke = 0; ke < 2; ++ke ) { // density @@ -456,12 +456,13 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase dGravHead_dP[ip][i] += dDensMean_dP[ip][i] * gravD; // dDPg/dP = {drho/dP1 * T g (z1 - z2) , drho/dP2 * T g (z1 - z2)} } - if ( m_hasCapPressure ) // check sign convention + if( m_hasCapPressure ) // check sign convention { real64 const capPres = m_phaseCapPressure[er][esr][ei][0][ip]; // Pc = Pc1 || Pc2 dCapGrad_dTrans -= signPotDiff[ke] * capPres; // dDPc/dT = (-Pc1 + Pc2) - pot -= trans[ke] * capPres; // Phi = T P1 - rho T g z1 - T Pc1 || -T P2 + rho T g z2 + T Pc2 - capGrad[ip] -= trans[ke] * capPres; // DPc = T (-Pc1 + Pc2) + pot -= trans[ke] * capPres; // Phi = T P1 - rho T g z1 - T Pc1 || -T P2 + rho T g z2 + T + // Pc2 + capGrad[ip] -= trans[ke] * capPres; // DPc = T (-Pc1 + Pc2) } potScale = fmax( potScale, fabs( pot ) ); // maxPhi = Phi1 > Phi2 ? Phi1 : Phi2 @@ -470,29 +471,35 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase for( integer ke = 0; ke < 2; ++ke ) { dPresGrad_dP[ip][ke] += dTrans_dP[ke] * dPresGrad_dTrans; // dDPv/dP = { T + dT/dP1 * (P1 - P2) , -T + dT/dP2 * (P1 - P2)} - dGravHead_dP[ip][ke] += dTrans_dP[ke] * dGravHead_dTrans; // dDPg/dP = { drho/dP1 * T g (z1 - z2) + dT/dP1 * rho g (z1 - z2) , + dGravHead_dP[ip][ke] += dTrans_dP[ke] * dGravHead_dTrans; // dDPg/dP = { drho/dP1 * T g (z1 - z2) + dT/dP1 * rho g (z1 - z2) , // drho/dP2 * T g (z1 - z2) + dT/dP2 * rho g (z1 - z2) } - if ( m_hasCapPressure ) + if( m_hasCapPressure ) { - real64 const dCapPres_dS = m_dPhaseCapPressure_dPhaseVolFrac[seri[ke]][sesri[ke]][sei[ke]][0][ip][ip]; // dPc/dS = dPc1/dS1 || dPc2/dS2 - dCapGrad_dP[ip][ke] += dTrans_dP[ke] * dCapGrad_dTrans; // dDPc/dP = { dT/dP1 * (-Pc1 + Pc2) , - // dT/dP2 * (-Pc1 + Pc2) } - dCapGrad_dS[ip][ke] -= trans[ke] * dCapPres_dS; // dDPc/dS = { -T * dPc1/dS1 , T * dPc2/dS2 } - } + real64 const dCapPres_dS = m_dPhaseCapPressure_dPhaseVolFrac[seri[ke]][sesri[ke]][sei[ke]][0][ip][ip]; // dPc/dS = dPc1/dS1 || + // dPc2/dS2 + dCapGrad_dP[ip][ke] += dTrans_dP[ke] * dCapGrad_dTrans; // dDPc/dP = { dT/dP1 * + // (-Pc1 + Pc2) , + // dT/dP2 * + // (-Pc1 + Pc2) } + dCapGrad_dS[ip][ke] -= trans[ke] * dCapPres_dS; // dDPc/dS = { -T * + // dPc1/dS1 , T * + // dPc2/dS2 } + } } // *** upwinding *** // compute potential gradient real64 potGrad = presGrad[ip] - gravHead[ip]; // DPhi = T (P1 - P2) - T rho g (z1 - z2) - if ( m_hasCapPressure ) + if( m_hasCapPressure ) { potGrad += capGrad[ip]; // DPhi = T (P1 - P2) - T rho g (z1 - z2) + T (-Pc1 + Pc2) } // compute upwinding tolerance real64 constexpr upwRelTol = 1e-8; - real64 const upwAbsTol = fmax( potScale * upwRelTol, LvArray::NumericLimits< real64 >::epsilon ); // abstol = maxPhi * tol > eps ? maxPhi * tol : eps + real64 const upwAbsTol = fmax( potScale * upwRelTol, LvArray::NumericLimits< real64 >::epsilon ); // abstol = maxPhi * tol > eps ? + // maxPhi * tol : eps // decide mobility coefficients - smooth variation in [-upwAbsTol; upwAbsTol] real64 const alpha = ( potGrad + upwAbsTol ) / ( 2 * upwAbsTol ); // alpha = (DPhi + abstol) / abstol / 2 @@ -502,7 +509,7 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase { localIndex const k_up = 1 - localIndex( fmax( fmin( alpha, 1.0 ), 0.0 ) ); // 1 upwind -> k_up = 0 || 2 upwind -> k_up = 1 - mobility[ip] = m_mob[seri[k_up]][sesri[k_up]][sei[k_up]][ip]; // M = Mupstream + mobility[ip] = m_mob[seri[k_up]][sesri[k_up]][sei[k_up]][ip]; // M = Mupstream dMob_dP[ip][k_up] = m_dMob[seri[k_up]][sesri[k_up]][sei[k_up]][ip][Deriv::dP]; // dM/dP = {dM/dP1 , 0} OR {0 , dM/dP2} dMob_dS[ip][k_up] = m_dMob[seri[k_up]][sesri[k_up]][sei[k_up]][ip][Deriv::dS]; // dM/dS = {dM/dS1 , 0} OR {0 , dM/dS2} } @@ -512,34 +519,40 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase for( integer ke = 0; ke < 2; ++ke ) { mobility[ip] += mobWeights[ke] * m_mob[seri[ke]][sesri[ke]][sei[ke]][ip]; // M = alpha * M1 + (1 - alpha) * M2 - dMob_dP[ip][ke] = mobWeights[ke] * m_dMob[seri[ke]][sesri[ke]][sei[ke]][ip][Deriv::dP]; // dM/dP = {alpha * dM1/dP1 , (1 - alpha) * dM2/dP2} - dMob_dS[ip][ke] = mobWeights[ke] * m_dMob[seri[ke]][sesri[ke]][sei[ke]][ip][Deriv::dS]; // dM/dP = {alpha * dM1/dS1 , (1 - alpha) * dM2/dS2} + dMob_dP[ip][ke] = mobWeights[ke] * m_dMob[seri[ke]][sesri[ke]][sei[ke]][ip][Deriv::dP]; // dM/dP = {alpha * dM1/dP1 , (1 - + // alpha) * dM2/dP2} + dMob_dS[ip][ke] = mobWeights[ke] * m_dMob[seri[ke]][sesri[ke]][sei[ke]][ip][Deriv::dS]; // dM/dP = {alpha * dM1/dS1 , (1 - + // alpha) * dM2/dS2} } } // pressure gradient depends on all points in the stencil for( integer ke = 0; ke < 2; ++ke ) { - dFlux_dP[ip][ke] += dPresGrad_dP[ip][ke]; // dF/dP = { T + dT/dP1 * (P1 - P2) , + dFlux_dP[ip][ke] += dPresGrad_dP[ip][ke]; // dF/dP = { T + dT/dP1 * (P1 - P2) , // -T + dT/dP2 * (P1 - P2) } } // gravitational head depends only on the two cells connected (same as mean density) - for( integer ke = 0; ke < 2; ++ke ) + for( integer ke = 0; ke < 2; ++ke ) { - dFlux_dP[ip][ke] -= dGravHead_dP[ip][ke]; // dF/dP = { T + dT/dP1 * (P1 - P2) - drho/dP1 * T g (z1 - z2) - dT/dP1 * rho g (z1 - z2) , - // -T + dT/dP2 * (P1 - P2) - drho/dP2 * T g (z1 - z2) - dT/dP2 * rho g (z1 - z2) } + dFlux_dP[ip][ke] -= dGravHead_dP[ip][ke]; // dF/dP = { T + dT/dP1 * (P1 - P2) - drho/dP1 * T g (z1 - z2) - dT/dP1 * rho g (z1 - + // z2) , + // -T + dT/dP2 * (P1 - P2) - drho/dP2 * T g (z1 - z2) - dT/dP2 * rho g (z1 - + // z2) } } // capillary pressure contribution - if ( m_hasCapPressure ) + if( m_hasCapPressure ) { for( integer ke = 0; ke < 2; ++ke ) - { - dFlux_dP[ip][ke] += dCapGrad_dP[ip][ke]; // dF/dP = { T + dT/dP1 * (P1 - P2) - drho/dP1 * T g (z1 - z2) - dT/dP1 * rho g (z1 - z2) + dT/dP1 * (-Pc1 + Pc2) , - // -T + dT/dP2 * (P1 - P2) - drho/dP2 * T g (z1 - z2) - dT/dP2 * rho g (z1 - z2) + dT/dP2 * (-Pc1 + Pc2) } + { + dFlux_dP[ip][ke] += dCapGrad_dP[ip][ke]; // dF/dP = { T + dT/dP1 * (P1 - P2) - drho/dP1 * T g (z1 - z2) - dT/dP1 * rho g (z1 + // - z2) + dT/dP1 * (-Pc1 + Pc2) , + // -T + dT/dP2 * (P1 - P2) - drho/dP2 * T g (z1 - z2) - dT/dP2 * rho g (z1 + // - z2) + dT/dP2 * (-Pc1 + Pc2) } - dFlux_dS[ip][ke] += dCapGrad_dS[ip][ke]; // dF/dS = { T * -dPc/dS1 , T * dPc/dS2 } + dFlux_dS[ip][ke] += dCapGrad_dS[ip][ke]; // dF/dS = { T * -dPc/dS1 , T * dPc/dS2 } } } @@ -548,20 +561,25 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase for( integer ke = 0; ke < 2; ++ke ) { - dFlux_dP[ip][ke] *= mobility[ip]; // dF/dP = { M [ T + dT/dP1 * (P1 - P2) - drho/dP1 * T g (z1 - z2) - dT/dP1 * rho g (z1 - z2) + dT/dP1 * (-Pc1 + Pc2)] , - // M [-T + dT/dP2 * (P1 - P2) - drho/dP2 * T g (z1 - z2) - dT/dP2 * rho g (z1 - z2) + dT/dP2 * (-Pc1 + Pc2)] } + dFlux_dP[ip][ke] *= mobility[ip]; // dF/dP = { M [ T + dT/dP1 * (P1 - P2) - drho/dP1 * T g (z1 - z2) - dT/dP1 * rho g (z1 - + // z2) + dT/dP1 * (-Pc1 + Pc2)] , + // M [-T + dT/dP2 * (P1 - P2) - drho/dP2 * T g (z1 - z2) - dT/dP2 * rho g (z1 - + // z2) + dT/dP2 * (-Pc1 + Pc2)] } - dFlux_dS[ip][ke] *= mobility[ip]; // dF/dS = { M [T * -dPc/dS1] , M [T * dPc/dS2] } + dFlux_dS[ip][ke] *= mobility[ip]; // dF/dS = { M [T * -dPc/dS1] , M [T * dPc/dS2] } } // add contribution from upstream cell mobility derivatives for( integer ke = 0; ke < 2; ++ke ) { - dFlux_dP[ip][ke] += dMob_dP[ip][ke] * potGrad; // dF/dP = { M [ T + dT/dP1 * (P1 - P2) - drho1/dP * T g (z1 - z2) - dT/dP1 * rho g (z1 - z2) + dT/dP1 * (-Pc1 + Pc2)] + dM/dP1 * DPhi , - // M [-T + dT/dP2 * (P1 - P2) - drho2/dP * T g (z1 - z2) - dT/dP2 * rho g (z1 - z2) + dT/dP2 * (-Pc1 + Pc2)] + dM/dP2 * DPhi } + dFlux_dP[ip][ke] += dMob_dP[ip][ke] * potGrad; // dF/dP = { M [ T + dT/dP1 * (P1 - P2) - drho1/dP * T g (z1 - z2) - dT/dP1 * + // rho g (z1 - z2) + dT/dP1 * (-Pc1 + Pc2)] + dM/dP1 * DPhi , + // M [-T + dT/dP2 * (P1 - P2) - drho2/dP * T g (z1 - z2) - dT/dP2 * + // rho g (z1 - z2) + dT/dP2 * (-Pc1 + Pc2)] + dM/dP2 * DPhi } - dFlux_dS[ip][ke] += dMob_dS[ip][ke] * potGrad; // dF/dS = { M [T * -dPc/dS1] + dM/dS1 * DPhi , M [T * dPc/dS2] + dM/dS2 * DPhi } - } + dFlux_dS[ip][ke] += dMob_dS[ip][ke] * potGrad; // dF/dS = { M [T * -dPc/dS1] + dM/dS1 * DPhi , M [T * dPc/dS2] + dM/dS2 * DPhi + // } + } // populate local flux vector and derivatives stack.localFlux[k[0]*numEqn + ip] += m_dt * fluxVal[ip]; @@ -581,7 +599,8 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase } // Customize the kernel with this lambda - kernelOp( k, seri, sesri, sei, connectionIndex, alpha, mobility, potGrad, fluxVal, dFlux_dP, dFlux_dS ); // Not sure what this does + kernelOp( k, seri, sesri, sei, connectionIndex, alpha, mobility, potGrad, fluxVal, dFlux_dP, dFlux_dS ); // Not sure what this + // does } // loop over phases @@ -597,7 +616,7 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase */ template< typename FUNC = NoOpFunc > // should change to multiphase GEOS_HOST_DEVICE - void complete( localIndex const iconn, + void complete( localIndex const iconn, StackVariables & stack, FUNC && kernelOp = NoOpFunc{} ) const { @@ -611,8 +630,8 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase globalIndex const globalRow = m_dofNumber[m_seri( iconn, i )][m_sesri( iconn, i )][m_sei( iconn, i )]; localIndex const localRow = LvArray::integerConversion< localIndex >( globalRow - m_rankOffset ); GEOS_ASSERT_GE( localRow, 0 ); - - GEOS_ASSERT_GT( m_localMatrix.numRows(), localRow + numEqn - 1); + + GEOS_ASSERT_GT( m_localMatrix.numRows(), localRow + numEqn - 1 ); for( integer ic = 0; ic < numEqn; ++ic ) { @@ -623,7 +642,7 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase stack.dofColIndices.data(), stack.localFluxJacobian[i * numEqn + ic].dataIfContiguous(), stack.stencilSize * numDof ); - } + } // call the lambda to assemble additional terms, such as thermal terms kernelOp( i, localRow ); @@ -695,7 +714,7 @@ class FaceBasedAssemblyKernelFactory template< typename POLICY, typename STENCILWRAPPER > static void createAndLaunch( integer const numPhases, - globalIndex const rankOffset, + globalIndex const rankOffset, string const & dofKey, integer const hasCapPressure, integer const useTotalMassEquation, @@ -715,7 +734,7 @@ class FaceBasedAssemblyKernelFactory using kernelType = FaceBasedAssemblyKernel< NUM_EQN, NUM_DOF, STENCILWRAPPER >; typename kernelType::ImmiscibleMultiphaseFlowAccessors flowAccessors( elemManager, solverName ); - typename kernelType::MultiphaseFluidAccessors fluidAccessors( elemManager, solverName ); + typename kernelType::MultiphaseFluidAccessors fluidAccessors( elemManager, solverName ); typename kernelType::CapPressureAccessors capPressureAccessors( elemManager, solverName ); typename kernelType::PermeabilityAccessors permAccessors( elemManager, solverName ); @@ -738,7 +757,7 @@ class PhaseMobilityKernel { public: - //using Base = MultiphaseFluidAccessors::PropertyKernelBase< NUM_COMP >; + //using Base = MultiphaseFluidAccessors::PropertyKernelBase< NUM_COMP >; /// Compile time value for the number of phases static constexpr integer numPhase = NUM_PHASE; @@ -752,7 +771,7 @@ class PhaseMobilityKernel PhaseMobilityKernel( ObjectManagerBase & subRegion, TwoPhaseFluid const & fluid, RelativePermeabilityBase const & relperm ) - : + : m_phaseDens( fluid.phaseDensity() ), m_dPhaseDens( fluid.dPhaseDensity() ), m_phaseVisc( fluid.phaseViscosity() ), @@ -792,10 +811,10 @@ class PhaseMobilityKernel void compute( localIndex const ei, FUNC && phaseMobilityKernelOp = NoOpFunc{} ) const { - using Deriv = immiscibleFlow::DerivativeOffset; - + using Deriv = immiscibleFlow::DerivativeOffset; + arraySlice1d< real64, immiscibleFlow::USD_PHASE - 1 > const phaseMob = m_phaseMob[ei]; - arraySlice2d< real64, immiscibleFlow::USD_PHASE_DS - 1 > const dPhaseMob = m_dPhaseMob[ei]; + arraySlice2d< real64, immiscibleFlow::USD_PHASE_DS - 1 > const dPhaseMob = m_dPhaseMob[ei]; for( integer ip = 0; ip < numPhase; ++ip ) { @@ -804,18 +823,18 @@ class PhaseMobilityKernel real64 const viscosity = m_phaseVisc[ei][0][ip]; real64 const dVisc_dP = m_dPhaseVisc[ei][0][ip][Deriv::dP]; - real64 const relPerm = m_phaseRelPerm[ei][0][ip]; + real64 const relPerm = m_phaseRelPerm[ei][0][ip]; real64 const mobility = relPerm * density / viscosity; phaseMob[ip] = mobility; - dPhaseMob[ip][Deriv::dP] = mobility * (dDens_dP / density - dVisc_dP / viscosity); + dPhaseMob[ip][Deriv::dP] = mobility * (dDens_dP / density - dVisc_dP / viscosity); for( integer jp = 0; jp < numPhase-1; ++jp ) { - real64 const dRelPerm_dS = m_dPhaseRelPerm_dPhaseVolFrac[ei][0][ip][jp]; - dPhaseMob[ip][Deriv::dS+jp] = dRelPerm_dS * density / viscosity; - } + real64 const dRelPerm_dS = m_dPhaseRelPerm_dPhaseVolFrac[ei][0][ip][jp]; + dPhaseMob[ip][Deriv::dS+jp] = dRelPerm_dS * density / viscosity; + } // call the lambda in the phase loop to allow the reuse of the relperm, density, viscosity, and mobility // possible use: assemble the derivatives wrt temperature @@ -836,7 +855,7 @@ class PhaseMobilityKernel /// Views on the phase viscosities arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > m_phaseVisc; - arrayView4d< real64 const, constitutive::multifluid::USD_PHASE_DC > m_dPhaseVisc; + arrayView4d< real64 const, constitutive::multifluid::USD_PHASE_DC > m_dPhaseVisc; //arrayView2d< real64 const, immiscibleFlow::USD_PHASE > m_phaseVisc; //arrayView2d< real64 const, immiscibleFlow::USD_PHASE > m_dPhaseVisc; @@ -856,7 +875,7 @@ class PhaseMobilityKernel */ class PhaseMobilityKernelFactory { -public: +public: /** * @brief Create a new kernel and launch @@ -873,7 +892,7 @@ class PhaseMobilityKernelFactory RelativePermeabilityBase const & relperm ) { if( numPhase == 2 ) - { + { PhaseMobilityKernel< 2 > kernel( subRegion, fluid, relperm ); PhaseMobilityKernel< 2 >::template launch< POLICY >( subRegion.size(), kernel ); } @@ -908,7 +927,7 @@ struct FluidUpdateKernel */ /// Compile time value for the number of norms to compute - static constexpr integer numNorm = 1; +static constexpr integer numNorm = 1; class ResidualNormKernel : public solverBaseKernels::ResidualNormKernelBase< numNorm > { @@ -919,9 +938,9 @@ class ResidualNormKernel : public solverBaseKernels::ResidualNormKernelBase< num using Base::m_minNormalizer; using Base::m_rankOffset; using Base::m_localResidual; - using Base::m_dofNumber; + using Base::m_dofNumber; -ResidualNormKernel( globalIndex const rankOffset, + ResidualNormKernel( globalIndex const rankOffset, arrayView1d< real64 const > const & localResidual, arrayView1d< globalIndex const > const & dofNumber, arrayView1d< localIndex const > const & ghostRank, @@ -962,7 +981,7 @@ ResidualNormKernel( globalIndex const rankOffset, { for( integer idof = 0; idof < m_numPhases; ++idof ) { - real64 const massNormalizer = LvArray::math::max( m_minNormalizer, m_phaseMass_n[ei][idof] ); + real64 const massNormalizer = LvArray::math::max( m_minNormalizer, m_phaseMass_n[ei][idof] ); stack.localValue[0] += m_localResidual[stack.localRow + idof] * m_localResidual[stack.localRow + idof]; stack.localNormalizer[0] += massNormalizer; } @@ -970,7 +989,7 @@ ResidualNormKernel( globalIndex const rankOffset, protected: - + /// Number of fluid phases integer const m_numPhases; @@ -1034,7 +1053,6 @@ class ResidualNormKernelFactory - } // namespace immiscible multiphasekernels From 6a43303cef12284216b16ddf4e881ab0d4a43531 Mon Sep 17 00:00:00 2001 From: Ammara-14 Date: Tue, 8 Oct 2024 12:19:17 -0700 Subject: [PATCH 039/104] Added applySystemSolution and phaseVolumeFractions boundary conditions --- .../fluidFlow/ImmiscibleMultiphaseFlow.cpp | 146 +++++++++++++++--- .../fluidFlow/ImmiscibleMultiphaseFlow.hpp | 7 + 2 files changed, 134 insertions(+), 19 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index a0f0be788a2..b3ddad9207d 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -133,6 +133,9 @@ void ImmiscibleMultiphaseFlow::registerDataOnMesh( Group & meshBodies ) subRegion.registerField< phaseVolumeFraction_n >( getName() ). reference().resizeDimension< 1 >( m_numPhases ); + subRegion.registerField< bcPhaseVolumeFraction>( getName() ). + reference().resizeDimension< 1 >( m_numPhases ); + subRegion.registerField< phaseMass >( getName() ). reference().resizeDimension< 1 >( m_numPhases ); @@ -757,6 +760,69 @@ char const bcLogMessage[] = "\nNote that if this number is equal to zero for all subRegions, the boundary condition will not be applied on this element set."; } + +void applyAndSpecifyFieldValue( real64 const & time_n, + real64 const & dt, + MeshLevel & mesh, + globalIndex const rankOffset, + string const dofKey, + bool const, + integer const idof, + string const fieldKey, + string const boundaryFieldKey, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) +{ + FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); + + fsManager.apply< ElementSubRegionBase >( time_n + dt, + mesh, + fieldKey, + [&]( FieldSpecificationBase const & fs, + string const &, + SortedArrayView< localIndex const > const & lset, + ElementSubRegionBase & subRegion, + string const & ) + { + // Specify the bc value of the field + fs.applyFieldValue< FieldSpecificationEqual, + parallelDevicePolicy<> >( lset, + time_n + dt, + subRegion, + boundaryFieldKey ); + + arrayView1d< integer const > const ghostRank = subRegion.ghostRank(); + arrayView1d< globalIndex const > const dofNumber = + subRegion.getReference< array1d< globalIndex > >( dofKey ); + arrayView1d< real64 const > const bcField = + subRegion.getReference< array1d< real64 > >( boundaryFieldKey ); + arrayView1d< real64 const > const field = + subRegion.getReference< array1d< real64 > >( fieldKey ); + + forAll< parallelDevicePolicy<> >( lset.size(), [=] GEOS_HOST_DEVICE ( localIndex const a ) + { + localIndex const ei = lset[a]; + if( ghostRank[ei] >= 0 ) + { + return; + } + + globalIndex const dofIndex = dofNumber[ei]; + localIndex const localRow = dofIndex - rankOffset; + real64 rhsValue; + + // Apply field value to the matrix/rhs + FieldSpecificationEqual::SpecifyFieldValue( dofIndex + idof, + rankOffset, + localMatrix, + rhsValue, + bcField[ei], + field[ei] ); + localRhs[localRow + idof] = rhsValue; + } ); + } ); +} + void ImmiscibleMultiphaseFlow::applyDirichletBC( real64 const time_n, real64 const dt, DofManager const & dofManager, @@ -784,9 +850,9 @@ void ImmiscibleMultiphaseFlow::applyDirichletBC( real64 const time_n, applyFieldValue< ElementSubRegionBase >( time_n, dt, mesh, bcLogMessage, fields::flow::pressure::key(), fields::flow::bcPressure::key() ); // 2. Apply saturation BC (phase volume fraction) and store in a separate field - //applyFieldValue< ElementSubRegionBase >( time_n, dt, mesh, bcLogMessage, - // fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key(), - // fields::immiscibleMultiphaseFlow::bcPhaseVolumeFraction::key() ); + applyFieldValue< ElementSubRegionBase >( time_n, dt, mesh, bcLogMessage, + fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key(), + fields::immiscibleMultiphaseFlow::bcPhaseVolumeFraction::key() ); globalIndex const rankOffset = dofManager.rankOffset(); string const dofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); @@ -804,9 +870,9 @@ void ImmiscibleMultiphaseFlow::applyDirichletBC( real64 const time_n, arrayView1d< real64 const > const bcPres = subRegion.getReference< array1d< real64 > >( fields::flow::bcPressure::key() ); - //arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const bcPhaseVolFraction = - //subRegion.getReference< array2d< real64, immiscibleFlow::LAYOUT_PHASE > >( - // fields::immiscibleMultiphaseFlow::bcPhaseVolumeFraction::key() ); + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const bcPhaseVolFraction = + subRegion.getReference< array2d< real64, immiscibleFlow::LAYOUT_PHASE > >( + fields::immiscibleMultiphaseFlow::bcPhaseVolumeFraction::key() ); arrayView1d< integer const > const ghostRank = subRegion.getReference< array1d< integer > >( ObjectManagerBase::viewKeyStruct::ghostRankString() ); @@ -814,9 +880,9 @@ void ImmiscibleMultiphaseFlow::applyDirichletBC( real64 const time_n, subRegion.getReference< array1d< globalIndex > >( dofKey ); arrayView1d< real64 const > const pres = subRegion.getReference< array1d< real64 > >( fields::flow::pressure::key() ); - //arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFraction = - //subRegion.getReference< array2d< real64, immiscibleFlow::LAYOUT_PHASE > >( - // fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key() ); + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFraction = + subRegion.getReference< array2d< real64, immiscibleFlow::LAYOUT_PHASE > >( + fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key() ); integer const numPhase = m_numPhases; forAll< parallelDevicePolicy<> >( targetSet.size(), [=] GEOS_HOST_DEVICE ( localIndex const a ) @@ -841,16 +907,16 @@ void ImmiscibleMultiphaseFlow::applyDirichletBC( real64 const time_n, localRhs[localRow] = rhsValue; // 3.2. For each phase, apply target saturation value - // for( integer ip = 0; ip < numPhase; ++ip ) - // { - // FieldSpecificationEqual::SpecifyFieldValue( dofIndex + ip + 1, - // rankOffset, - // localMatrix, - // rhsValue, - // bcPhaseVolFraction[ei][ip], - // phaseVolFraction[ei][ip] ); - // localRhs[localRow + ip + 1] = rhsValue; - // } + for( integer ip = 0; ip < numPhase-1; ++ip ) + { + FieldSpecificationEqual::SpecifyFieldValue( dofIndex + ip + 1, + rankOffset, + localMatrix, + rhsValue, + bcPhaseVolFraction[ei][ip], + phaseVolFraction[ei][ip] ); + localRhs[localRow + ip + 1] = rhsValue; + } } ); } ); } ); @@ -944,6 +1010,48 @@ real64 ImmiscibleMultiphaseFlow::calculateResidualNorm( real64 const & GEOS_UNUS return residualNorm; } +void ImmiscibleMultiphaseFlow::applySystemSolution( DofManager const & dofManager, + arrayView1d< real64 const > const & localSolution, + real64 const scalingFactor, + real64 const dt, + DomainPartition & domain ) +{ + GEOS_UNUSED_VAR( dt ); + + DofManager::CompMask pressureMask( m_numDofPerCell, 0, 1 ); + DofManager::CompMask PhaseMask( m_numDofPerCell, 1, m_numPhases ); + + // 1. apply the pressure update + + dofManager.addVectorToField( localSolution, + viewKeyStruct::elemDofFieldString(), + fields::flow::pressure::key(), + scalingFactor, + pressureMask ); + + // 2. apply the phaseVolumeFraction update + + dofManager.addVectorToField( localSolution, + viewKeyStruct::elemDofFieldString(), + fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key(), + scalingFactor, + PhaseMask ); + + // 3. synchronize + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, + MeshLevel & mesh, + arrayView1d< string const > const & regionNames ) + { + std::vector< string > fields{ fields::flow::pressure::key(), fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key() }; + + FieldIdentifiers fieldsToBeSync; + fieldsToBeSync.addElementFields( fields, regionNames ); + + CommunicationTools::getInstance().synchronizeFields( fieldsToBeSync, mesh, domain.getNeighbors(), true ); + } ); +} + + void ImmiscibleMultiphaseFlow::resetStateToBeginningOfStep( DomainPartition & domain ) { GEOS_MARK_FUNCTION; diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp index 65961ec2df8..a5b0ccdf809 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp @@ -96,6 +96,13 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase DofManager const & dofManager, arrayView1d< real64 const > const & localRhs ) override; + virtual void + applySystemSolution( DofManager const & dofManager, + arrayView1d< real64 const > const & localSolution, + real64 const scalingFactor, + real64 const dt, + DomainPartition & domain ) override; + virtual void setupDofs( DomainPartition const & domain, DofManager & dofManager ) const override; From c854b703df5b697baa42b4b97673696f86ea352f Mon Sep 17 00:00:00 2001 From: Ammara-14 Date: Wed, 16 Oct 2024 10:19:17 -0700 Subject: [PATCH 040/104] this version runs a simple test case with no convergence issues --- .../fluidFlow/ImmiscibleMultiphaseFlow.cpp | 57 +++++++++++++++++-- .../fluidFlow/ImmiscibleMultiphaseFlow.hpp | 2 + .../fluidFlow/ImmiscibleMultiphaseKernels.hpp | 17 +++++- 3 files changed, 70 insertions(+), 6 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index b3ddad9207d..cc1191e0fa3 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -284,6 +284,7 @@ void ImmiscibleMultiphaseFlow::updateFluidState( ElementSubRegionBase & subRegio GEOS_MARK_FUNCTION; updateFluidModel( subRegion ); + updatePhaseVolumeFraction( subRegion ); updatePhaseMass( subRegion ); updateRelPermModel( subRegion ); updatePhaseMobility( subRegion ); @@ -529,6 +530,7 @@ ImmiscibleMultiphaseFlow::implicitStepSetup( real64 const & GEOS_UNUSED_PARAM( t // update porosity, permeability updatePorosityAndPermeability( subRegion ); // update all fluid properties + updatePhaseVolumeFraction( subRegion ); updateFluidState( subRegion ); // after the update, save the new saturation @@ -639,7 +641,7 @@ void ImmiscibleMultiphaseFlow::assembleAccumulationTerm( DomainPartition & domai } // compute accumulation - + int signPotDiff[2] = {1, -1}; for( integer ip = 0; ip < numofPhases; ++ip ) { @@ -653,8 +655,17 @@ void ImmiscibleMultiphaseFlow::assembleAccumulationTerm( DomainPartition & domai localJacobian[ip][0] += dPhaseMass_dP; real64 const dPhaseMass_dS = poreVolume * phaseDens[ei][0][ip]; + + + // if ( ip == 0) + // { + // localJacobian[ip][1] += dPhaseMass_dS; + // } else { + // localJacobian[ip][1] -= dPhaseMass_dS; + // } + + localJacobian[ip][1] += signPotDiff[ip] * dPhaseMass_dS; - localJacobian[ip][1] += dPhaseMass_dS; } // complete @@ -745,9 +756,17 @@ void ImmiscibleMultiphaseFlow::applyBoundaryConditions( real64 const time_n, arrayView1d< real64 > const & localRhs ) { GEOS_MARK_FUNCTION; - + // apply pressure boundary conditions. applyDirichletBC( time_n, dt, dofManager, domain, localMatrix.toViewConstSizes(), localRhs.toView() ); + + // for( localIndex row = 0; row < localMatrix.toViewConstSizes().numRows(); ++row ) + // { + // std::cout << "row " << row << std::endl; + // std::cout << "\tcolumns: " << localMatrix.toViewConstSizes().getColumns( row ) << std::endl; + // std::cout << "\tvalues: " << localMatrix.toViewConstSizes().getEntries( row ) << std::endl; + // } + } namespace @@ -884,7 +903,11 @@ void ImmiscibleMultiphaseFlow::applyDirichletBC( real64 const time_n, subRegion.getReference< array2d< real64, immiscibleFlow::LAYOUT_PHASE > >( fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key() ); + // GEOS_LOG_RANK_0(GEOS_FMT("Saturation {}", phaseVolFraction)); + integer const numPhase = m_numPhases; + + forAll< parallelDevicePolicy<> >( targetSet.size(), [=] GEOS_HOST_DEVICE ( localIndex const a ) { localIndex const ei = targetSet[a]; @@ -905,6 +928,8 @@ void ImmiscibleMultiphaseFlow::applyDirichletBC( real64 const time_n, bcPres[ei], pres[ei] ); localRhs[localRow] = rhsValue; + // GEOS_LOG_RANK_0(GEOS_FMT("BC Pressure {}", bcPres[ei])); + // GEOS_LOG_RANK_0(GEOS_FMT("Pressure {}", pres[ei])); // 3.2. For each phase, apply target saturation value for( integer ip = 0; ip < numPhase-1; ++ip ) @@ -916,12 +941,16 @@ void ImmiscibleMultiphaseFlow::applyDirichletBC( real64 const time_n, bcPhaseVolFraction[ei][ip], phaseVolFraction[ei][ip] ); localRhs[localRow + ip + 1] = rhsValue; + + // GEOS_LOG_RANK_0(GEOS_FMT("BC Saturation {}", bcPhaseVolFraction[ei][ip])); + // GEOS_LOG_RANK_0(GEOS_FMT("Saturation {}", phaseVolFraction[ei][ip])); } } ); } ); } ); } + real64 ImmiscibleMultiphaseFlow::calculateResidualNorm( real64 const & GEOS_UNUSED_PARAM( time_n ), real64 const & GEOS_UNUSED_PARAM( dt ), DomainPartition const & domain, @@ -1019,7 +1048,7 @@ void ImmiscibleMultiphaseFlow::applySystemSolution( DofManager const & dofManage GEOS_UNUSED_VAR( dt ); DofManager::CompMask pressureMask( m_numDofPerCell, 0, 1 ); - DofManager::CompMask PhaseMask( m_numDofPerCell, 1, m_numPhases ); + //DofManager::CompMask PhaseMask( m_numDofPerCell, 1, m_numPhases ); // 1. apply the pressure update @@ -1035,7 +1064,7 @@ void ImmiscibleMultiphaseFlow::applySystemSolution( DofManager const & dofManage viewKeyStruct::elemDofFieldString(), fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key(), scalingFactor, - PhaseMask ); + ~pressureMask ); // 3. synchronize forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, @@ -1049,9 +1078,26 @@ void ImmiscibleMultiphaseFlow::applySystemSolution( DofManager const & dofManage CommunicationTools::getInstance().synchronizeFields( fieldsToBeSync, mesh, domain.getNeighbors(), true ); } ); + } +void ImmiscibleMultiphaseFlow::updatePhaseVolumeFraction( ElementSubRegionBase & subRegion ) const +{ + GEOS_MARK_FUNCTION; + integer const numofPhases = 2; + + //arrayView1d< real64 const> const singleSaturation = subRegion.getField< fields::immiscibleMultiphaseFlow::singleSaturation >(); + arrayView2d< real64, immiscibleFlow::USD_PHASE > const phaseVolumeFraction = subRegion.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); + + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const ei ) + { + // phaseVolumeFraction[ei][0] = singleSaturation[ei]; + phaseVolumeFraction[ei][1] = 1.0 - phaseVolumeFraction[ei][0]; + } + ); +} + void ImmiscibleMultiphaseFlow::resetStateToBeginningOfStep( DomainPartition & domain ) { GEOS_MARK_FUNCTION; @@ -1193,6 +1239,7 @@ void ImmiscibleMultiphaseFlow::updateState( DomainPartition & domain ) // update porosity, permeability, and solid internal energy updatePorosityAndPermeability( subRegion ); // update all fluid properties + updatePhaseVolumeFraction( subRegion ); updateFluidState( subRegion ); } ); } ); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp index a5b0ccdf809..0e95c760cea 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp @@ -125,6 +125,8 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase void updateFluidState( ElementSubRegionBase & subRegion ) const; + void updatePhaseVolumeFraction( ElementSubRegionBase & subRegion ) const; + virtual void saveConvergedState( ElementSubRegionBase & subRegion ) const override final; virtual void updateState( DomainPartition & domain ) override final; diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp index 97690653236..7bbcd75004e 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp @@ -963,15 +963,30 @@ class ResidualNormKernel : public solverBaseKernels::ResidualNormKernelBase< num virtual void computeLinf( localIndex const ei, LinfStackVariables & stack ) const override { + real64 massNormalizer = 0; + for( integer idof = 0; idof < m_numPhases; ++idof ) + { + massNormalizer += LvArray::math::max( m_minNormalizer, m_phaseMass_n[ei][idof] ); + } + for( integer idof = 0; idof < m_numPhases; ++idof ) { - real64 const massNormalizer = LvArray::math::max( m_minNormalizer, m_phaseMass_n[ei][idof] ); real64 const valMass = LvArray::math::abs( m_localResidual[stack.localRow + idof] ) / massNormalizer; if( valMass > stack.localValue[0] ) { stack.localValue[0] = valMass; } } + + // for( integer idof = 0; idof < m_numPhases; ++idof ) + // { + // real64 const massNormalizer = LvArray::math::max( m_minNormalizer, m_phaseMass_n[ei][idof] ); + // real64 const valMass = LvArray::math::abs( m_localResidual[stack.localRow + idof] ) / massNormalizer; + // if( valMass > stack.localValue[0] ) + // { + // stack.localValue[0] = valMass; + // } + // } } From f4be6ef0ad8b3d3fb4df6f05bc23b856f57cc287 Mon Sep 17 00:00:00 2001 From: Ammara-14 Date: Thu, 17 Oct 2024 12:34:36 -0700 Subject: [PATCH 041/104] Fixed relative permeability calculation --- .../fluidFlow/ImmiscibleMultiphaseKernels.hpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp index 7bbcd75004e..4f98986dd75 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp @@ -815,6 +815,7 @@ class PhaseMobilityKernel arraySlice1d< real64, immiscibleFlow::USD_PHASE - 1 > const phaseMob = m_phaseMob[ei]; arraySlice2d< real64, immiscibleFlow::USD_PHASE_DS - 1 > const dPhaseMob = m_dPhaseMob[ei]; + int sign[2] = {1, -1}; for( integer ip = 0; ip < numPhase; ++ip ) { @@ -830,11 +831,11 @@ class PhaseMobilityKernel phaseMob[ip] = mobility; dPhaseMob[ip][Deriv::dP] = mobility * (dDens_dP / density - dVisc_dP / viscosity); - for( integer jp = 0; jp < numPhase-1; ++jp ) - { - real64 const dRelPerm_dS = m_dPhaseRelPerm_dPhaseVolFrac[ei][0][ip][jp]; - dPhaseMob[ip][Deriv::dS+jp] = dRelPerm_dS * density / viscosity; - } + // for( integer jp = 0; jp < numPhase-1; ++jp ) + // { + real64 const dRelPerm_dS = sign[ip] * m_dPhaseRelPerm_dPhaseVolFrac[ei][0][ip][ip]; + dPhaseMob[ip][Deriv::dS] = dRelPerm_dS * density / viscosity; + // } // call the lambda in the phase loop to allow the reuse of the relperm, density, viscosity, and mobility // possible use: assemble the derivatives wrt temperature From 2acd7c99ea42d63bf4ab9af2f0f17001691242ec Mon Sep 17 00:00:00 2001 From: DENEL Bertrand Date: Thu, 17 Oct 2024 17:09:37 -0500 Subject: [PATCH 042/104] Clean up and formatting. --- .../fluidFlow/ImmiscibleMultiphaseFlow.cpp | 71 +++++++++---------- .../fluidFlow/ImmiscibleMultiphaseKernels.hpp | 16 ++--- 2 files changed, 40 insertions(+), 47 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index cc1191e0fa3..0a1429ef807 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -133,7 +133,7 @@ void ImmiscibleMultiphaseFlow::registerDataOnMesh( Group & meshBodies ) subRegion.registerField< phaseVolumeFraction_n >( getName() ). reference().resizeDimension< 1 >( m_numPhases ); - subRegion.registerField< bcPhaseVolumeFraction>( getName() ). + subRegion.registerField< bcPhaseVolumeFraction >( getName() ). reference().resizeDimension< 1 >( m_numPhases ); subRegion.registerField< phaseMass >( getName() ). @@ -302,7 +302,6 @@ void ImmiscibleMultiphaseFlow::updatePhaseMass( ElementSubRegionBase & subRegion TwoPhaseFluid const & fluid = getConstitutiveModel< TwoPhaseFluid >( subRegion, fluidName ); CoupledSolidBase const & solid = getConstitutiveModel< CoupledSolidBase >( subRegion, solidName ); - integer const numofPhases = 2; arrayView1d< real64 const > const volume = subRegion.getElementVolume(); arrayView2d< real64 const > const porosity = solid.getPorosity(); @@ -655,8 +654,8 @@ void ImmiscibleMultiphaseFlow::assembleAccumulationTerm( DomainPartition & domai localJacobian[ip][0] += dPhaseMass_dP; real64 const dPhaseMass_dS = poreVolume * phaseDens[ei][0][ip]; - - + + // if ( ip == 0) // { // localJacobian[ip][1] += dPhaseMass_dS; @@ -756,7 +755,7 @@ void ImmiscibleMultiphaseFlow::applyBoundaryConditions( real64 const time_n, arrayView1d< real64 > const & localRhs ) { GEOS_MARK_FUNCTION; - + // apply pressure boundary conditions. applyDirichletBC( time_n, dt, dofManager, domain, localMatrix.toViewConstSizes(), localRhs.toView() ); @@ -871,7 +870,7 @@ void ImmiscibleMultiphaseFlow::applyDirichletBC( real64 const time_n, // 2. Apply saturation BC (phase volume fraction) and store in a separate field applyFieldValue< ElementSubRegionBase >( time_n, dt, mesh, bcLogMessage, fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key(), - fields::immiscibleMultiphaseFlow::bcPhaseVolumeFraction::key() ); + fields::immiscibleMultiphaseFlow::bcPhaseVolumeFraction::key() ); globalIndex const rankOffset = dofManager.rankOffset(); string const dofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); @@ -890,8 +889,8 @@ void ImmiscibleMultiphaseFlow::applyDirichletBC( real64 const time_n, arrayView1d< real64 const > const bcPres = subRegion.getReference< array1d< real64 > >( fields::flow::bcPressure::key() ); arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const bcPhaseVolFraction = - subRegion.getReference< array2d< real64, immiscibleFlow::LAYOUT_PHASE > >( - fields::immiscibleMultiphaseFlow::bcPhaseVolumeFraction::key() ); + subRegion.getReference< array2d< real64, immiscibleFlow::LAYOUT_PHASE > >( + fields::immiscibleMultiphaseFlow::bcPhaseVolumeFraction::key() ); arrayView1d< integer const > const ghostRank = subRegion.getReference< array1d< integer > >( ObjectManagerBase::viewKeyStruct::ghostRankString() ); @@ -900,10 +899,10 @@ void ImmiscibleMultiphaseFlow::applyDirichletBC( real64 const time_n, arrayView1d< real64 const > const pres = subRegion.getReference< array1d< real64 > >( fields::flow::pressure::key() ); arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFraction = - subRegion.getReference< array2d< real64, immiscibleFlow::LAYOUT_PHASE > >( - fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key() ); + subRegion.getReference< array2d< real64, immiscibleFlow::LAYOUT_PHASE > >( + fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key() ); - // GEOS_LOG_RANK_0(GEOS_FMT("Saturation {}", phaseVolFraction)); + // GEOS_LOG_RANK_0(GEOS_FMT("Saturation {}", phaseVolFraction)); integer const numPhase = m_numPhases; @@ -928,8 +927,8 @@ void ImmiscibleMultiphaseFlow::applyDirichletBC( real64 const time_n, bcPres[ei], pres[ei] ); localRhs[localRow] = rhsValue; - // GEOS_LOG_RANK_0(GEOS_FMT("BC Pressure {}", bcPres[ei])); - // GEOS_LOG_RANK_0(GEOS_FMT("Pressure {}", pres[ei])); + // GEOS_LOG_RANK_0(GEOS_FMT("BC Pressure {}", bcPres[ei])); + // GEOS_LOG_RANK_0(GEOS_FMT("Pressure {}", pres[ei])); // 3.2. For each phase, apply target saturation value for( integer ip = 0; ip < numPhase-1; ++ip ) @@ -942,8 +941,8 @@ void ImmiscibleMultiphaseFlow::applyDirichletBC( real64 const time_n, phaseVolFraction[ei][ip] ); localRhs[localRow + ip + 1] = rhsValue; - // GEOS_LOG_RANK_0(GEOS_FMT("BC Saturation {}", bcPhaseVolFraction[ei][ip])); - // GEOS_LOG_RANK_0(GEOS_FMT("Saturation {}", phaseVolFraction[ei][ip])); + // GEOS_LOG_RANK_0(GEOS_FMT("BC Saturation {}", bcPhaseVolFraction[ei][ip])); + // GEOS_LOG_RANK_0(GEOS_FMT("Saturation {}", phaseVolFraction[ei][ip])); } } ); } ); @@ -980,9 +979,6 @@ real64 ImmiscibleMultiphaseFlow::calculateResidualNorm( real64 const & GEOS_UNUS real64 subRegionResidualNorm[numNorm]{}; real64 subRegionResidualNormalizer[numNorm]{}; - string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); - TwoPhaseFluid const & fluid = getConstitutiveModel< TwoPhaseFluid >( subRegion, fluidName ); - string const & solidName = subRegion.getReference< string >( viewKeyStruct::solidNamesString() ); CoupledSolidBase const & solid = getConstitutiveModel< CoupledSolidBase >( subRegion, solidName ); @@ -1040,10 +1036,10 @@ real64 ImmiscibleMultiphaseFlow::calculateResidualNorm( real64 const & GEOS_UNUS } void ImmiscibleMultiphaseFlow::applySystemSolution( DofManager const & dofManager, - arrayView1d< real64 const > const & localSolution, - real64 const scalingFactor, - real64 const dt, - DomainPartition & domain ) + arrayView1d< real64 const > const & localSolution, + real64 const scalingFactor, + real64 const dt, + DomainPartition & domain ) { GEOS_UNUSED_VAR( dt ); @@ -1053,18 +1049,18 @@ void ImmiscibleMultiphaseFlow::applySystemSolution( DofManager const & dofManage // 1. apply the pressure update dofManager.addVectorToField( localSolution, - viewKeyStruct::elemDofFieldString(), - fields::flow::pressure::key(), - scalingFactor, - pressureMask ); + viewKeyStruct::elemDofFieldString(), + fields::flow::pressure::key(), + scalingFactor, + pressureMask ); // 2. apply the phaseVolumeFraction update dofManager.addVectorToField( localSolution, - viewKeyStruct::elemDofFieldString(), - fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key(), - scalingFactor, - ~pressureMask ); + viewKeyStruct::elemDofFieldString(), + fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key(), + scalingFactor, + ~pressureMask ); // 3. synchronize forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, @@ -1085,18 +1081,15 @@ void ImmiscibleMultiphaseFlow::applySystemSolution( DofManager const & dofManage void ImmiscibleMultiphaseFlow::updatePhaseVolumeFraction( ElementSubRegionBase & subRegion ) const { GEOS_MARK_FUNCTION; - integer const numofPhases = 2; - - //arrayView1d< real64 const> const singleSaturation = subRegion.getField< fields::immiscibleMultiphaseFlow::singleSaturation >(); + arrayView2d< real64, immiscibleFlow::USD_PHASE > const phaseVolumeFraction = subRegion.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); - + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const ei ) { - // phaseVolumeFraction[ei][0] = singleSaturation[ei]; - phaseVolumeFraction[ei][1] = 1.0 - phaseVolumeFraction[ei][0]; - } - ); -} + phaseVolumeFraction[ei][1] = 1.0 - phaseVolumeFraction[ei][0]; + } ); +} + void ImmiscibleMultiphaseFlow::resetStateToBeginningOfStep( DomainPartition & domain ) { diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp index 4f98986dd75..0f668592462 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp @@ -831,10 +831,10 @@ class PhaseMobilityKernel phaseMob[ip] = mobility; dPhaseMob[ip][Deriv::dP] = mobility * (dDens_dP / density - dVisc_dP / viscosity); - // for( integer jp = 0; jp < numPhase-1; ++jp ) - // { - real64 const dRelPerm_dS = sign[ip] * m_dPhaseRelPerm_dPhaseVolFrac[ei][0][ip][ip]; - dPhaseMob[ip][Deriv::dS] = dRelPerm_dS * density / viscosity; + // for( integer jp = 0; jp < numPhase-1; ++jp ) + // { + real64 const dRelPerm_dS = sign[ip] * m_dPhaseRelPerm_dPhaseVolFrac[ei][0][ip][ip]; + dPhaseMob[ip][Deriv::dS] = dRelPerm_dS * density / viscosity; // } // call the lambda in the phase loop to allow the reuse of the relperm, density, viscosity, and mobility @@ -965,10 +965,10 @@ class ResidualNormKernel : public solverBaseKernels::ResidualNormKernelBase< num LinfStackVariables & stack ) const override { real64 massNormalizer = 0; - for( integer idof = 0; idof < m_numPhases; ++idof ) + for( integer idof = 0; idof < m_numPhases; ++idof ) { - massNormalizer += LvArray::math::max( m_minNormalizer, m_phaseMass_n[ei][idof] ); - } + massNormalizer += LvArray::math::max( m_minNormalizer, m_phaseMass_n[ei][idof] ); + } for( integer idof = 0; idof < m_numPhases; ++idof ) { @@ -978,7 +978,7 @@ class ResidualNormKernel : public solverBaseKernels::ResidualNormKernelBase< num stack.localValue[0] = valMass; } } - + // for( integer idof = 0; idof < m_numPhases; ++idof ) // { // real64 const massNormalizer = LvArray::math::max( m_minNormalizer, m_phaseMass_n[ei][idof] ); From 7089df709532f5c3ad1d10863effde3073e204f3 Mon Sep 17 00:00:00 2001 From: DENEL Bertrand Date: Fri, 18 Oct 2024 12:37:25 -0500 Subject: [PATCH 043/104] Fixed GPU compilation. --- .../fluidFlow/ImmiscibleMultiphaseFlow.cpp | 8 -------- .../fluidFlow/ImmiscibleMultiphaseFlow.hpp | 12 ++++++------ 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index 0a1429ef807..c18af502abc 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -902,8 +902,6 @@ void ImmiscibleMultiphaseFlow::applyDirichletBC( real64 const time_n, subRegion.getReference< array2d< real64, immiscibleFlow::LAYOUT_PHASE > >( fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key() ); - // GEOS_LOG_RANK_0(GEOS_FMT("Saturation {}", phaseVolFraction)); - integer const numPhase = m_numPhases; @@ -927,8 +925,6 @@ void ImmiscibleMultiphaseFlow::applyDirichletBC( real64 const time_n, bcPres[ei], pres[ei] ); localRhs[localRow] = rhsValue; - // GEOS_LOG_RANK_0(GEOS_FMT("BC Pressure {}", bcPres[ei])); - // GEOS_LOG_RANK_0(GEOS_FMT("Pressure {}", pres[ei])); // 3.2. For each phase, apply target saturation value for( integer ip = 0; ip < numPhase-1; ++ip ) @@ -940,9 +936,6 @@ void ImmiscibleMultiphaseFlow::applyDirichletBC( real64 const time_n, bcPhaseVolFraction[ei][ip], phaseVolFraction[ei][ip] ); localRhs[localRow + ip + 1] = rhsValue; - - // GEOS_LOG_RANK_0(GEOS_FMT("BC Saturation {}", bcPhaseVolFraction[ei][ip])); - // GEOS_LOG_RANK_0(GEOS_FMT("Saturation {}", phaseVolFraction[ei][ip])); } } ); } ); @@ -957,7 +950,6 @@ real64 ImmiscibleMultiphaseFlow::calculateResidualNorm( real64 const & GEOS_UNUS arrayView1d< real64 const > const & localRhs ) { GEOS_MARK_FUNCTION; - integer constexpr numNorm = 1; // mass balance array1d< real64 > localResidualNorm; array1d< real64 > localResidualNormalizer; localResidualNorm.resize( numNorm ); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp index 0e95c760cea..47f450594d9 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp @@ -203,6 +203,12 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase virtual void initializePostInitialConditionsPreSubGroups() override; + /** + * @brief Function to update fluid mass + * @param subRegion subregion that contains the fields + */ + void updatePhaseMass( ElementSubRegionBase & subRegion ) const; + private: virtual void postInputInitialization() override; @@ -215,12 +221,6 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase */ void updateFluidModel( ObjectManagerBase & dataGroup ) const; - /** - * @brief Function to update fluid mass - * @param subRegion subregion that contains the fields - */ - void updatePhaseMass( ElementSubRegionBase & subRegion ) const; - /** * @brief Update all relevant relperm models using current values of phase volume fraction * @param dataGroup the group storing the required fields From 4418aaa065b30fd019c11db6ab205bbb601b953a Mon Sep 17 00:00:00 2001 From: DENEL Bertrand Date: Fri, 18 Oct 2024 16:08:39 -0500 Subject: [PATCH 044/104] Minor formatting to pass the CI uncrustify test --- .../physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp | 2 +- .../unitTests/constitutiveTests/testTwoPhaseFluid.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp index 47f450594d9..f5859062729 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp @@ -207,7 +207,7 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase * @brief Function to update fluid mass * @param subRegion subregion that contains the fields */ - void updatePhaseMass( ElementSubRegionBase & subRegion ) const; + void updatePhaseMass( ElementSubRegionBase & subRegion ) const; private: diff --git a/src/coreComponents/unitTests/constitutiveTests/testTwoPhaseFluid.cpp b/src/coreComponents/unitTests/constitutiveTests/testTwoPhaseFluid.cpp index ef37ec0cb13..b37fc732a55 100644 --- a/src/coreComponents/unitTests/constitutiveTests/testTwoPhaseFluid.cpp +++ b/src/coreComponents/unitTests/constitutiveTests/testTwoPhaseFluid.cpp @@ -99,7 +99,7 @@ class TwoPhaseFluidTest : public ConstitutiveTestBase< TwoPhaseFluid > fluidCopy.allocateConstitutiveData( fluid.getParent(), 1 ); // extract data views from both fluids -#define GET_FLUID_DATA( FLUID, TRAIT ) \ + #define GET_FLUID_DATA( FLUID, TRAIT ) \ FLUID.getReference< TRAIT::type >( TRAIT::key() )[0][0] constitutive::MultiFluidVarSlice< real64, 1, constitutive::multifluid::USD_PHASE - 2, constitutive::multifluid::USD_PHASE_DC - 2 > phaseVisc { From 61c61698480620c2be9e28c87e1df427aa8463ac Mon Sep 17 00:00:00 2001 From: DENEL Bertrand Date: Wed, 23 Oct 2024 16:42:32 -0500 Subject: [PATCH 045/104] Fixed reset function for saturations --- .../physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index c18af502abc..e941b4a376b 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -1108,7 +1108,7 @@ void ImmiscibleMultiphaseFlow::resetStateToBeginningOfStep( DomainPartition & do arrayView2d< real64, immiscibleFlow::USD_PHASE > const phaseVolFrac = subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); - phaseVolFrac.setValues< parallelDevicePolicy<> >( phaseVolFrac ); + phaseVolFrac.setValues< parallelDevicePolicy<> >( phaseVolFrac_n ); arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const & phaseMass_n = subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseMass_n >(); From b8eafc336ad1f80707b001b7dd46275ba0c30684 Mon Sep 17 00:00:00 2001 From: DENEL Bertrand Date: Wed, 23 Oct 2024 19:16:28 -0500 Subject: [PATCH 046/104] Added a unit test to numerically check the Jacobian. --- .../fluidFlow/ImmiscibleMultiphaseFlow.hpp | 15 +- .../unitTests/fluidFlowTests/CMakeLists.txt | 3 +- .../testImmiscibleMultiphaseFlow.cpp | 448 ++++++++++++++++++ 3 files changed, 459 insertions(+), 7 deletions(-) create mode 100644 src/coreComponents/unitTests/fluidFlowTests/testImmiscibleMultiphaseFlow.cpp diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp index f5859062729..8abacdc7145 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp @@ -209,6 +209,14 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase */ void updatePhaseMass( ElementSubRegionBase & subRegion ) const; + struct viewKeyStruct : public FlowSolverBase::viewKeyStruct + { + static constexpr char const * capPressureNamesString() { return "capPressureNames"; } + static constexpr char const * relPermNamesString() { return "relPermNames"; } + static constexpr char const * elemDofFieldString() { return "elemDofField"; } + }; + + private: virtual void postInputInitialization() override; @@ -265,12 +273,7 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase /// flag to determine whether or not to use total velocity formulation integer m_useTotalMassEquation; - struct viewKeyStruct : public FlowSolverBase::viewKeyStruct - { - static constexpr char const * capPressureNamesString() { return "capPressureNames"; } - static constexpr char const * relPermNamesString() { return "relPermNames"; } - static constexpr char const * elemDofFieldString() { return "elemDofField"; } - }; + private: diff --git a/src/coreComponents/unitTests/fluidFlowTests/CMakeLists.txt b/src/coreComponents/unitTests/fluidFlowTests/CMakeLists.txt index c21190560cf..0663d3ad720 100644 --- a/src/coreComponents/unitTests/fluidFlowTests/CMakeLists.txt +++ b/src/coreComponents/unitTests/fluidFlowTests/CMakeLists.txt @@ -4,7 +4,8 @@ set( gtest_geosx_tests testThermalCompMultiphaseFlow.cpp testThermalSinglePhaseFlow.cpp testFlowStatistics.cpp - testTransmissibility.cpp ) + testTransmissibility.cpp + testImmiscibleMultiphaseFlow.cpp ) if( ENABLE_PVTPackage ) list( APPEND gtest_geosx_tests diff --git a/src/coreComponents/unitTests/fluidFlowTests/testImmiscibleMultiphaseFlow.cpp b/src/coreComponents/unitTests/fluidFlowTests/testImmiscibleMultiphaseFlow.cpp new file mode 100644 index 00000000000..9e2c4cc4b06 --- /dev/null +++ b/src/coreComponents/unitTests/fluidFlowTests/testImmiscibleMultiphaseFlow.cpp @@ -0,0 +1,448 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 Total, S.A + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2023-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +#include "mainInterface/initialization.hpp" +#include "mainInterface/GeosxState.hpp" +#include "constitutive/fluid/twophasefluid/TwoPhaseFluid.hpp" +#include "physicsSolvers/PhysicsSolverManager.hpp" +#include "physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp" +#include "unitTests/fluidFlowTests/testCompFlowUtils.hpp" + +using namespace geos; +using namespace geos::dataRepository; +using namespace geos::constitutive; +using namespace geos::testing; + +CommandLineOptions g_commandLineOptions; + +// Sphinx start after input XML +char const *xmlInput = + R"xml( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + )xml"; +// Sphinx end before input XML + +template< typename LAMBDA > +void fillCellCenteredNumericalJacobian( ImmiscibleMultiphaseFlow & solver, + DomainPartition & domain, + real64 const perturbParameter, + arrayView1d< real64 > residual, + arrayView1d< real64 > residualOrig, + CRSMatrixView< real64, globalIndex > jacobian, + CRSMatrixView< real64, globalIndex > jacobianFD, + LAMBDA assembleFunction ) +{ + DofManager const & dofManager = solver.getDofManager(); + string const elemDofKey = dofManager.getKey( ImmiscibleMultiphaseFlow::viewKeyStruct::elemDofFieldString()); + + solver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + arrayView1d< string const > const & regionNames ) + { + mesh.getElemManager().forElementSubRegions( regionNames, + [&]( localIndex const, + ElementSubRegionBase & subRegion ) + { + arrayView1d< integer const > const & elemGhostRank = subRegion.ghostRank(); + arrayView1d< globalIndex const > const & elemDofNumber = + subRegion.getReference< array1d< globalIndex > >( elemDofKey ); + + arrayView1d< real64 > const pres = + subRegion.getField< fields::flow::pressure >(); + + arrayView2d< real64, immiscibleFlow::USD_PHASE > const phaseVolumeFraction = + subRegion.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); + + + for( localIndex ei = 0; ei < subRegion.size(); ++ei ) + { + if( elemGhostRank[ei] >= 0 ) + { + continue; + } + + // Step 1: compute numerical derivatives wrt pressure + solver.resetStateToBeginningOfStep( domain ); + pres.move( hostMemorySpace, true ); + + real64 const dP = perturbParameter * (pres[ei] + perturbParameter); + pres[ei] += dP; + +#if defined(GEOS_USE_CUDA) + pres.move( parallelDeviceMemorySpace, false ); +#endif + solver.updateState( domain ); + + residual.zero(); + jacobian.zero(); + assembleFunction( jacobian.toViewConstSizes(), residual.toView()); + + fillNumericalJacobian( residual.toViewConst(), + residualOrig.toViewConst(), + elemDofNumber[ei], + dP, + jacobianFD.toViewConstSizes()); + + + // Step 2: compute numerical derivatives wrt saturation + solver.resetStateToBeginningOfStep( domain ); + phaseVolumeFraction.move( hostMemorySpace, true ); + + real64 const dS = perturbParameter * (phaseVolumeFraction[ei][0] + perturbParameter); + phaseVolumeFraction[ei][0] += dS; + phaseVolumeFraction[ei][1] = 1- phaseVolumeFraction[ei][0]; + +#if defined(GEOS_USE_CUDA) + phaseVolumeFraction.move( parallelDeviceMemorySpace, false ); +#endif + + solver.updateState( domain ); + + residual.zero(); + jacobian.zero(); + assembleFunction( jacobian.toViewConstSizes(), residual.toView()); + + fillNumericalJacobian( residual.toViewConst(), + residualOrig.toViewConst(), + elemDofNumber[ei]+1, + dS, + jacobianFD.toViewConstSizes()); + } + } ); + } ); +} + +template< typename LAMBDA > +void testNumericalJacobian( ImmiscibleMultiphaseFlow & solver, + DomainPartition & domain, + real64 const perturbParameter, + real64 const relTol, + LAMBDA assembleFunction ) +{ + CRSMatrix< real64, globalIndex > const & jacobian = solver.getLocalMatrix(); + array1d< real64 > residual( jacobian.numRows()); + + // assemble the analytical residual + solver.resetStateToBeginningOfStep( domain ); + + residual.zero(); + jacobian.zero(); + + assembleFunction( jacobian.toViewConstSizes(), residual.toView()); + residual.move( hostMemorySpace, false ); + + // copy the analytical residual + array1d< real64 > residualOrig( residual ); + + // create the numerical jacobian + jacobian.move( hostMemorySpace ); + CRSMatrix< real64, globalIndex > jacobianFD( jacobian ); + jacobianFD.zero(); + + // fill jacobian FD + fillCellCenteredNumericalJacobian( solver, + domain, + perturbParameter, + residual.toView(), + residualOrig.toView(), + jacobian.toView(), + jacobianFD.toView(), + assembleFunction ); + + // assemble the analytical jacobian + solver.resetStateToBeginningOfStep( domain ); + + residual.zero(); + jacobian.zero(); + assembleFunction( jacobian.toViewConstSizes(), residual.toView()); + compareLocalMatrices( jacobian.toViewConst(), jacobianFD.toViewConst(), relTol ); +} + +class ImmiscibleMultiphaseFlowTest : public ::testing::Test +{ +public: + ImmiscibleMultiphaseFlowTest(): state( std::make_unique< CommandLineOptions >( g_commandLineOptions )) + {} + +protected: + void SetUp() override + { + setupProblemFromXML( state.getProblemManager(), xmlInput ); + solver = &state.getProblemManager().getPhysicsSolverManager().getGroup< ImmiscibleMultiphaseFlow >( "FlowSolver" ); + + DomainPartition & domain = state.getProblemManager().getDomainPartition(); + + solver->setupSystem( domain, + solver->getDofManager(), + solver->getLocalMatrix(), + solver->getSystemRhs(), + solver->getSystemSolution()); + + solver->implicitStepSetup( time, dt, domain ); + } + + static real64 constexpr time = 0.0; + static real64 constexpr dt = 1e4; + static real64 constexpr eps = std::numeric_limits< real64 >::epsilon(); + + GeosxState state; + ImmiscibleMultiphaseFlow *solver; +}; + +real64 constexpr ImmiscibleMultiphaseFlowTest::time; +real64 constexpr ImmiscibleMultiphaseFlowTest::dt; +real64 constexpr ImmiscibleMultiphaseFlowTest::eps; + + +TEST_F( ImmiscibleMultiphaseFlowTest, jacobianNumericalCheck_flux ) +{ + real64 const perturb = 0.000001; + real64 const tol = 1e-2; // 1% error margin + + DomainPartition & domain = state.getProblemManager().getDomainPartition(); + + testNumericalJacobian( *solver, domain, perturb, tol, + [&]( CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) + { + solver->assembleFluxTerms( dt, domain, solver->getDofManager(), localMatrix, localRhs ); + } ); +} + + +TEST_F( ImmiscibleMultiphaseFlowTest, jacobianNumericalCheck_accumulationVolumeBalance ) +{ + real64 const perturb = sqrt( eps ); + real64 const tol = 1e-2; // 1% error margin + + DomainPartition & domain = state.getProblemManager().getDomainPartition(); + + testNumericalJacobian( *solver, domain, perturb, tol, + [&] ( CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) + { + solver->assembleAccumulationTerm( domain, solver->getDofManager(), localMatrix, localRhs ); + } ); +} + + +int main( int argc, char * *argv ) +{ + ::testing::InitGoogleTest( &argc, argv ); + g_commandLineOptions = *geos::basicSetup( argc, argv ); + int const result = RUN_ALL_TESTS(); + geos::basicCleanup(); + return result; +} From fc01af3acdd315f1021f4e28b40b5444a63a8a2b Mon Sep 17 00:00:00 2001 From: Ammara-14 Date: Thu, 24 Oct 2024 10:56:13 -0700 Subject: [PATCH 047/104] added applySourceFlux --- .../fluidFlow/ImmiscibleMultiphaseFlow.cpp | 158 ++++++++++++++++++ .../fluidFlow/ImmiscibleMultiphaseFlow.hpp | 7 + 2 files changed, 165 insertions(+) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index e941b4a376b..72a147e432e 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -942,6 +942,164 @@ void ImmiscibleMultiphaseFlow::applyDirichletBC( real64 const time_n, } ); } +void ImmiscibleMultiphaseFlow::applySourceFluxBC( real64 const time_n, + real64 const dt, + DomainPartition & domain, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) const +{ + GEOS_MARK_FUNCTION; + + FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); + + string const dofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); + + // Step 1: count individual source flux boundary conditions + + std::map< string, localIndex > bcNameToBcId; + localIndex bcCounter = 0; + + fsManager.forSubGroups< SourceFluxBoundaryCondition >( [&] ( SourceFluxBoundaryCondition const & bc ) + { + // collect all the bc names to idx + bcNameToBcId[bc.getName()] = bcCounter; + bcCounter++; + } ); + + if( bcCounter == 0 ) + { + return; + } + + // Step 2: count the set size for each source flux (each source flux may have multiple target sets) + + array1d< globalIndex > bcAllSetsSize( bcNameToBcId.size() ); + + computeSourceFluxSizeScalingFactor( time_n, + dt, + domain, + bcNameToBcId, + bcAllSetsSize.toView() ); + + // Step 3: we are ready to impose the boundary condition, normalized by the set size + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + arrayView1d< string const > const & ) + { + integer const isThermal = 0; + + fsManager.apply< ElementSubRegionBase, + SourceFluxBoundaryCondition >( time_n + dt, + mesh, + SourceFluxBoundaryCondition::catalogName(), + [&, isThermal]( SourceFluxBoundaryCondition const & fs, + string const & setName, + SortedArrayView< localIndex const > const & targetSet, + ElementSubRegionBase & subRegion, + string const & ) + { + if( targetSet.size() == 0 ) + { + return; + } + if( !subRegion.hasWrapper( dofKey ) ) + { + if( fs.getLogLevel() >= 1 ) + { + GEOS_LOG_RANK( GEOS_FMT( "{}: trying to apply SourceFlux, but its targetSet named '{}' intersects with non-simulated region named '{}'.", + getDataContext(), setName, subRegion.getName() ) ); + } + return; + } + + arrayView1d< globalIndex const > const dofNumber = subRegion.getReference< array1d< globalIndex > >( dofKey ); + arrayView1d< integer const > const ghostRank = subRegion.ghostRank(); + + // Step 3.1: get the values of the source boundary condition that need to be added to the rhs + + array1d< globalIndex > dofArray( targetSet.size() ); + array1d< real64 > rhsContributionArray( targetSet.size() ); + arrayView1d< real64 > rhsContributionArrayView = rhsContributionArray.toView(); + localIndex const rankOffset = dofManager.rankOffset(); + + RAJA::ReduceSum< parallelDeviceReduce, real64 > massProd( 0.0 ); + + // note that the dofArray will not be used after this step (simpler to use dofNumber instead) + fs.computeRhsContribution< FieldSpecificationAdd, + parallelDevicePolicy<> >( targetSet.toViewConst(), + time_n + dt, + dt, + subRegion, + dofNumber, + rankOffset, + localMatrix, + dofArray.toView(), + rhsContributionArrayView, + [] GEOS_HOST_DEVICE ( localIndex const ) + { + return 0.0; + } ); + + // Step 3.2: we are ready to add the right-hand side contributions, taking into account our equation layout + + // get the normalizer + real64 const sizeScalingFactor = bcAllSetsSize[bcNameToBcId.at( fs.getName())]; + integer const fluidPhaseId = fs.getComponent(); + integer const numFluidPhases = m_numPhases; + integer const useTotalMassEquation = 0; + forAll< parallelDevicePolicy<> >( targetSet.size(), [sizeScalingFactor, + targetSet, + rankOffset, + ghostRank, + fluidPhaseId, + numFluidPhases, + useTotalMassEquation, + dofNumber, + rhsContributionArrayView, + localRhs, + massProd] GEOS_HOST_DEVICE ( localIndex const a ) + { + // we need to filter out ghosts here, because targetSet may contain them + localIndex const ei = targetSet[a]; + if( ghostRank[ei] >= 0 ) + { + return; + } + + real64 const rhsValue = rhsContributionArrayView[a] / sizeScalingFactor; // scale the contribution by the sizeScalingFactor here! + massProd += rhsValue; + if( useTotalMassEquation > 0 ) + { + // for all "fluid components", we add the value to the total mass balance equation + globalIndex const totalMassBalanceRow = dofNumber[ei] - rankOffset; + localRhs[totalMassBalanceRow] += rhsValue; + if( fluidPhaseId < numFluidPhases - 1 ) + { + globalIndex const compMassBalanceRow = totalMassBalanceRow + fluidPhaseId + 1; // component mass bal equations are shifted + localRhs[compMassBalanceRow] += rhsValue; + } + } + else + { + globalIndex const compMassBalanceRow = dofNumber[ei] - rankOffset + fluidPhaseId; + localRhs[compMassBalanceRow] += rhsValue; + } + } ); + + // SourceFluxStatsAggregator::forAllFluxStatWrappers( subRegion, fs.getName(), + // [&]( SourceFluxStatsAggregator::WrappedStats & wrapper ) + // { + // // set the new sub-region statistics for this timestep + // array1d< real64 > massProdArr{ m_numPhases }; + // massProdArr[fluidPhaseId] = massProd.get(); + // wrapper.gatherTimeStepStats( time, dt, massProdArr.toViewConst(), targetSet.size() ); + // } ); + } ); + } ); +} + real64 ImmiscibleMultiphaseFlow::calculateResidualNorm( real64 const & GEOS_UNUSED_PARAM( time_n ), real64 const & GEOS_UNUSED_PARAM( dt ), diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp index 8abacdc7145..2a13371b122 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp @@ -192,6 +192,13 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) const; +void + applySourceFluxBC( real64 const time_n, + real64 const dt, + DomainPartition & domain, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) const; /** * @brief function to set the next time step size * @param[in] currentDt the current time step size From da993f628a7158e396fd73ff3da612926b0090f2 Mon Sep 17 00:00:00 2001 From: Ammara-14 Date: Thu, 24 Oct 2024 12:30:24 -0700 Subject: [PATCH 048/104] minor fix on applySourceFluxBC --- .../fluidFlow/ImmiscibleMultiphaseFlow.cpp | 32 ++++++++++++------- .../fluidFlow/ImmiscibleMultiphaseFlow.hpp | 13 ++++---- 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index 72a147e432e..bcc7c82f8ce 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -759,6 +759,9 @@ void ImmiscibleMultiphaseFlow::applyBoundaryConditions( real64 const time_n, // apply pressure boundary conditions. applyDirichletBC( time_n, dt, dofManager, domain, localMatrix.toViewConstSizes(), localRhs.toView() ); +// apply flux boundary conditions + applySourceFluxBC( time_n, dt, dofManager, domain, localMatrix.toViewConstSizes(), localRhs.toView() ); + // for( localIndex row = 0; row < localMatrix.toViewConstSizes().numRows(); ++row ) // { // std::cout << "row " << row << std::endl; @@ -942,12 +945,12 @@ void ImmiscibleMultiphaseFlow::applyDirichletBC( real64 const time_n, } ); } -void ImmiscibleMultiphaseFlow::applySourceFluxBC( real64 const time_n, - real64 const dt, - DomainPartition & domain, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) const +void ImmiscibleMultiphaseFlow::applySourceFluxBC( real64 const time, + real64 const dt, + DofManager const & dofManager, + DomainPartition & domain, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) const { GEOS_MARK_FUNCTION; @@ -976,7 +979,7 @@ void ImmiscibleMultiphaseFlow::applySourceFluxBC( real64 const time_n, array1d< globalIndex > bcAllSetsSize( bcNameToBcId.size() ); - computeSourceFluxSizeScalingFactor( time_n, + computeSourceFluxSizeScalingFactor( time, dt, domain, bcNameToBcId, @@ -988,18 +991,25 @@ void ImmiscibleMultiphaseFlow::applySourceFluxBC( real64 const time_n, MeshLevel & mesh, arrayView1d< string const > const & ) { - integer const isThermal = 0; fsManager.apply< ElementSubRegionBase, - SourceFluxBoundaryCondition >( time_n + dt, + SourceFluxBoundaryCondition >( time + dt, mesh, SourceFluxBoundaryCondition::catalogName(), - [&, isThermal]( SourceFluxBoundaryCondition const & fs, + [&]( SourceFluxBoundaryCondition const & fs, string const & setName, SortedArrayView< localIndex const > const & targetSet, ElementSubRegionBase & subRegion, string const & ) { + if( fs.getLogLevel() >= 1 && m_nonlinearSolverParameters.m_numNewtonIterations == 0 ) + { + globalIndex const numTargetElems = MpiWrapper::sum< globalIndex >( targetSet.size() ); + GEOS_LOG_RANK_0( GEOS_FMT( bcLogMessage, + getName(), time+dt, fs.getCatalogName(), fs.getName(), + setName, subRegion.getName(), fs.getScale(), numTargetElems ) ); + } + if( targetSet.size() == 0 ) { return; @@ -1029,7 +1039,7 @@ void ImmiscibleMultiphaseFlow::applySourceFluxBC( real64 const time_n, // note that the dofArray will not be used after this step (simpler to use dofNumber instead) fs.computeRhsContribution< FieldSpecificationAdd, parallelDevicePolicy<> >( targetSet.toViewConst(), - time_n + dt, + time + dt, dt, subRegion, dofNumber, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp index 2a13371b122..565a2b1a562 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp @@ -192,13 +192,12 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) const; -void - applySourceFluxBC( real64 const time_n, - real64 const dt, - DomainPartition & domain, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) const; + void applySourceFluxBC( real64 const time, + real64 const dt, + DofManager const & dofManager, + DomainPartition & domain, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) const; /** * @brief function to set the next time step size * @param[in] currentDt the current time step size From 9f0c7c5d2bc1d219f4a3d89a2d37e2ab6337dc8f Mon Sep 17 00:00:00 2001 From: rpiazza87 Date: Thu, 24 Oct 2024 14:51:32 -0700 Subject: [PATCH 049/104] included iterative solvers --- .../linearAlgebra/CMakeLists.txt | 1 + .../interfaces/hypre/HypreMGR.cpp | 6 ++ .../mgrStrategies/ImmiscibleMultiphaseFVM.hpp | 97 +++++++++++++++++++ .../testLinearSolverParametersEnums.cpp | 1 + .../utilities/LinearSolverParameters.hpp | 2 + .../fluidFlow/ImmiscibleMultiphaseFlow.cpp | 2 + 6 files changed, 109 insertions(+) create mode 100644 src/coreComponents/linearAlgebra/interfaces/hypre/mgrStrategies/ImmiscibleMultiphaseFVM.hpp diff --git a/src/coreComponents/linearAlgebra/CMakeLists.txt b/src/coreComponents/linearAlgebra/CMakeLists.txt index 095544ff4aa..d9b72819f54 100644 --- a/src/coreComponents/linearAlgebra/CMakeLists.txt +++ b/src/coreComponents/linearAlgebra/CMakeLists.txt @@ -101,6 +101,7 @@ if( ENABLE_HYPRE ) interfaces/hypre/mgrStrategies/CompositionalMultiphaseReservoirHybridFVM.hpp interfaces/hypre/mgrStrategies/HybridSinglePhasePoromechanics.hpp interfaces/hypre/mgrStrategies/Hydrofracture.hpp + interfaces/hypre/mgrStrategies/ImmiscibleMultiphaseFVM.hpp interfaces/hypre/mgrStrategies/LagrangianContactMechanics.hpp interfaces/hypre/mgrStrategies/MultiphasePoromechanics.hpp interfaces/hypre/mgrStrategies/SinglePhasePoromechanicsEmbeddedFractures.hpp diff --git a/src/coreComponents/linearAlgebra/interfaces/hypre/HypreMGR.cpp b/src/coreComponents/linearAlgebra/interfaces/hypre/HypreMGR.cpp index a14f0ac6b5b..f92e208ac5e 100644 --- a/src/coreComponents/linearAlgebra/interfaces/hypre/HypreMGR.cpp +++ b/src/coreComponents/linearAlgebra/interfaces/hypre/HypreMGR.cpp @@ -26,6 +26,7 @@ #include "linearAlgebra/interfaces/hypre/mgrStrategies/CompositionalMultiphaseReservoirHybridFVM.hpp" #include "linearAlgebra/interfaces/hypre/mgrStrategies/HybridSinglePhasePoromechanics.hpp" #include "linearAlgebra/interfaces/hypre/mgrStrategies/Hydrofracture.hpp" +#include "linearAlgebra/interfaces/hypre/mgrStrategies/ImmiscibleMultiphaseFVM.hpp" #include "linearAlgebra/interfaces/hypre/mgrStrategies/LagrangianContactMechanics.hpp" #include "linearAlgebra/interfaces/hypre/mgrStrategies/MultiphasePoromechanics.hpp" #include "linearAlgebra/interfaces/hypre/mgrStrategies/MultiphasePoromechanicsReservoirFVM.hpp" @@ -187,6 +188,11 @@ void hypre::mgr::createMGR( LinearSolverParameters const & params, setStrategy< SolidMechanicsEmbeddedFractures >( params.mgr, numComponentsPerField, precond, mgrData ); break; } + case LinearSolverParameters::MGR::StrategyType::immiscibleMultiphaseFVM: + { + setStrategy< ImmiscibleMultiphaseFVM >( params.mgr, numComponentsPerField, precond, mgrData ); + break; + } default: { GEOS_ERROR( "Unsupported MGR strategy: " << params.mgr.strategy ); diff --git a/src/coreComponents/linearAlgebra/interfaces/hypre/mgrStrategies/ImmiscibleMultiphaseFVM.hpp b/src/coreComponents/linearAlgebra/interfaces/hypre/mgrStrategies/ImmiscibleMultiphaseFVM.hpp new file mode 100644 index 00000000000..1fe5b33f15d --- /dev/null +++ b/src/coreComponents/linearAlgebra/interfaces/hypre/mgrStrategies/ImmiscibleMultiphaseFVM.hpp @@ -0,0 +1,97 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 Total, S.A + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2023-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/** + * @file ImmiscibleMultiphaseFVM.hpp + */ + +#ifndef GEOS_LINEARALGEBRA_INTERFACES_HYPREMGRIMMISCIBLEMULTIPHASEFVM_HPP_ +#define GEOS_LINEARALGEBRA_INTERFACES_HYPREMGRIMMISCIBLEMULTIPHASEFVM_HPP_ + +#include "linearAlgebra/interfaces/hypre/HypreMGR.hpp" + +namespace geos +{ + +namespace hypre +{ + +namespace mgr +{ + +/** + * @brief ImmiscibleMultiphaseFVM strategy. + * + * Labels description stored in point_marker_array + * 0 = pressure + * 1 = phase volume fraction + * ... = phase volume fractions + * numLabels - 1 = phase volume fraction + * + * 1-level MGR reduction strategy: + * - 1st level: eliminate the reservoir phase volume fractions + * - The coarse grid (pressure system) is solved with BoomerAMG. + * + */ +class ImmiscibleMultiphaseFVM : public MGRStrategyBase< 1 > +{ +public: + /** + * @brief Constructor. + * @param numComponentsPerField array with number of components for each field + */ + explicit ImmiscibleMultiphaseFVM( arrayView1d< int const > const & numComponentsPerField ) + : MGRStrategyBase( LvArray::integerConversion< HYPRE_Int >( numComponentsPerField[0] ) ) + { + // Level 0: eliminate last density which corresponds to the volume constraint equation + // m_labels[0].resize( m_numBlocks - 1 ); + // std::iota( m_labels[0].begin(), m_labels[0].end(), 0 ); + + // Level 0: eliminate the phase volume fractions + m_labels[0].push_back( 0 ); + + setupLabels(); + + m_levelFRelaxType[0] = MGRFRelaxationType::none; + m_levelInterpType[0] = MGRInterpolationType::injection; + m_levelRestrictType[0] = MGRRestrictionType::blockColLumped; // True-IMPES + m_levelCoarseGridMethod[0] = MGRCoarseGridMethod::galerkin; + m_levelGlobalSmootherType[0] = MGRGlobalSmootherType::ilu0; + m_levelGlobalSmootherIters[0] = 1; + } + + /** + * @brief Setup the MGR strategy. + * @param precond preconditioner wrapper + * @param mgrData auxiliary MGR data + */ + void setup( LinearSolverParameters::MGR const &, + HyprePrecWrapper & precond, + HypreMGRData & mgrData ) + { + setReduction( precond, mgrData ); + + // Configure the BoomerAMG solver used as mgr coarse solver for the pressure reduced system + setPressureAMG( mgrData.coarseSolver ); + } +}; + +} // namespace mgr + +} // namespace hypre + +} // namespace geos + +#endif /*GEOS_LINEARALGEBRA_INTERFACES_HYPREMGRCOMPOSITIONALMULTIPHASEFVM_HPP_*/ diff --git a/src/coreComponents/linearAlgebra/unitTests/testLinearSolverParametersEnums.cpp b/src/coreComponents/linearAlgebra/unitTests/testLinearSolverParametersEnums.cpp index 5194fab06bd..928adc90b45 100644 --- a/src/coreComponents/linearAlgebra/unitTests/testLinearSolverParametersEnums.cpp +++ b/src/coreComponents/linearAlgebra/unitTests/testLinearSolverParametersEnums.cpp @@ -97,6 +97,7 @@ TEST( LinearSolverParametersEnums, MGRStrategyType ) ASSERT_EQ( "compositionalMultiphaseHybridFVM", toString( EnumType::compositionalMultiphaseHybridFVM ) ); ASSERT_EQ( "compositionalMultiphaseReservoirFVM", toString( EnumType::compositionalMultiphaseReservoirFVM ) ); ASSERT_EQ( "compositionalMultiphaseReservoirHybridFVM", toString( EnumType::compositionalMultiphaseReservoirHybridFVM ) ); + ASSERT_EQ( "immiscibleMultiphaseFVM", toString( EnumType::immiscibleMultiphaseFVM ) ); ASSERT_EQ( "multiphasePoromechanics", toString( EnumType::multiphasePoromechanics ) ); ASSERT_EQ( "hydrofracture", toString( EnumType::hydrofracture ) ); ASSERT_EQ( "lagrangianContactMechanics", toString( EnumType::lagrangianContactMechanics ) ); diff --git a/src/coreComponents/linearAlgebra/utilities/LinearSolverParameters.hpp b/src/coreComponents/linearAlgebra/utilities/LinearSolverParameters.hpp index 51c2239c0a6..bf060c88d8d 100644 --- a/src/coreComponents/linearAlgebra/utilities/LinearSolverParameters.hpp +++ b/src/coreComponents/linearAlgebra/utilities/LinearSolverParameters.hpp @@ -282,6 +282,7 @@ struct LinearSolverParameters compositionalMultiphaseHybridFVM, ///< hybrid finite volume compositional multiphase flow compositionalMultiphaseReservoirFVM, ///< finite volume compositional multiphase flow with wells compositionalMultiphaseReservoirHybridFVM, ///< hybrid finite volume compositional multiphase flow with wells + immiscibleMultiphaseFVM, ///< finite volume immiscible multiphase flow reactiveCompositionalMultiphaseOBL, ///< finite volume reactive compositional flow with OBL thermalCompositionalMultiphaseFVM, ///< finite volume thermal compositional multiphase flow multiphasePoromechanics, ///< multiphase poromechanics with finite volume compositional multiphase flow @@ -374,6 +375,7 @@ ENUM_STRINGS( LinearSolverParameters::MGR::StrategyType, "compositionalMultiphaseHybridFVM", "compositionalMultiphaseReservoirFVM", "compositionalMultiphaseReservoirHybridFVM", + "immiscibleMultiphaseFVM", "reactiveCompositionalMultiphaseOBL", "thermalCompositionalMultiphaseFVM", "multiphasePoromechanics", diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index bcc7c82f8ce..38942e62c64 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -184,6 +184,8 @@ void ImmiscibleMultiphaseFlow::setConstitutiveNames( ElementSubRegionBase & subR void ImmiscibleMultiphaseFlow::initializePreSubGroups() { + m_linearSolverParameters.get().mgr.strategy = LinearSolverParameters::MGR::StrategyType::immiscibleMultiphaseFVM; + FlowSolverBase::initializePreSubGroups(); DomainPartition & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" ); From 645748d28d6f94fc8f18eda8db479d30f814147f Mon Sep 17 00:00:00 2001 From: DENEL Bertrand Date: Fri, 25 Oct 2024 11:10:27 -0500 Subject: [PATCH 050/104] Fooled compiler to prevent an unusedlambdacapture error --- .../physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index 38942e62c64..e0150d21b06 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -1060,7 +1060,7 @@ void ImmiscibleMultiphaseFlow::applySourceFluxBC( real64 const time, real64 const sizeScalingFactor = bcAllSetsSize[bcNameToBcId.at( fs.getName())]; integer const fluidPhaseId = fs.getComponent(); integer const numFluidPhases = m_numPhases; - integer const useTotalMassEquation = 0; + integer useTotalMassEquation = 0; forAll< parallelDevicePolicy<> >( targetSet.size(), [sizeScalingFactor, targetSet, rankOffset, From 6c8eefaedefff4c5f3a21ec9016a65a477c8c6bc Mon Sep 17 00:00:00 2001 From: DENEL Bertrand Date: Mon, 28 Oct 2024 12:17:30 -0500 Subject: [PATCH 051/104] Added input files for BuckleyLeverett, CapillaryPressure and Gravity tests. --- .../buckleyLeverett_base.xml | 181 ++++++++++++++++ .../buckleyLeverett_benchmark.xml | 62 ++++++ .../immiscibleTwoPhase_CapillaryPressure.xml | 190 +++++++++++++++++ .../initialSaturation1.txt | 10 + .../initialSaturation2.txt | 11 + .../x.txt | 10 + .../y.txt | 1 + .../z.txt | 1 + .../immiscibleTwoPhase_Gravity.xml | 195 ++++++++++++++++++ .../initialPressure.txt | 10 + .../initialSaturation1.txt | 10 + .../initialSaturation2.txt | 10 + .../immiscibleTwoPhase_Gravity/x.txt | 1 + .../immiscibleTwoPhase_Gravity/y.txt | 1 + .../immiscibleTwoPhase_Gravity/z.txt | 10 + 15 files changed, 703 insertions(+) create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_BuckleyLeverett/buckleyLeverett_base.xml create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_BuckleyLeverett/buckleyLeverett_benchmark.xml create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_CapillaryPressure/immiscibleTwoPhase_CapillaryPressure.xml create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_CapillaryPressure/initialSaturation1.txt create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_CapillaryPressure/initialSaturation2.txt create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_CapillaryPressure/x.txt create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_CapillaryPressure/y.txt create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_CapillaryPressure/z.txt create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_Gravity/immiscibleTwoPhase_Gravity.xml create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_Gravity/initialPressure.txt create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_Gravity/initialSaturation1.txt create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_Gravity/initialSaturation2.txt create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_Gravity/x.txt create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_Gravity/y.txt create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_Gravity/z.txt diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_BuckleyLeverett/buckleyLeverett_base.xml b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_BuckleyLeverett/buckleyLeverett_base.xml new file mode 100644 index 00000000000..4bd8a93c7c8 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_BuckleyLeverett/buckleyLeverett_base.xml @@ -0,0 +1,181 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_BuckleyLeverett/buckleyLeverett_benchmark.xml b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_BuckleyLeverett/buckleyLeverett_benchmark.xml new file mode 100644 index 00000000000..df684689511 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_BuckleyLeverett/buckleyLeverett_benchmark.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_CapillaryPressure/immiscibleTwoPhase_CapillaryPressure.xml b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_CapillaryPressure/immiscibleTwoPhase_CapillaryPressure.xml new file mode 100644 index 00000000000..46d250ee052 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_CapillaryPressure/immiscibleTwoPhase_CapillaryPressure.xml @@ -0,0 +1,190 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_CapillaryPressure/initialSaturation1.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_CapillaryPressure/initialSaturation1.txt new file mode 100644 index 00000000000..1c03b9c1871 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_CapillaryPressure/initialSaturation1.txt @@ -0,0 +1,10 @@ +1 +1 +1 +1 +1 +0 +0 +0 +0 +0 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_CapillaryPressure/initialSaturation2.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_CapillaryPressure/initialSaturation2.txt new file mode 100644 index 00000000000..cd9d2981d61 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_CapillaryPressure/initialSaturation2.txt @@ -0,0 +1,11 @@ +0 +0 +0 +0 +0 +1 +1 +1 +1 +1 + diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_CapillaryPressure/x.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_CapillaryPressure/x.txt new file mode 100644 index 00000000000..f43a1f14d26 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_CapillaryPressure/x.txt @@ -0,0 +1,10 @@ +0.5 +1.5 +2.5 +3.5 +4.5 +5.5 +6.5 +7.5 +8.5 +9.5 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_CapillaryPressure/y.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_CapillaryPressure/y.txt new file mode 100644 index 00000000000..2eb3c4fe4ee --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_CapillaryPressure/y.txt @@ -0,0 +1 @@ +0.5 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_CapillaryPressure/z.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_CapillaryPressure/z.txt new file mode 100644 index 00000000000..2eb3c4fe4ee --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_CapillaryPressure/z.txt @@ -0,0 +1 @@ +0.5 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_Gravity/immiscibleTwoPhase_Gravity.xml b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_Gravity/immiscibleTwoPhase_Gravity.xml new file mode 100644 index 00000000000..b4390686079 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_Gravity/immiscibleTwoPhase_Gravity.xml @@ -0,0 +1,195 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_Gravity/initialPressure.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_Gravity/initialPressure.txt new file mode 100644 index 00000000000..85a30e13876 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_Gravity/initialPressure.txt @@ -0,0 +1,10 @@ +495.0 +485.0 +475.0 +465.0 +455.0 +400.0 +300.0 +200.0 +100.0 +0.0 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_Gravity/initialSaturation1.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_Gravity/initialSaturation1.txt new file mode 100644 index 00000000000..99f11f6b2e7 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_Gravity/initialSaturation1.txt @@ -0,0 +1,10 @@ +0 +0 +0 +0 +0 +1 +1 +1 +1 +1 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_Gravity/initialSaturation2.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_Gravity/initialSaturation2.txt new file mode 100644 index 00000000000..1c03b9c1871 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_Gravity/initialSaturation2.txt @@ -0,0 +1,10 @@ +1 +1 +1 +1 +1 +0 +0 +0 +0 +0 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_Gravity/x.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_Gravity/x.txt new file mode 100644 index 00000000000..2eb3c4fe4ee --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_Gravity/x.txt @@ -0,0 +1 @@ +0.5 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_Gravity/y.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_Gravity/y.txt new file mode 100644 index 00000000000..2eb3c4fe4ee --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_Gravity/y.txt @@ -0,0 +1 @@ +0.5 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_Gravity/z.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_Gravity/z.txt new file mode 100644 index 00000000000..f43a1f14d26 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_Gravity/z.txt @@ -0,0 +1,10 @@ +0.5 +1.5 +2.5 +3.5 +4.5 +5.5 +6.5 +7.5 +8.5 +9.5 From 05f0287c0bb89845912d662012156a1b001cfa1f Mon Sep 17 00:00:00 2001 From: DENEL Bertrand Date: Mon, 28 Oct 2024 12:39:36 -0500 Subject: [PATCH 052/104] Fixed xml format. --- .../buckleyLeverett_benchmark.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_BuckleyLeverett/buckleyLeverett_benchmark.xml b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_BuckleyLeverett/buckleyLeverett_benchmark.xml index df684689511..0fb90cd71d2 100644 --- a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_BuckleyLeverett/buckleyLeverett_benchmark.xml +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_BuckleyLeverett/buckleyLeverett_benchmark.xml @@ -1,4 +1,3 @@ - From 83086d067cda149f6643560c3f82424012fdd437 Mon Sep 17 00:00:00 2001 From: DENEL Bertrand Date: Mon, 28 Oct 2024 12:57:16 -0500 Subject: [PATCH 053/104] Updated unit test for better coverage. --- .../fluidFlow/ImmiscibleMultiphaseFlow.cpp | 22 +++++----- .../testImmiscibleMultiphaseFlow.cpp | 41 +++++++++++++++---- 2 files changed, 43 insertions(+), 20 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index e0150d21b06..f5dfe772a65 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -185,7 +185,7 @@ void ImmiscibleMultiphaseFlow::setConstitutiveNames( ElementSubRegionBase & subR void ImmiscibleMultiphaseFlow::initializePreSubGroups() { m_linearSolverParameters.get().mgr.strategy = LinearSolverParameters::MGR::StrategyType::immiscibleMultiphaseFVM; - + FlowSolverBase::initializePreSubGroups(); DomainPartition & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" ); @@ -763,7 +763,7 @@ void ImmiscibleMultiphaseFlow::applyBoundaryConditions( real64 const time_n, // apply flux boundary conditions applySourceFluxBC( time_n, dt, dofManager, domain, localMatrix.toViewConstSizes(), localRhs.toView() ); - + // for( localIndex row = 0; row < localMatrix.toViewConstSizes().numRows(); ++row ) // { // std::cout << "row " << row << std::endl; @@ -948,11 +948,11 @@ void ImmiscibleMultiphaseFlow::applyDirichletBC( real64 const time_n, } void ImmiscibleMultiphaseFlow::applySourceFluxBC( real64 const time, - real64 const dt, - DofManager const & dofManager, - DomainPartition & domain, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) const + real64 const dt, + DofManager const & dofManager, + DomainPartition & domain, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) const { GEOS_MARK_FUNCTION; @@ -999,10 +999,10 @@ void ImmiscibleMultiphaseFlow::applySourceFluxBC( real64 const time, mesh, SourceFluxBoundaryCondition::catalogName(), [&]( SourceFluxBoundaryCondition const & fs, - string const & setName, - SortedArrayView< localIndex const > const & targetSet, - ElementSubRegionBase & subRegion, - string const & ) + string const & setName, + SortedArrayView< localIndex const > const & targetSet, + ElementSubRegionBase & subRegion, + string const & ) { if( fs.getLogLevel() >= 1 && m_nonlinearSolverParameters.m_numNewtonIterations == 0 ) { diff --git a/src/coreComponents/unitTests/fluidFlowTests/testImmiscibleMultiphaseFlow.cpp b/src/coreComponents/unitTests/fluidFlowTests/testImmiscibleMultiphaseFlow.cpp index 9e2c4cc4b06..a1fc731b321 100644 --- a/src/coreComponents/unitTests/fluidFlowTests/testImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/unitTests/fluidFlowTests/testImmiscibleMultiphaseFlow.cpp @@ -88,7 +88,7 @@ char const *xmlInput = + materialList="{ fluid, rock, relperm, capPressure }"/> @@ -113,7 +113,7 @@ char const *xmlInput = - + permeabilityModelName="rockPerm" /> + name="nullSolid" /> + compressibility="0.0" /> - + phaseRelPermMaxValue="{ 1.0, 1.0 }" /> + + @@ -406,7 +413,7 @@ real64 constexpr ImmiscibleMultiphaseFlowTest::dt; real64 constexpr ImmiscibleMultiphaseFlowTest::eps; -TEST_F( ImmiscibleMultiphaseFlowTest, jacobianNumericalCheck_flux ) +TEST_F( ImmiscibleMultiphaseFlowTest, jacobianNumericalCheck_fluxTerm ) { real64 const perturb = 0.000001; real64 const tol = 1e-2; // 1% error margin @@ -422,7 +429,7 @@ TEST_F( ImmiscibleMultiphaseFlowTest, jacobianNumericalCheck_flux ) } -TEST_F( ImmiscibleMultiphaseFlowTest, jacobianNumericalCheck_accumulationVolumeBalance ) +TEST_F( ImmiscibleMultiphaseFlowTest, jacobianNumericalCheck_accumulationTerm ) { real64 const perturb = sqrt( eps ); real64 const tol = 1e-2; // 1% error margin @@ -438,6 +445,22 @@ TEST_F( ImmiscibleMultiphaseFlowTest, jacobianNumericalCheck_accumulationVolumeB } +TEST_F( ImmiscibleMultiphaseFlowTest, jacobianNumericalCheck_full ) +{ + real64 const perturb = 0.000001; + real64 const tol = 1e-2; // 1% error margin + + DomainPartition & domain = state.getProblemManager().getDomainPartition(); + + testNumericalJacobian( *solver, domain, perturb, tol, + [&] ( CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) + { + solver->assembleSystem( time, dt, domain, solver->getDofManager(), localMatrix, localRhs ); + } ); +} + + int main( int argc, char * *argv ) { ::testing::InitGoogleTest( &argc, argv ); From a99d949d5d1f7896ca3ecdc01390d35f36d08af5 Mon Sep 17 00:00:00 2001 From: DENEL Bertrand Date: Tue, 29 Oct 2024 16:06:31 -0500 Subject: [PATCH 054/104] Added SPE10_layer84 test case. --- ...iscibleTwoPhase_GravitySegregation_1d.xml} | 0 .../initialPressure.txt | 0 .../initialSaturation1.txt | 0 .../initialSaturation2.txt | 0 .../x.txt | 0 .../y.txt | 0 .../z.txt | 0 .../dens_pvdo.txt | 3 + ...ibleTwoPhase_SPE10_layer84_base_direct.xml | 238 + ...eTwoPhase_SPE10_layer84_base_iterative.xml | 238 + ...woPhase_SPE10_layer84_benchmark_direct.xml | 54 + ...hase_SPE10_layer84_benchmark_iterative.xml | 54 + .../layer84_permx.geos | 13200 ++++++++++++++++ .../layer84_permy.geos | 13200 ++++++++++++++++ .../layer84_permz.geos | 13200 ++++++++++++++++ .../layer84_poro.geos | 13200 ++++++++++++++++ .../pres_pvdo.txt | 3 + .../visc_pvdo.txt | 3 + .../xlin.geos | 60 + .../ylin.geos | 220 + .../zlin.geos | 1 + .../mgrStrategies/ImmiscibleMultiphaseFVM.hpp | 2 +- 22 files changed, 53675 insertions(+), 1 deletion(-) rename inputFiles/immiscibleMultiphaseFlow/{immiscibleTwoPhase_Gravity/immiscibleTwoPhase_Gravity.xml => immiscibleTwoPhase_GravitySegregation_1d/immiscibleTwoPhase_GravitySegregation_1d.xml} (100%) rename inputFiles/immiscibleMultiphaseFlow/{immiscibleTwoPhase_Gravity => immiscibleTwoPhase_GravitySegregation_1d}/initialPressure.txt (100%) rename inputFiles/immiscibleMultiphaseFlow/{immiscibleTwoPhase_Gravity => immiscibleTwoPhase_GravitySegregation_1d}/initialSaturation1.txt (100%) rename inputFiles/immiscibleMultiphaseFlow/{immiscibleTwoPhase_Gravity => immiscibleTwoPhase_GravitySegregation_1d}/initialSaturation2.txt (100%) rename inputFiles/immiscibleMultiphaseFlow/{immiscibleTwoPhase_Gravity => immiscibleTwoPhase_GravitySegregation_1d}/x.txt (100%) rename inputFiles/immiscibleMultiphaseFlow/{immiscibleTwoPhase_Gravity => immiscibleTwoPhase_GravitySegregation_1d}/y.txt (100%) rename inputFiles/immiscibleMultiphaseFlow/{immiscibleTwoPhase_Gravity => immiscibleTwoPhase_GravitySegregation_1d}/z.txt (100%) create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/dens_pvdo.txt create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/immiscibleTwoPhase_SPE10_layer84_base_direct.xml create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/immiscibleTwoPhase_SPE10_layer84_base_iterative.xml create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/immiscibleTwoPhase_SPE10_layer84_benchmark_direct.xml create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/immiscibleTwoPhase_SPE10_layer84_benchmark_iterative.xml create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/layer84_permx.geos create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/layer84_permy.geos create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/layer84_permz.geos create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/layer84_poro.geos create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/pres_pvdo.txt create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/visc_pvdo.txt create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/xlin.geos create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/ylin.geos create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/zlin.geos diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_Gravity/immiscibleTwoPhase_Gravity.xml b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_GravitySegregation_1d/immiscibleTwoPhase_GravitySegregation_1d.xml similarity index 100% rename from inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_Gravity/immiscibleTwoPhase_Gravity.xml rename to inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_GravitySegregation_1d/immiscibleTwoPhase_GravitySegregation_1d.xml diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_Gravity/initialPressure.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_GravitySegregation_1d/initialPressure.txt similarity index 100% rename from inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_Gravity/initialPressure.txt rename to inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_GravitySegregation_1d/initialPressure.txt diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_Gravity/initialSaturation1.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_GravitySegregation_1d/initialSaturation1.txt similarity index 100% rename from inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_Gravity/initialSaturation1.txt rename to inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_GravitySegregation_1d/initialSaturation1.txt diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_Gravity/initialSaturation2.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_GravitySegregation_1d/initialSaturation2.txt similarity index 100% rename from inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_Gravity/initialSaturation2.txt rename to inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_GravitySegregation_1d/initialSaturation2.txt diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_Gravity/x.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_GravitySegregation_1d/x.txt similarity index 100% rename from inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_Gravity/x.txt rename to inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_GravitySegregation_1d/x.txt diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_Gravity/y.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_GravitySegregation_1d/y.txt similarity index 100% rename from inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_Gravity/y.txt rename to inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_GravitySegregation_1d/y.txt diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_Gravity/z.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_GravitySegregation_1d/z.txt similarity index 100% rename from inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_Gravity/z.txt rename to inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_GravitySegregation_1d/z.txt diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/dens_pvdo.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/dens_pvdo.txt new file mode 100644 index 00000000000..363a10269a5 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/dens_pvdo.txt @@ -0,0 +1,3 @@ +761.90476190476190476190 +784.31372549019607843137 +792.07920792079207920792 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/immiscibleTwoPhase_SPE10_layer84_base_direct.xml b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/immiscibleTwoPhase_SPE10_layer84_base_direct.xml new file mode 100644 index 00000000000..54064522013 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/immiscibleTwoPhase_SPE10_layer84_base_direct.xml @@ -0,0 +1,238 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/immiscibleTwoPhase_SPE10_layer84_base_iterative.xml b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/immiscibleTwoPhase_SPE10_layer84_base_iterative.xml new file mode 100644 index 00000000000..13264fe80d0 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/immiscibleTwoPhase_SPE10_layer84_base_iterative.xml @@ -0,0 +1,238 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/immiscibleTwoPhase_SPE10_layer84_benchmark_direct.xml b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/immiscibleTwoPhase_SPE10_layer84_benchmark_direct.xml new file mode 100644 index 00000000000..35ab5d391b3 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/immiscibleTwoPhase_SPE10_layer84_benchmark_direct.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/immiscibleTwoPhase_SPE10_layer84_benchmark_iterative.xml b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/immiscibleTwoPhase_SPE10_layer84_benchmark_iterative.xml new file mode 100644 index 00000000000..d20765c07bb --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/immiscibleTwoPhase_SPE10_layer84_benchmark_iterative.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/layer84_permx.geos b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/layer84_permx.geos new file mode 100644 index 00000000000..d83867f1511 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/layer84_permx.geos @@ -0,0 +1,13200 @@ +0.064542 +0.034083 +0.033865 +12.584 +25.506 +49.557 +110.05 +3.1658 +1864.7 +554.89 +778.92 +166.98 +1152.9 +430.23 +940.06 +345.37 +229.37 +390.37 +744.79 +110.79 +189.92 +61.175 +45.341 +299.3 +268.93 +51.619 +25.666 +116.14 +0.10857 +0.30584 +0.11793 +0.097815 +0.18215 +0.13971 +0.091116 +0.046364 +0.10297 +0.079578 +0.013536 +0.03645 +0.10576 +0.45575 +0.19143 +0.081675 +521.47 +588.83 +425.18 +60.599 +71.636 +285.38 +361.31 +17.056 +47.555 +148.49 +65.429 +34.797 +111.85 +136.38 +98.327 +169.98 +0.11286 +0.10634 +0.081667 +0.052393 +32.541 +36.477 +166.46 +2237.7 +678.13 +492.44 +793.61 +285.87 +1633.4 +676.45 +371.46 +426.83 +379.78 +369.9 +288.81 +69.299 +67.002 +25.327 +39.998 +379.97 +257.87 +65.124 +28.595 +98.913 +0.28881 +0.33028 +0.25872 +0.1233 +0.048856 +0.22513 +0.37565 +0.026637 +0.059152 +0.034875 +0.01443 +0.019086 +0.11767 +0.099196 +0.07389 +0.034775 +432.54 +324 +52.078 +142.62 +195.34 +231.22 +246.73 +317.3 +61.988 +65.189 +258.83 +34.475 +138.53 +276.58 +166.55 +293.29 +0.065883 +0.097745 +0.20938 +0.79875 +0.49302 +0.23443 +44.765 +200.05 +608.83 +190.16 +566.79 +230.07 +998.9 +648.59 +145.2 +617.66 +574.48 +340.95 +139.57 +73.181 +85.964 +22.285 +47.058 +120.34 +235.96 +27.214 +24.529 +70.772 +0.63261 +0.18382 +0.19455 +0.12733 +0.086306 +0.15792 +0.23827 +0.38131 +0.15722 +0.24469 +0.043473 +0.12284 +0.25926 +0.087617 +0.036858 +0.055697 +246.6 +376.72 +87.035 +252.94 +338.94 +141.44 +308.2 +237.84 +47.03 +90.055 +141.26 +38.305 +423.1 +231.6 +144.91 +193.52 +0.19582 +0.029963 +0.16623 +0.18874 +0.63653 +0.13589 +0.46928 +0.069859 +84.093 +297.66 +709.97 +332.23 +1179.3 +960.02 +99.835 +679.55 +690.79 +230.29 +64.782 +74.962 +63.969 +29.326 +31.055 +62.858 +78.211 +49.509 +27.538 +52.3 +0.14683 +0.073425 +0.079791 +0.23118 +0.15686 +0.37766 +0.23192 +0.18254 +0.13246 +0.36985 +0.28115 +0.45961 +0.2039 +0.14442 +0.12089 +0.035193 +51.816 +279.09 +98.52 +165.48 +205.67 +84.122 +126.41 +144.61 +141.12 +84.454 +98.735 +29.543 +30.702 +32.005 +64.901 +190.82 +0.24328 +0.045128 +0.27136 +0.17964 +0.28686 +0.31372 +0.10344 +0.027707 +65.548 +192.02 +1056.6 +451.14 +568.55 +884.24 +143.95 +218.63 +354.26 +223.68 +182.13 +73.648 +12.494 +23.241 +24.469 +120.55 +87.03 +59.859 +63.365 +57.563 +205.47 +0.10258 +0.036084 +0.22701 +0.34276 +0.15466 +0.037823 +0.042638 +0.41338 +0.31336 +1.0557 +0.074098 +0.12464 +0.063393 +0.15806 +0.071952 +0.1078 +161.37 +108.25 +289.25 +122.91 +205.05 +483.29 +86.51 +38.502 +49.36 +34.694 +21.44 +222.37 +340.5 +35.465 +382.73 +0.17405 +0.24344 +0.21956 +0.11204 +0.50225 +0.40387 +0.13347 +44.621 +49.595 +205.14 +110.97 +231.59 +598.07 +241.89 +127.55 +257.68 +301.45 +264.14 +205.78 +945.86 +406.89 +33.532 +88.773 +139.35 +43.266 +31.504 +50.983 +70.095 +116.72 +0.012884 +0.021406 +0.11139 +0.13991 +0.23014 +0.083808 +0.14631 +0.4154 +0.39946 +0.58834 +0.10903 +0.023152 +0.062313 +0.44326 +0.042737 +0.11187 +0.20606 +833.41 +200.2 +185.46 +139.76 +433.92 +115.96 +43.992 +58.488 +38.38 +15.999 +142.26 +272.44 +125.73 +374.02 +0.36356 +0.23023 +0.34597 +0.57646 +0.69528 +0.18271 +12.786 +22.28 +72.075 +293.26 +69.144 +144.89 +185.07 +65.641 +227.53 +69.682 +112.23 +163.93 +110.52 +557.42 +414.41 +44.922 +90.015 +218.6 +32.666 +31.722 +28.023 +82.649 +82.841 +0.2781 +0.15826 +0.2424 +0.26436 +0.079702 +0.068927 +0.1803 +0.22496 +0.30583 +0.92788 +0.13457 +0.011549 +0.072593 +0.26906 +0.1108 +1005.4 +403.63 +357.54 +179.15 +227.94 +169.22 +248.56 +256.55 +135.76 +46.386 +87.288 +80.658 +268.25 +110.56 +70.52 +354.73 +0.17062 +0.19122 +1.4683 +0.28591 +1.1344 +0.61433 +14.97 +31.062 +70.954 +232.54 +179.12 +120.54 +133.6 +89.496 +52.812 +379.81 +200.82 +100.85 +75.243 +157.67 +347.75 +206.1 +229.32 +114.01 +20.654 +33.827 +40.613 +76.305 +22.376 +63.505 +0.11355 +0.14114 +0.011373 +0.057265 +0.20586 +0.21325 +0.055662 +0.093884 +0.14534 +0.048081 +0.041314 +0.046246 +0.03562 +760.16 +1217 +745.93 +795.84 +99.913 +204.06 +123.77 +253.1 +204.19 +152.04 +138.02 +84.878 +82.619 +104.82 +76.898 +59.541 +152.44 +0.29373 +0.13717 +0.29431 +4.3611 +0.32076 +0.83081 +27.533 +64.722 +31.243 +177.8 +211.94 +158.24 +69.265 +56.738 +307.65 +339.36 +257.26 +60.568 +76.742 +169.22 +444.62 +208.19 +372.92 +89.071 +34.606 +36.319 +27.375 +106.42 +24.527 +75.613 +2362.9 +0.072295 +0.033354 +0.018601 +0.089319 +0.086002 +0.066354 +0.17864 +0.32434 +0.066334 +0.061923 +0.1465 +0.20517 +459.33 +444.1 +699.99 +768.6 +99.921 +170.93 +233.83 +1389.3 +377.83 +235.73 +251.35 +104.14 +64.791 +76.809 +0.16251 +0.24275 +0.030701 +0.45119 +0.20232 +0.5466 +0.65022 +0.55413 +0.10716 +46.39 +83.23 +37.374 +213.88 +51.885 +22.977 +74.532 +168.72 +187.73 +234.98 +232.28 +30.974 +294.42 +566.89 +529.52 +245.32 +313.32 +257.05 +385.16 +157.47 +129.16 +135.72 +27.896 +78.059 +3242.2 +975.66 +0.072112 +0.029737 +0.06779 +0.035362 +0.083346 +0.22955 +0.071457 +0.12459 +0.11444 +3172.4 +278.98 +589.88 +584.53 +403.27 +750.9 +217.59 +194.54 +164.41 +467.93 +1360.8 +290.77 +253.07 +355.59 +196.4 +326.85 +0.14956 +0.11366 +0.15315 +0.37969 +0.23949 +0.10672 +0.079027 +0.080941 +0.064121 +72.658 +43.561 +50.816 +137.24 +25.553 +16.117 +53.033 +347.26 +201.64 +299.23 +176.54 +33.877 +462.13 +136.41 +112.91 +138.66 +221.94 +188.74 +803.49 +116.76 +912.63 +127.61 +125.75 +166.11 +101.56 +911.79 +186.47 +0.08453 +0.039313 +0.049767 +0.40395 +0.10691 +0.016847 +161.96 +577.41 +2099.7 +241.99 +319.12 +2261.6 +2442.1 +209.19 +146.51 +159.46 +348.49 +263.67 +462.89 +129.9 +107.08 +133.09 +711.3 +275.4 +0.055833 +0.14019 +0.06268 +0.20509 +0.2143 +0.25294 +0.52994 +0.079145 +0.090655 +47.828 +26.751 +31.94 +55.881 +172.71 +31.025 +83.53 +472.45 +473.52 +180.58 +68.023 +18.186 +513.8 +87.376 +62.507 +172.49 +268.2 +211.04 +371.53 +41.53 +79.049 +533.62 +218.18 +33.722 +149.07 +76.799 +505.42 +0.028038 +0.12757 +0.098478 +0.40759 +0.23775 +352.3 +361.97 +507.75 +1063 +463.21 +934.6 +1800.2 +2441.5 +161.96 +71.926 +129.75 +276.79 +752.58 +373.23 +55.897 +222.43 +267.63 +855 +547.59 +754.28 +0.12624 +0.056341 +0.091799 +0.18029 +0.54194 +0.17822 +0.24298 +0.22995 +115.58 +55.764 +51.966 +60.55 +83.883 +40.962 +111.47 +437.03 +625.37 +60.861 +110.38 +35.098 +344.29 +228.48 +232.04 +284.52 +453.57 +223.13 +454.08 +79.732 +78.156 +327.48 +269.76 +928.72 +373.5 +51.307 +107.01 +0.027685 +0.049666 +0.1022 +0.21973 +60.967 +291.13 +482.85 +889.98 +1986.5 +279.88 +2971.5 +1887.5 +1686.1 +177.06 +246 +239.78 +133.89 +475.95 +498.08 +73.064 +150.48 +197.38 +1038 +828.51 +0.054693 +0.027247 +0.042157 +0.034732 +0.01816 +0.1158 +0.22036 +0.023251 +0.041459 +224.57 +76.117 +70.432 +230.56 +57.266 +57.341 +263.94 +298.04 +535.68 +44.06 +238 +335.79 +115.85 +1013.3 +547.52 +490.85 +748.42 +196.51 +235.21 +38.992 +174.13 +614.47 +508.34 +1093.2 +207.76 +76.966 +2303.5 +6468.3 +3378 +3568.4 +232.79 +102.71 +154.52 +296.64 +666.62 +0.044901 +0.033646 +0.074568 +1040.8 +1456 +484.49 +372.73 +165.15 +117.14 +69.967 +328.01 +411.26 +271.49 +2909.1 +1338.5 +0.10492 +0.09618 +0.17501 +0.042574 +0.045451 +0.032037 +0.064184 +0.13178 +0.045783 +0.1872 +380.62 +112.71 +86.495 +250.1 +79.037 +90.322 +220.58 +328.97 +146.02 +33.509 +428.75 +129.38 +131.41 +141.74 +518.04 +652.16 +824.41 +224.94 +455.9 +903.34 +368.35 +741.47 +394.17 +825.35 +719.21 +126.73 +53.909 +1682.2 +3920.8 +5337.6 +7227.1 +63.056 +196.31 +207.31 +0.018731 +0.081244 +0.03119 +0.034039 +1053 +1256.4 +457.57 +714.14 +210.8 +436.48 +71.696 +183.29 +303.12 +691.12 +467.88 +0.043608 +0.057146 +0.34246 +0.13845 +0.050325 +0.10604 +0.022569 +0.10474 +0.17147 +0.26691 +0.66749 +375.88 +96.477 +186.03 +255.69 +93.254 +55.775 +109.36 +129.54 +117.51 +30.112 +702.12 +153.61 +217.21 +2400.3 +390.82 +528.63 +678.78 +169.76 +902.57 +786.16 +583.42 +1555.4 +273.07 +796.46 +692.55 +157.24 +64.409 +693.8 +1953.5 +4344.9 +4908.8 +6861.6 +115.13 +196.53 +0.010065 +0.005226 +0.015142 +0.044592 +841.66 +701.51 +569.97 +1404.1 +420 +945.03 +91.569 +372.7 +479.58 +867.86 +0.14671 +0.022754 +0.058072 +0.25578 +0.373 +0.12615 +0.10488 +0.040757 +0.038922 +0.1141 +1.5126 +5.2666 +0.50732 +1.732 +57.488 +162.49 +111.95 +109.48 +146.69 +203.31 +60.671 +24.116 +83.11 +271.01 +83.895 +1165.8 +506.66 +704.71 +537.11 +226.38 +486.78 +850.98 +792.5 +221.86 +97.752 +287.8 +506.4 +259.7 +63.291 +259.46 +281.67 +4594.3 +2977.5 +5929.5 +154.72 +0.18093 +0.023153 +0.013063 +0.062635 +1468.4 +93.999 +988.36 +1146.2 +1007.5 +631.03 +1563.5 +555.79 +373.58 +897.79 +510.13 +1.5394 +0.071805 +0.41543 +0.22775 +0.16103 +0.14905 +0.3836 +0.059474 +0.068608 +0.37691 +0.56713 +4.4797 +0.21818 +0.065353 +45.733 +83.197 +154.54 +98.953 +44.568 +100.51 +36.408 +38.667 +107.35 +26.764 +36.915 +691.38 +423.64 +503.46 +211.26 +398.14 +109.26 +933.74 +664.61 +245.23 +97.1 +911.37 +794.12 +234.75 +101.76 +94.315 +292.58 +825.85 +2257.3 +1809.7 +65.881 +1.2157 +0.20489 +0.041237 +0.055386 +0.22325 +252.36 +123.01 +3059.1 +383.73 +219.59 +460.94 +1039.4 +352.3 +127.91 +0.057797 +0.60867 +0.15544 +0.21043 +0.25787 +0.2688 +0.20647 +0.5459 +0.072486 +0.041144 +0.061576 +0.37612 +0.22198 +0.061339 +0.018407 +77.257 +137.34 +199.79 +93.143 +69.812 +97.414 +41.885 +30.648 +41.72 +51.445 +670.2 +421.82 +327.57 +761.36 +250.34 +271.42 +128.38 +230.9 +86.811 +177.7 +0.046207 +1417.1 +447.81 +359.22 +225.09 +85.249 +398.68 +1450.6 +1573.5 +3203.5 +2303.9 +0.085812 +0.12855 +0.058119 +0.058183 +82.827 +338.13 +24.439 +351.91 +600.56 +371.71 +288.02 +777.4 +126.96 +135.74 +748.38 +0.28827 +0.92401 +0.099892 +0.063414 +0.047237 +0.23694 +0.1953 +0.016815 +0.062956 +0.10603 +0.20299 +0.068023 +0.015586 +0.079782 +0.069472 +70.9 +168.8 +83.003 +66.23 +89.389 +39.068 +11.904 +33.453 +148.55 +689.3 +510.42 +255.16 +396.9 +233.01 +234.7 +148.23 +192.56 +132.09 +377.94 +20000 +641.09 +535.18 +422.13 +203.7 +103.14 +164.08 +384.23 +3595.2 +3326.6 +0.43644 +0.87682 +0.21329 +216.08 +67.867 +88.226 +332.5 +40.323 +75.919 +571.44 +681.47 +703.88 +751.92 +96.307 +55.034 +817.01 +857.88 +1.8641 +0.30399 +0.023181 +0.095362 +0.085263 +0.02839 +0.069068 +0.045199 +0.077594 +0.14852 +0.08044 +0.045626 +0.029042 +0.062378 +38.99 +97.05 +125.67 +129.75 +182.08 +45.691 +58.096 +471.37 +87.832 +407.89 +519.4 +270.96 +490.63 +379.78 +260.58 +235.88 +4558.9 +101.19 +220.15 +20000 +183.09 +491.78 +784.9 +192.65 +266.35 +321.63 +260.47 +3947.8 +0.15472 +0.1247 +0.086955 +0.15396 +17.211 +197.68 +92.417 +434.23 +30.135 +188.99 +381.47 +3151.1 +1147.3 +222.12 +171.38 +7.9534 +559.02 +608.7 +281.97 +0.22344 +0.082356 +0.052349 +0.04474 +0.006468 +0.085523 +0.055831 +0.16622 +0.071888 +0.051486 +0.010634 +0.10723 +94.868 +34.1 +112.63 +81.7 +125.74 +102.26 +30.577 +327.97 +341.43 +87.525 +262.53 +432.91 +77.231 +391.52 +312.13 +246.19 +3986.3 +3196.6 +391.99 +250 +217.76 +199.5 +1131.3 +322.69 +290.15 +257.5 +376.57 +0.32552 +0.20756 +0.41813 +0.46419 +0.42621 +10.378 +15.666 +43.303 +927.56 +735.71 +103.51 +149.84 +381.74 +2065.3 +108.7 +155.15 +74.238 +9.7458 +564.77 +739.74 +318.89 +254.18 +0.05016 +0.15938 +0.44953 +0.64601 +0.021304 +0.046599 +0.037551 +0.050755 +0.049153 +670.11 +313.38 +202.78 +25.986 +138.02 +74.498 +167.35 +896.58 +477.79 +617.6 +187.95 +76.598 +386.53 +705.47 +172.13 +444.19 +508.81 +1394.4 +2491.8 +140.81 +363.63 +1131.9 +402.83 +125.62 +989.79 +768.08 +217.83 +93.863 +0.073146 +0.1392 +0.066525 +0.064315 +0.086 +0.062137 +11.013 +11.121 +89.624 +505.35 +227.03 +59.997 +179.86 +623.13 +167.34 +145.28 +106.3 +183.74 +23.414 +353.03 +346.34 +118.33 +0.38988 +0.048508 +0.14228 +0.059671 +0.058192 +0.15036 +0.42229 +0.22523 +0.10655 +0.17156 +629.91 +505.61 +227.95 +55.159 +147.97 +85.203 +1598 +1243.7 +1036.3 +168.31 +141.9 +180.92 +582.24 +442.22 +261.19 +309.28 +5384.5 +0.29577 +148.73 +99.551 +213.17 +735.85 +767.04 +157.13 +49.371 +999.46 +467.36 +0.15842 +0.031487 +0.040931 +0.20878 +0.15259 +0.33171 +11.363 +8.2247 +6.9178 +208.51 +238.45 +246.52 +124.96 +57.279 +103.69 +133.34 +154.73 +198.42 +606.44 +49.994 +543.56 +310.61 +254.47 +0.094992 +0.086519 +0.12653 +0.068546 +0.09167 +0.047976 +0.080055 +0.18503 +0.065935 +436.44 +383.64 +177.41 +189.57 +89.964 +289.68 +975.21 +341 +109.23 +51.145 +165.32 +79.5 +220.37 +1144.4 +564.87 +6233.4 +326.03 +258.97 +80.484 +104.37 +70.665 +172.14 +607.39 +1315.4 +2035.7 +411.98 +953.81 +0.037991 +0.056282 +0.039962 +0.059559 +0.1805 +0.27062 +1.4387 +4.6608 +138.79 +113.75 +10.047 +15.914 +60.87 +56.757 +23.284 +144.9 +133.17 +242 +76.539 +366.93 +67.01 +439.08 +601.39 +292.76 +1679.2 +0.20646 +0.090226 +0.051762 +0.16651 +0.063797 +0.03858 +0.053665 +0.053837 +342.42 +357.26 +0.14388 +207.49 +364.89 +243.9 +677.55 +177.9 +172.02 +39.464 +144.03 +163.96 +106.44 +9344.4 +7339.1 +134.06 +283.62 +697.86 +107.66 +112.39 +175.22 +626.53 +0.13755 +992.8 +1401 +411.5 +847.72 +1832.8 +0.26055 +0.37582 +0.081309 +0.17563 +0.12407 +625.01 +1241.6 +80.451 +17.904 +18.647 +6.8496 +2.6433 +84.082 +46.953 +144.48 +145.76 +229.34 +112.21 +175.66 +133.41 +493.73 +777.01 +438.79 +2223.4 +0.24289 +0.090909 +0.054286 +0.035886 +0.042054 +0.017021 +0.036003 +0.033485 +0.056762 +714.37 +112.05 +302.28 +827.07 +292.39 +458.93 +363.44 +172.85 +108.84 +252.63 +234.15 +12024 +102.83 +134.89 +254.97 +507.3 +693.86 +234.78 +224.19 +0.21142 +0.15445 +0.069956 +494.82 +610.78 +622.52 +1029.1 +1772.1 +301.51 +0.18088 +0.12615 +0.083816 +332.2 +0.045379 +0.018357 +0.024315 +14.364 +14.716 +7.4866 +58.744 +77.545 +79.97 +223.5 +171.29 +236.06 +163.15 +255.84 +516.74 +0.011899 +717.16 +296.42 +2101.7 +733.89 +0.012212 +0.024235 +0.027301 +0.02557 +0.010744 +0.024276 +0.04748 +94.542 +80.874 +99.301 +307.32 +868.22 +682.78 +437.97 +482.38 +372.26 +307.69 +36.34 +155.75 +81.583 +127.78 +106.65 +101.24 +424.24 +433.57 +202.87 +0.13553 +0.020352 +0.054023 +0.037423 +0.023142 +372.85 +519 +526.58 +834.26 +298.72 +90.51 +597.77 +1087.5 +0.026311 +0.032221 +0.067858 +0.037855 +0.067948 +0.059987 +104.08 +95.129 +147.7 +143.52 +323.02 +148.59 +487.15 +596.4 +863.81 +937.84 +355.45 +198.74 +179.55 +2036.5 +0.017805 +0.027843 +0.037913 +0.039088 +0.02631 +0.022821 +235.55 +117.99 +43.88 +90.053 +129.31 +249.62 +1078.8 +1344 +496.9 +430.09 +374.78 +29.099 +94.298 +143.63 +162.17 +142.08 +71.208 +92.798 +222.48 +2987.3 +0.04223 +0.023116 +0.16845 +0.029541 +0.043063 +988.46 +276.95 +668.82 +306.4 +721.62 +381.79 +817.32 +2100 +7.8004 +0.029002 +0.063596 +0.032126 +164.94 +166.56 +162.23 +144.35 +91.474 +103.39 +87.628 +244.26 +319.17 +553.78 +654.83 +461.8 +511.82 +208.13 +340.31 +392 +786.86 +0.036235 +0.080712 +0.089838 +0.16975 +0.051504 +227.24 +147.28 +82.719 +23.627 +46.817 +132.27 +188.31 +860.68 +575.89 +288.7 +763.1 +73.746 +116.37 +96.039 +164.91 +73.634 +144.24 +70.428 +70.998 +3815.2 +2041.4 +0.13388 +0.13954 +0.13916 +0.023716 +0.019203 +921.26 +287.58 +790.68 +1085 +998.12 +371.65 +545.76 +1367.7 +11.845 +0.011215 +5747.8 +10258 +841.05 +117.53 +153.13 +169.41 +120.66 +144.86 +285.1 +289.18 +130.82 +217.66 +205.8 +288.47 +432.23 +181.83 +251.83 +1077.2 +736.78 +0.32814 +0.064353 +0.18512 +0.041463 +120.27 +190.09 +106.56 +93.094 +25.747 +79.519 +192.22 +230.07 +1161.7 +550.42 +341.85 +177.41 +134.28 +177.31 +105.5 +164.13 +120.76 +59.415 +40.681 +45.245 +2568.5 +3029.3 +4473 +8542.1 +0.022298 +0.035673 +0.035346 +977.49 +394.62 +913.86 +646.09 +2371.4 +297.66 +279.83 +977.18 +124.68 +0.031991 +4585.1 +9669.5 +970.54 +171.93 +84.455 +211.19 +1630 +2793 +465.26 +144.91 +148.96 +147.98 +133.03 +416.29 +324.25 +118.46 +236.1 +1085.5 +790.89 +0.3891 +0.13582 +0.083521 +0.044139 +100.48 +89.16 +120.24 +87.716 +73.05 +68.88 +144.98 +387.36 +938.04 +528.41 +1160 +458.76 +175.31 +148.55 +59.324 +170.47 +178.92 +48.419 +70.68 +4090.7 +5340.3 +3119.6 +6201.5 +8242.8 +16749 +12469 +102.8 +660.59 +217.71 +879.71 +649.42 +2004.5 +212.34 +288.94 +225.95 +308.23 +562.39 +5784.4 +5212.6 +351 +125.83 +75.04 +476.05 +0.054004 +619.38 +227.82 +191.05 +71.829 +204.96 +161.22 +178.01 +193.32 +163.02 +433.27 +1454.6 +754.13 +271.06 +0.019848 +0.11036 +0.047296 +106.88 +95.278 +95.915 +111.79 +50.32 +153.07 +200.04 +365.17 +1101.2 +729.67 +1837.1 +0.02878 +195.7 +202.86 +72.614 +212.57 +189.85 +51.696 +176.23 +150.16 +6093.7 +3746.3 +4104.9 +18194 +33.859 +83.221 +62.64 +272.86 +306.46 +910.8 +624.76 +1693.9 +175.95 +291.47 +156.22 +514.46 +696.38 +345.06 +4924.7 +730.5 +211.28 +210.53 +895.53 +0.10021 +18.802 +183.56 +236.6 +65.828 +161.85 +79.685 +318.64 +453.92 +841.64 +805.6 +1730.2 +751.39 +190.02 +0.048484 +0.050683 +0.038711 +244.93 +180.15 +90.256 +106.18 +51.704 +591.79 +180.03 +479.85 +496.25 +1132.1 +1525 +46.547 +156.02 +224.87 +129.04 +391.41 +260.57 +53.318 +82.291 +19.442 +66.122 +4506.7 +271.49 +105.16 +60.001 +155.7 +91.994 +244.82 +966.31 +514.52 +338.86 +1287.5 +104.38 +271.78 +281.53 +894.33 +757.46 +334.09 +5967 +1082.9 +256.95 +157.1 +1930.3 +0.16706 +0.23357 +20.546 +135.89 +57.231 +71.034 +63.959 +268.83 +538.06 +364.27 +1327.3 +577.67 +453.41 +471.46 +0.032577 +0.096693 +0.030402 +0.094 +0.074792 +78.624 +65.998 +39.28 +306.65 +344.83 +510.79 +772.37 +694.05 +0.03337 +69.284 +270.64 +290.06 +142.75 +261.81 +144.63 +35.737 +83.141 +27.761 +1207.6 +538.28 +198.34 +222.84 +161.79 +336.02 +119.24 +226.28 +747.55 +1313.5 +339.85 +831.74 +102.72 +0.18271 +0.088591 +369.18 +764.11 +302.49 +30.472 +2402.1 +432.65 +316.17 +2418.3 +0.35435 +33.611 +32.474 +98.578 +117.95 +91.226 +102.23 +233.26 +279.37 +279.32 +280.64 +370.97 +731.11 +595.38 +889.63 +0.36594 +0.019786 +0.10423 +0.040005 +32.878 +117.14 +73.209 +232.31 +252.47 +651 +183.84 +0.10801 +27.506 +188.62 +509.14 +266.7 +168.45 +172.56 +109.56 +55.617 +252.76 +607.03 +865.22 +472.78 +268.46 +632.95 +328.74 +331.95 +83.728 +261.86 +661.03 +1607.8 +329.39 +0.39644 +0.43631 +0.39884 +0.37352 +44.636 +260.62 +246.54 +541.03 +128.29 +3362.3 +602.47 +2247.1 +2084.1 +19.81 +32.902 +110.82 +289.74 +271.99 +370.5 +156.57 +148.43 +271.8 +246.04 +308.34 +513.93 +437.25 +722.29 +0.055349 +0.064215 +0.060211 +35.199 +43.349 +82.321 +116.22 +259.09 +300.14 +914.46 +0.051738 +0.04402 +845.58 +114.58 +867.06 +171.51 +100.07 +45.13 +49.633 +600.8 +400.96 +1189.2 +438.15 +333.41 +334.24 +506.34 +1009.4 +329.67 +193.95 +650.63 +20000 +9786.2 +14168 +0.38846 +0.26615 +0.15357 +0.16432 +0.22051 +284.96 +503.52 +226.77 +172.01 +21.474 +285.29 +2905.1 +2362.1 +1942.4 +83.699 +73.349 +222.87 +209.62 +370.26 +269.28 +1046.7 +189.19 +151.17 +400.13 +284.85 +1056.1 +353.95 +0.055006 +0.037158 +0.058991 +53.239 +74.838 +61.747 +135.69 +136.02 +768.77 +653.57 +1313.4 +1847.1 +958.28 +44.354 +273.64 +80.772 +66.911 +66.443 +15.835 +310.34 +831.23 +874.79 +260.78 +201.9 +514.62 +357.33 +921.11 +20000 +20000 +20000 +20000 +333.48 +401.43 +404.68 +255.02 +0.080324 +0.13234 +0.13573 +0.068013 +140.55 +115.24 +186.85 +25.299 +20.742 +4288.7 +2670.6 +1431.7 +2539.6 +1994.2 +163.74 +126.74 +399.95 +995.58 +896.65 +446.85 +108.79 +239.23 +284.56 +511.5 +543.92 +0.45725 +0.092232 +230.78 +142.68 +65.559 +185.2 +158.98 +306.39 +1413.1 +0.07376 +0.090521 +0.16032 +1730.2 +37.544 +178.01 +141.25 +115.97 +51.94 +15.798 +542.98 +640.16 +1060 +245.69 +0.32582 +0.32508 +0.15372 +20000 +13832 +16616 +20000 +20000 +17596 +1783.3 +563.1 +180.11 +696.35 +0.059353 +159.76 +75.456 +118.69 +258.25 +1071 +129.54 +100.61 +9.3211 +1943.4 +2179.4 +2620 +1787.8 +154.85 +104.89 +45.203 +277.6 +885.44 +383.8 +79.739 +94.45 +904.37 +651.6 +0.067856 +1.7106 +0.041091 +170.08 +53.609 +83.895 +228.6 +157 +445.71 +1656.3 +215.4 +214.53 +323.24 +263.59 +722.11 +1039.8 +128.05 +172.71 +35.944 +11.673 +384.68 +0.054976 +0.056484 +0.54125 +0.3867 +0.40171 +0.29226 +20000 +20000 +8921.1 +20000 +20000 +12660 +6466.7 +1395.4 +147.94 +356.31 +0.05831 +0.24296 +86.243 +153.72 +331.3 +674.56 +551.37 +132.56 +13.224 +9.2287 +1452 +1480.5 +1856.3 +2736.7 +924.97 +42.436 +61.555 +114.05 +89.524 +156.76 +59.733 +584.63 +384.05 +0.092109 +0.22831 +0.29556 +109.33 +107.95 +123.46 +112.61 +120.59 +422.5 +2442.1 +3099.1 +307.89 +538.93 +460.33 +408.81 +2071.4 +4612.8 +225.9 +28.076 +17.87 +11.689 +9.242 +0.25543 +0.26083 +0.18224 +0.56139 +15142 +20000 +20000 +10371 +20000 +20000 +49.477 +36.952 +1063.7 +202.47 +196.9 +0.21012 +0.097823 +64.417 +174.78 +533.15 +413.96 +11.479 +68.185 +43.638 +13.485 +10.291 +1656.3 +1165.1 +2048.9 +102.33 +68.549 +71.977 +238.51 +103.31 +101.99 +48.875 +43.378 +0.13187 +0.046404 +0.16419 +0.64175 +0.29613 +49.225 +195.35 +288.27 +177.93 +207.91 +1662.8 +2651.5 +219.76 +498.8 +594.19 +527.32 +2374.4 +3434.4 +262.9 +49.239 +15.312 +9.3444 +5.436 +0.076231 +0.017327 +0.36808 +20000 +13640 +20000 +20000 +9387.2 +20000 +64.693 +36.159 +23.757 +771.4 +0.081627 +0.033605 +0.031971 +89.904 +79.553 +127.75 +395.49 +11.296 +43.573 +91.118 +47.1 +77.163 +17.461 +63.621 +180.78 +2007.6 +181.5 +145.37 +35.083 +170.21 +95.539 +60.156 +41.245 +23.391 +69.86 +0.307 +0.077237 +0.53307 +0.58566 +0.23657 +77.484 +112.25 +930.2 +143.83 +1019.6 +2324.4 +362.98 +243.42 +419.78 +1374 +5187.8 +3194.1 +398.6 +47.299 +9.0425 +13.18 +4.9446 +0.11462 +0.07608 +0.11186 +20000 +20000 +20000 +13096 +4292.8 +20000 +20.069 +25.817 +46.058 +38.489 +0.047873 +0.038792 +0.20183 +0.60446 +0.067169 +0.18499 +0.084948 +12.808 +60.674 +79.399 +53.937 +20.307 +20.734 +92.872 +180.4 +980.75 +299.44 +113.78 +25.021 +41.784 +65.546 +64.539 +55.268 +32.824 +59.059 +75.303 +0.20485 +0.30454 +0.80804 +0.30306 +0.21426 +272.83 +488.85 +639.85 +1251 +1381.8 +756.77 +224.57 +542.77 +2310.6 +4436 +251.9 +57.621 +0.12822 +22.411 +4.2519 +6.105 +34.843 +6.9776 +0.60394 +20000 +19465 +17455 +4239.9 +4172.6 +16588 +65.404 +32.694 +65.236 +78.405 +0.036713 +0.19119 +0.31752 +0.56851 +0.039968 +0.029245 +30.799 +26.298 +227.98 +129.25 +61.616 +26.855 +33.661 +93.855 +116.68 +700.72 +213.94 +126.5 +25.579 +84.178 +49.549 +8.5375 +28.304 +26.286 +106.17 +45.605 +0.049351 +0.17173 +0.69811 +0.052192 +0.35938 +243.35 +315.11 +1604.8 +3327.6 +1522.5 +3306.4 +687.62 +412.38 +1979.8 +571.65 +891.01 +95.9 +779.36 +871.37 +3.5137 +9.9101 +32.84 +15.585 +25.363 +20000 +8196.4 +8226.6 +3601.3 +7732.2 +5508.6 +5874.1 +23.066 +51.827 +60.333 +154.1 +0.71506 +0.056885 +0.11326 +0.015941 +197.96 +62.482 +23.728 +213.73 +244.99 +26.328 +9.1281 +45.411 +120.23 +96.569 +907.68 +540.16 +68.777 +94.686 +65.724 +46.961 +12.289 +27.698 +29.001 +108.36 +49.029 +47.646 +0.27776 +0.82964 +0.06854 +99.124 +77.718 +140.85 +1004.8 +7960.1 +2334.2 +4649.5 +1402.8 +1298.7 +1638.8 +0.072125 +688.5 +2079.8 +584.88 +3649 +4.3504 +10.351 +43.181 +21.816 +11.112 +19465 +9088.5 +8617.2 +3232.9 +3562.4 +2620.5 +2983.7 +0.10192 +0.050717 +0.11496 +30.927 +31.204 +77.521 +0.055553 +471.38 +179.76 +100.76 +47.416 +415.41 +29.07 +19.549 +12.258 +52.935 +81.248 +104 +1043.8 +314.65 +138.76 +253.09 +101.64 +56.527 +9.4114 +12.099 +86.919 +145.69 +84.334 +59.532 +3.5592 +1.4952 +0.20445 +126.68 +112.03 +119.11 +351.73 +1289.2 +1421.1 +1711.5 +2364.9 +2012.4 +2515.3 +1119.9 +0.028167 +1173.3 +1219.5 +3030.7 +6.4432 +24.535 +40.614 +20.341 +10.027 +33.453 +5069.9 +4820.1 +4278.2 +5420.9 +1473.5 +0.057922 +0.22536 +0.10497 +0.16221 +0.10651 +0.021999 +433.08 +700.8 +856.04 +361.87 +243.95 +115.59 +55.019 +29.417 +9.5029 +9.9344 +45.165 +166.51 +46.815 +879.39 +193.78 +128.07 +179.34 +108.69 +135.75 +5.5524 +20.318 +49.264 +85.334 +165.48 +63.665 +0.84262 +0.59375 +0.30898 +0.042635 +72.153 +204.03 +130.92 +637.33 +230.95 +2356.6 +1382.4 +1872.7 +1943.6 +20.261 +705.67 +873.58 +1404.3 +15.366 +2.9473 +60.206 +45.805 +26.319 +10.562 +19.043 +29.694 +2600.1 +2673.8 +0.081876 +0.043923 +0.2819 +0.11478 +0.028511 +0.084036 +2.7731 +134.4 +185.52 +112.87 +510.91 +520.47 +345.36 +0.063346 +73.226 +38.148 +9.8193 +11.886 +38.157 +1353.6 +1987.7 +272.93 +203.1 +116.25 +136.02 +105.43 +155.47 +5.4723 +18.547 +32.067 +182.26 +90.351 +109.49 +0.81705 +0.34805 +0.038671 +0.062894 +128.42 +215.59 +178.89 +915.24 +193.08 +886.74 +2050.6 +1852.2 +852.21 +163.03 +1351.8 +553.68 +32.529 +15.394 +7.4316 +33.642 +26.94 +47.707 +16.751 +21.442 +22.55 +1174.5 +2916.1 +0.055861 +0.021274 +0.035199 +0.12111 +0.030879 +0.065266 +7.5117 +74.467 +177.32 +281.32 +281.42 +577.49 +0.050091 +0.18737 +0.1568 +28.529 +27.63 +2517 +738.1 +933.11 +871.79 +320.2 +157.03 +134.77 +168.69 +435.01 +652.92 +1859.8 +925.77 +1486.1 +1661.3 +4411.9 +46.269 +0.20478 +0.39581 +0.14735 +0.025938 +0.007892 +169.87 +198.28 +784.71 +2717.8 +1377.4 +3238.6 +5057.7 +695.24 +195.7 +1475 +1.9986 +13.711 +16.673 +35.938 +15.221 +20.127 +65.248 +20.669 +39.491 +51.869 +1473.4 +0.024469 +0.049945 +0.47797 +0.054648 +0.032764 +0.081617 +0.012342 +10.976 +113.37 +468.65 +442.29 +271.33 +1267.8 +0.02819 +0.053603 +0.054862 +43.035 +350.07 +1881 +1500.1 +950.93 +515.64 +479.51 +1144 +1023 +592.2 +329.2 +947.42 +973.82 +1447.6 +2677.9 +4213.7 +1444.8 +11079 +0.030241 +0.069073 +0.036347 +0.03097 +0.058345 +0.066494 +175.42 +3026.1 +1156.2 +2183 +2936.2 +2181.8 +832.18 +153.02 +706.54 +3.2145 +9.2865 +11.159 +17.896 +17.044 +23.973 +85.297 +34.483 +88.593 +39.678 +0.21368 +0.032631 +0.050632 +1.04 +1.1297 +0.059103 +0.077958 +0.11299 +23.192 +35.882 +438.07 +225.29 +411.25 +791.82 +0.039732 +0.069966 +0.071924 +247.34 +634.64 +2155.8 +872.2 +861.18 +112.31 +98.951 +431.1 +1775.3 +1553 +694.85 +1883 +1581.8 +910.39 +2078.4 +2836.2 +3505.7 +553.37 +0.068438 +0.0474 +0.081545 +0.077128 +0.14198 +0.09065 +0.15977 +2837.4 +1414.8 +1445.8 +6372.8 +4334.1 +1119 +15.122 +11.556 +2.4852 +20.439 +21.996 +28.635 +27.434 +24.46 +138.18 +62.951 +85.102 +143.21 +0.058604 +0.022878 +0.019812 +0.19787 +0.48935 +0.030584 +0.022982 +0.050755 +21.166 +40.382 +159.58 +195.45 +539.41 +193.07 +32.902 +18.827 +73.82 +257.64 +336.34 +2065.9 +58.382 +27.374 +91.346 +178.89 +738.15 +832.97 +2162.5 +234.65 +2058.4 +762.53 +1245 +544.75 +647.57 +285.73 +423.48 +0.13564 +0.15352 +0.23669 +0.21923 +0.040201 +0.052 +0.15072 +51.245 +1021.1 +2010.3 +3525.3 +6405.1 +1013.6 +14.065 +10.346 +3.1605 +15.167 +13.149 +25.728 +22.907 +35.685 +147.94 +23.242 +6649.4 +0.090554 +0.011954 +0.023624 +0.071026 +0.049531 +0.045962 +0.11707 +0.044904 +0.003453 +22.756 +77.47 +204.08 +127.37 +401.03 +291.2 +0.45181 +13.075 +151.26 +97.186 +47.583 +124.12 +75.046 +41.142 +91.46 +182.45 +976.96 +672.16 +687.45 +446.96 +717.36 +517.9 +938.71 +636.23 +1017.9 +515.14 +28.852 +0.21398 +0.24414 +0.17823 +0.55816 +0.085047 +0.31459 +0.09849 +0.079809 +54.552 +3577.8 +2515.6 +1908.1 +1342.8 +8.5413 +5.534 +4.4049 +11.797 +17.816 +20.836 +49.496 +43.551 +101.72 +35.164 +20.077 +0.16516 +0.017769 +0.080451 +0.094329 +0.030378 +0.063156 +0.013578 +0.022231 +0.013782 +0.015439 +127.72 +177.31 +158.85 +541.11 +667.76 +21.918 +117.12 +94.865 +93.768 +28.75 +94.018 +187.67 +111.14 +267.7 +364.4 +1178.8 +1002 +356.12 +982.39 +224.03 +983.79 +154.17 +186.08 +286.98 +88.52 +49.485 +0.17155 +0.021736 +0.29292 +0.12531 +0.42716 +0.91892 +0.20216 +0.38024 +0.52909 +410.89 +1841.5 +1972.3 +27.504 +14.306 +4.465 +11.739 +23.305 +23.479 +17.397 +139.09 +68.664 +82.785 +20.509 +20000 +0.02774 +0.013818 +0.071988 +0.039631 +0.054121 +0.059862 +0.020456 +0.021124 +0.059129 +0.09583 +99.545 +206.83 +121.91 +60.056 +20.178 +63.626 +81.151 +77.169 +63.101 +30.57 +69.759 +92.996 +134.47 +191.73 +170.07 +85.207 +967.41 +10.064 +465.78 +856.99 +543.12 +128.59 +104.4 +509.09 +142.32 +30.173 +0.018056 +0.069506 +0.21218 +0.25674 +0.29171 +0.041781 +0.082685 +0.12274 +0.28577 +514.54 +1315.1 +1134.4 +362.18 +36.529 +5.7158 +13.332 +22.623 +42.637 +27.724 +269 +60.291 +139.61 +20000 +13.809 +0.095444 +0.022126 +0.028104 +0.077474 +0.1055 +0.10579 +0.055851 +0.015427 +0.038735 +0.31868 +0.31549 +323.86 +16.54 +63.47 +33.31 +75.162 +30.931 +49.124 +104.16 +28.062 +64.962 +122.33 +1827.4 +111.14 +125.46 +175.3 +306.12 +622.04 +332.1 +756.65 +332.29 +99.591 +97.807 +617.16 +237.91 +0.075459 +0.09817 +0.036888 +0.050964 +0.079193 +0.13119 +0.13242 +0.14494 +0.031957 +0.17187 +589.53 +1208.2 +631.15 +655.41 +28.047 +1.964 +8.8037 +9.9004 +54.197 +108.86 +292.79 +127.63 +80.943 +20000 +23.485 +0.29382 +0.29789 +0.19878 +0.33962 +0.068099 +0.079467 +0.007288 +0.037506 +0.28082 +0.24958 +0.5342 +138.92 +43.91 +80.864 +75.525 +33.456 +43.745 +35.243 +68.509 +242.97 +111.28 +665.75 +1173.1 +293.92 +63.573 +117.11 +65.458 +437.87 +2401.5 +322.46 +248.79 +0.22628 +0.31325 +0.029867 +0.055075 +0.33352 +0.10808 +0.097961 +0.050965 +0.097559 +0.26001 +0.10609 +0.22272 +0.19604 +0.4478 +0.04884 +2688.5 +517.31 +1947.1 +2998.4 +3050.5 +19.024 +12.228 +36.285 +111.83 +933.51 +384.9 +9.5006 +6.9376 +32.749 +0.14588 +0.63414 +0.23036 +0.19989 +0.096949 +0.13617 +0.17872 +0.22419 +0.49506 +0.1051 +0.23654 +84.427 +69.478 +44.515 +66.773 +22.462 +24.596 +25.031 +51.575 +86.672 +89.458 +274.77 +1748.2 +347.16 +86.336 +160.91 +340.79 +905.96 +918.58 +895.08 +642.69 +0.61904 +0.26566 +0.022074 +0.009777 +0.038808 +0.046555 +0.049495 +0.072805 +0.039843 +412.94 +526.09 +127.76 +681.57 +1018.9 +2207.2 +3223 +460.75 +1377.1 +2722.3 +1138.6 +646.42 +8.875 +19.774 +160 +1286.4 +791 +533.6 +6.5705 +0.093492 +0.22165 +0.15121 +0.10654 +0.031967 +0.096837 +0.18621 +0.33583 +0.58797 +0.61404 +951.81 +750.49 +104.87 +48.109 +32.955 +53.962 +46.786 +15.958 +44.103 +1.6119 +3.2856 +109.51 +557.3 +439.74 +346.32 +119.83 +730.12 +422.69 +34.31 +547.07 +961.38 +1593.4 +657.75 +581.54 +0.086168 +0.016832 +0.14373 +0.036174 +0.12091 +718.86 +371.35 +523.68 +454.24 +395.61 +136.23 +74.243 +199.85 +2667 +339.19 +987.6 +1520.3 +1379.8 +699.36 +137.48 +65.923 +121.29 +1393 +530.65 +475.79 +263.41 +48.472 +0.14855 +0.070753 +0.16731 +0.46154 +0.46442 +0.60423 +0.70573 +0.62273 +0.59138 +2110.8 +644.45 +96.967 +24.153 +46.224 +80.647 +100.5 +22.023 +98.255 +2.7744 +3.3778 +1.4647 +407.64 +477.95 +109.45 +72.38 +0.18236 +704.03 +34.932 +45.493 +70.09 +1557.5 +1527.5 +945.92 +353.64 +0.009963 +0.078112 +0.015346 +1543.1 +814.47 +205.55 +734.18 +586.54 +0.22841 +195.42 +25.252 +4308.7 +2982.5 +381.27 +911.22 +1223.6 +1845.3 +804.02 +256.27 +114.24 +449 +790.84 +371.47 +358.03 +72.74 +111.62 +114.86 +0.092551 +0.33198 +0.24754 +2.024 +0.25662 +0.45082 +0.73555 +3636.6 +1332.3 +736.46 +38.128 +14.932 +75.837 +145.37 +49.5 +30.549 +106.6 +4.1381 +3.8719 +4.404 +55.712 +140.15 +113.51 +110.97 +275.25 +53.031 +27.742 +28.972 +791.02 +1455.2 +803.03 +850 +187.82 +107.59 +0.027439 +406.67 +1281.1 +704.42 +392.19 +472.2 +0.36087 +0.13702 +108.82 +48.818 +2490.1 +1403.5 +598.74 +1206.4 +703.75 +2806.5 +904.82 +339.44 +266.8 +644.84 +1400.6 +213.52 +141.4 +64.925 +59.615 +218.05 +143.68 +156.46 +0.48526 +0.10011 +0.11582 +0.73423 +1.2026 +1077.8 +2833.8 +16.095 +53.049 +132.48 +81.803 +69.067 +23.986 +49.768 +9.1437 +5.7868 +5.7691 +4.7154 +25.75 +67.965 +96.853 +242.67 +299.44 +51.551 +870.16 +1561.1 +542.65 +1431.2 +1150.8 +573.67 +195.28 +120.62 +0.023145 +870.83 +1111.1 +1623.7 +689.16 +0.3522 +0.27709 +0.1833 +84.574 +9416.9 +1964.3 +1223.8 +985.14 +1189.1 +463.23 +2388.6 +339.1 +599.4 +42.319 +24.308 +1690.2 +454.07 +242.87 +92.49 +73.505 +260.17 +109.93 +87.11 +108.57 +0.25691 +0.10643 +0.5489 +0.29398 +1.0334 +0.76915 +23.035 +50.295 +112.1 +42.311 +58.278 +32.938 +56.575 +20.429 +17.221 +4.8275 +3.405 +26.037 +109.89 +262.45 +308.71 +460.05 +424.02 +759.79 +1671.8 +336.06 +494.13 +717.63 +681.86 +289.17 +190.57 +0.18026 +711.92 +1083.2 +1827.5 +1171.1 +524.14 +0.061159 +0.031658 +605.27 +3347.5 +1701.1 +844.35 +456.99 +252.33 +316.51 +1033.5 +289.16 +70.727 +135.95 +582.36 +3156 +436.38 +248.56 +434.39 +52.032 +252.51 +129.67 +64.451 +71.064 +43.197 +0.029187 +0.072202 +0.38776 +2.4376 +181.32 +26.303 +42.276 +129.77 +32.753 +29.461 +99.841 +57.437 +28.765 +16.319 +8.3125 +7.3448 +23.654 +0.20924 +341.65 +422.03 +888.55 +534.11 +0.052916 +2180.4 +554.26 +218.29 +663.52 +1142.7 +817.44 +181.83 +0.089715 +0.032828 +947.58 +770.61 +1104.5 +1372.5 +678.25 +0.03667 +2659.3 +4856.2 +108.41 +123.03 +385.33 +379.59 +289.76 +250.33 +44.122 +260.79 +406.53 +1078.2 +3163.8 +273.69 +143.51 +168.7 +161.71 +171.2 +83.715 +82.244 +82.581 +57.142 +84.223 +0.058064 +0.018525 +0.39208 +0.15717 +16.971 +26.239 +52.178 +14.793 +118.26 +87.222 +61.228 +19.653 +30.895 +16.039 +13.371 +0.076717 +0.042508 +0.14078 +368.6 +666.25 +390.75 +501.48 +1717.7 +227.22 +241.15 +1341.2 +2700.1 +1806.7 +0.19326 +0.62515 +0.083615 +0.068975 +1131.9 +1615.2 +1545.7 +2075.8 +2324 +0.1476 +6878.3 +90.707 +312.39 +208.75 +242.32 +233.34 +151.02 +500.75 +388.44 +272.79 +1254.3 +4917.3 +98.984 +180.57 +198.4 +57.886 +259.46 +261.01 +67.35 +39.523 +42.377 +68.401 +157.25 +0.01787 +0.093927 +180.75 +30.16 +22.477 +30.127 +17.203 +136.04 +33.182 +39.505 +30.61 +43.289 +28.315 +12.101 +0.051425 +0.11961 +0.062837 +404.75 +513.94 +507.17 +864.34 +545.76 +211.6 +321.55 +1383.1 +0.083571 +0.14291 +0.054787 +0.060374 +0.078012 +0.13783 +0.18706 +0.033564 +1573.2 +1813.8 +1907 +165.69 +81.013 +34.524 +163.51 +116.98 +94.782 +221.14 +1203.7 +794.01 +199.88 +328.06 +84.876 +134.85 +307.53 +117.17 +91.555 +149.31 +160.97 +256.08 +534.92 +40.635 +52.465 +52.969 +97.493 +0.016214 +0.036701 +234.14 +24.63 +58.414 +40.832 +18.311 +128.47 +33.194 +52.25 +12.694 +16.668 +32.631 +0.067626 +0.070366 +0.044752 +0.034006 +0.027681 +658.06 +758.61 +390 +426.88 +510.17 +464.74 +0.13617 +0.061527 +0.087851 +0.020834 +0.045807 +0.4487 +0.084579 +0.11244 +0.15476 +0.15494 +419.6 +284.29 +119.32 +93.848 +84.025 +223.19 +177.65 +6307.8 +507.65 +3118.7 +911.39 +391.22 +679.23 +100.11 +126.79 +283.41 +173.7 +113.68 +225.72 +131.52 +225.97 +817.71 +348.18 +372.26 +57.65 +90.304 +20.171 +516.09 +247.33 +63.356 +74.041 +24.325 +8.2242 +58.143 +22.833 +78.461 +18.696 +40.656 +28.866 +93.915 +0.011003 +0.073427 +4526 +10336 +494.75 +304.54 +1025 +237.63 +0.002272 +0.005741 +0.060402 +0.14137 +0.20482 +0.10709 +0.083907 +0.0853 +0.10609 +0.037686 +0.067858 +318.77 +273.43 +400.58 +150.08 +411.98 +51.441 +409.36 +565.16 +1434.6 +299.26 +2137.7 +734.81 +324.33 +967.01 +102.8 +120.28 +180.99 +0.086837 +0.033348 +0.008534 +96.816 +193.99 +313.71 +956.59 +718.23 +850.96 +178.73 +0.1603 +910.03 +183.92 +98.902 +80.227 +24.142 +0.020188 +23.907 +14.608 +28.496 +29.781 +22.497 +77.264 +159.32 +1591.7 +2224.3 +2747.5 +7564.6 +412.89 +493.36 +502.46 +0.012131 +0.008558 +0.026392 +0.085925 +0.1077 +0.071627 +0.094142 +0.046302 +0.048062 +0.034325 +0.21603 +300.71 +177.25 +211.43 +427.51 +146.06 +442.42 +975.6 +335.97 +967.08 +2985.5 +60.42 +54.068 +704.03 +0.02306 +1035.3 +176.47 +127.3 +0.019727 +0.29127 +0.068753 +0.027058 +2487.6 +104.35 +292.43 +1463 +259.57 +170.55 +0.15116 +492.86 +539.76 +457.75 +102.31 +55.297 +38.528 +6.612 +15.844 +7.7647 +14.473 +10.46 +17.294 +8942.5 +4122.4 +594.54 +802.4 +3440.1 +146.86 +126.7 +511.74 +601.7 +0.057692 +0.012538 +0.01099 +0.038868 +0.044684 +0.13979 +0.030668 +0.21989 +0.13407 +0.11574 +0.2496 +199.53 +114.29 +274.94 +33.134 +479.09 +450.39 +982.35 +304.81 +88.049 +209.88 +55.653 +31.25 +113.94 +445.04 +946.55 +151.36 +174.95 +0.049855 +0.13605 +226.8 +34.862 +738.82 +50.615 +1907.3 +996.84 +465.19 +85.041 +276.28 +181.44 +655.15 +919.45 +109.43 +37.833 +27.835 +6.7402 +15.373 +8.2221 +7.6279 +1380.1 +533.43 +194.9 +5635.1 +274.6 +235.42 +62.942 +78.698 +69.16 +0.007722 +0.13023 +0.049211 +0.010245 +0.020563 +0.022641 +0.091124 +0.15535 +0.19873 +0.29305 +0.33786 +0.10192 +0.042678 +0.020192 +23.556 +14.152 +45.576 +307.51 +136.5 +624.89 +858.12 +99.928 +151.83 +71.425 +25.967 +56.879 +472.13 +510.66 +352.05 +79.415 +0.17203 +218.25 +75.95 +56.997 +497.52 +27.933 +270.4 +669.57 +303.85 +105.2 +228.22 +122.79 +637.57 +303.92 +374.63 +245.07 +502.21 +680.14 +1623.2 +8.4624 +8.9577 +629.67 +0.061892 +8909.8 +159.49 +677.37 +153.96 +85.477 +45.226 +60.335 +0.10648 +0.18655 +0.22092 +0.012167 +0.030462 +0.015229 +0.028981 +0.048712 +0.43826 +0.252 +1.0217 +0.018653 +0.036854 +73.349 +16.855 +11.295 +26.129 +347.36 +322.43 +552.6 +890.92 +32.549 +43.508 +73.622 +24.926 +109.28 +238.14 +416.98 +188.04 +449.95 +398.66 +170.41 +79.815 +95.673 +0.27222 +0.18093 +0.099412 +728.63 +279.76 +106.08 +105.93 +114.35 +579.9 +145.47 +350.57 +326.93 +327.06 +404.72 +2442.8 +23.22 +0.13094 +1272.3 +0.061405 +948.63 +670.77 +125.22 +195.95 +34.767 +4.7996 +7.6113 +206.15 +20000 +0.085704 +0.024358 +0.058225 +0.026277 +0.12056 +0.12881 +0.095422 +0.20475 +0.1025 +261.33 +28.282 +79.353 +11.461 +14.806 +46.148 +381.07 +1339.5 +2644.2 +2204 +18499 +13.498 +49.602 +49.291 +104.11 +170.35 +330.54 +179.27 +468.26 +248.86 +294.03 +0.053086 +0.15638 +0.17896 +0.057096 +0.10409 +389.8 +278.98 +138.09 +251.28 +69.998 +487.99 +193.42 +498.54 +583.57 +304.76 +441.69 +795.82 +28.704 +4453.1 +309.73 +218.23 +598.49 +126.07 +191.18 +238.11 +151.22 +4.2604 +16.769 +8.6944 +46.896 +20000 +0.058789 +0.031753 +0.029668 +0.052241 +0.060219 +0.055602 +0.042411 +116.59 +141.78 +33.119 +49.46 +18.537 +107.1 +109.59 +453.53 +856.03 +1966.7 +4702.7 +10483 +21.285 +36.398 +48.881 +57.389 +1738.9 +540.17 +227.33 +630.35 +183.45 +226.62 +0.036326 +0.18052 +0.26416 +0.062086 +165.83 +545.48 +363.39 +98.071 +236.69 +114.21 +793.05 +477.92 +441.84 +267.67 +241.48 +472.05 +22.592 +0.35364 +141.98 +228.99 +224.72 +725.45 +82.94 +194.02 +189.35 +233.12 +489.4 +156.65 +8.6617 +132.28 +274.97 +169.6 +0.050915 +0.20541 +0.15962 +0.040473 +0.075542 +0.018255 +62.153 +123.03 +46.883 +42.171 +5631.1 +156.32 +66.638 +398.24 +674.13 +1072.3 +3557.2 +19321 +39.996 +28.732 +1360 +1106.8 +2210.8 +110.59 +66.505 +42.229 +200.82 +373.87 +595.05 +172.14 +279.86 +89.853 +139.81 +406.56 +220.54 +68.397 +113.36 +94.087 +1111.3 +324.35 +731.92 +95.594 +266.7 +62.053 +0.34574 +0.2113 +210.22 +337.77 +166.75 +9545.1 +62.981 +276.98 +349.55 +394.66 +634.95 +108.46 +0.13416 +107.17 +152.83 +338.19 +364.16 +519.42 +0.07794 +0.033883 +0.2838 +0.19881 +69.799 +49.651 +25.233 +25.888 +114.23 +52.859 +129.04 +423.46 +474.19 +1418.7 +2605 +14113 +6876.4 +632.08 +0.092299 +0.14075 +31.368 +110.51 +51.841 +23.413 +70.669 +550.1 +466.24 +118.63 +261.82 +77.011 +244.97 +433.74 +323.13 +397.83 +86.997 +482.12 +739.15 +143.05 +334.83 +0.10281 +0.22904 +0.15238 +0.022898 +0.097099 +205.89 +566.19 +99.629 +183.24 +74.231 +489.25 +531.23 +396.59 +1122 +528.96 +0.051827 +0.083037 +229.91 +319.65 +531.87 +430.27 +732.83 +7.0731 +0.06587 +0.10876 +75.451 +58.959 +30.712 +16.583 +50.468 +59.804 +154.15 +251.82 +468.08 +1276.3 +1122.8 +8582.5 +10320 +3300.7 +0.15433 +0.20388 +0.63893 +0.18157 +52.929 +24.673 +545.4 +274.18 +278.55 +75.689 +116.33 +162.69 +268.68 +551.12 +0.19239 +0.11292 +60.657 +434.49 +979.98 +21.284 +19.879 +0.099067 +0.27608 +0.11631 +0.30046 +211.34 +202.58 +258.79 +45.264 +203.56 +153.83 +614.78 +936.77 +935.1 +979.13 +0.42986 +0.23606 +0.2249 +0.40697 +369.44 +514.15 +197.64 +180.6 +21.749 +27.009 +17.92 +57.311 +21.804 +23.169 +30.378 +162.28 +143.9 +313.23 +379.54 +711.43 +1728.3 +1246.5 +3557.4 +14315 +4393.6 +0.045182 +0.10496 +141.78 +220.48 +98.791 +352.79 +813.81 +261.83 +233.61 +31.084 +0.065815 +0.16378 +0.2224 +0.20522 +0.23151 +110.96 +75.017 +0.053733 +34.637 +34.584 +25.741 +0.060038 +0.47984 +0.18324 +0.17818 +0.14935 +440.01 +144.25 +90.102 +7591.9 +2420.2 +469.07 +994.25 +256.92 +386.32 +0.4726 +0.2206 +0.10404 +0.25653 +0.21994 +491.04 +171.67 +449.13 +171.95 +14.905 +15.409 +51.898 +18.941 +8.0037 +46.097 +219.13 +210.1 +455.97 +220.09 +0.032572 +1991.2 +1630.7 +7786.8 +20000 +10464 +9506.7 +476.34 +323.28 +125.83 +109.16 +214.58 +521.41 +157.49 +281.17 +7353.2 +0.028334 +0.12307 +0.049167 +0.050323 +0.060093 +0.085251 +0.10346 +0.03905 +0.060784 +68.62 +48.841 +51.48 +55.646 +172.46 +435.81 +564.81 +238.47 +253.22 +55.839 +106.42 +213.26 +1892.6 +1061.9 +427.01 +275.19 +231.97 +0.66456 +0.14827 +0.26272 +0.10371 +0.2377 +165.92 +156.79 +154.46 +16.875 +23.637 +77.109 +27.485 +6.6853 +80.203 +161.46 +342.98 +45.325 +85.355 +0.10149 +634.3 +1968.6 +9329.9 +10999 +2855.7 +11456 +400.77 +1128.2 +70.43 +0.16392 +576.76 +1125.1 +135.97 +191.64 +4497.4 +1402.9 +0.13357 +0.064486 +0.065728 +0.069227 +0.02709 +0.077618 +0.035601 +0.026241 +0.069374 +52.44 +156.85 +15.385 +265.81 +707.69 +1896.8 +1876.6 +122.75 +48.43 +326.29 +163.61 +0.24287 +0.48659 +536.6 +517.08 +269.23 +0.18578 +0.16186 +0.2275 +0.065137 +0.36187 +0.13932 +358.77 +340.26 +505.36 +81.75 +82.705 +20.117 +19.797 +157.64 +279.37 +142.96 +44.14 +0.15828 +922.11 +755.57 +922.31 +14702 +13445 +1706 +12244 +15940 +0.073185 +0.22957 +49.04 +447.54 +320.07 +116.87 +261.78 +938.64 +1081.3 +0.20777 +0.12221 +0.18277 +0.10492 +0.029754 +0.093913 +0.27934 +0.080188 +0.12469 +37.618 +60.276 +80.551 +101.44 +47.278 +1058.1 +3053.7 +121.17 +76.871 +195.09 +107.5 +122.78 +0.30328 +0.68965 +501.64 +134.37 +53.823 +0.09565 +0.018662 +0.11248 +0.063694 +0.29031 +421.38 +525.67 +399.43 +160.19 +45.561 +30.058 +20.207 +189.46 +259.87 +159.38 +330.54 +120.43 +1131.4 +535.07 +998.61 +18824 +11549 +2342.9 +10327 +11622 +20000 +100.18 +138.46 +174.17 +197.57 +131.49 +35.636 +859.09 +755.13 +0.12208 +0.06326 +0.17272 +0.16701 +0.074919 +0.28059 +0.097066 +78.622 +28.389 +51.072 +35.034 +59.461 +19.288 +103.09 +88.101 +4344.6 +0.082997 +47.989 +543.78 +182.17 +222.24 +0.20307 +0.33123 +1.1954 +125.88 +187.31 +245.27 +0.074553 +0.080342 +0.14937 +0.060376 +551.16 +343.73 +552.14 +154.86 +81.622 +28.188 +19.149 +114.79 +167.95 +55.014 +100.81 +281 +570.48 +246.54 +913.15 +902.89 +0.28008 +2308.8 +8697 +18408 +19984 +16036 +222.52 +74.515 +92.665 +69.826 +45.865 +967.5 +0.10053 +0.047957 +0.2536 +0.31526 +0.48919 +0.14268 +0.61258 +29.592 +170.92 +58.489 +98.876 +15.002 +67.972 +273.48 +109.28 +72.592 +36.251 +0.20465 +0.073255 +416.49 +355.74 +330.01 +108.41 +0.31262 +0.24472 +0.50086 +289.54 +305.19 +392.76 +0.046269 +1364.5 +1327.8 +1237.5 +328.25 +443.09 +198.19 +75.954 +30.309 +25.599 +141.79 +96.878 +75.471 +46.122 +16.209 +462.37 +171.34 +1103 +60.938 +0.18159 +2799.2 +5734.3 +20000 +8483 +14129 +3510.5 +55.485 +114.45 +137.68 +23.673 +0.14777 +0.070849 +0.1263 +0.16507 +0.12828 +0.10689 +0.08366 +0.41969 +12.148 +350.06 +102.6 +137.85 +25.573 +116.32 +917.42 +474.11 +87.351 +35.026 +0.024031 +0.077738 +419.87 +456.46 +370.93 +198.7 +0.20856 +0.20605 +0.37574 +0.24119 +0.12551 +304.4 +380.06 +66.674 +71.871 +80.959 +154.45 +174.2 +120.15 +112.93 +30.151 +849.27 +883.1 +68.032 +39.522 +21.946 +16.395 +60.955 +114.05 +474.19 +33.016 +9.7092 +2993.5 +3237.1 +11553 +8108.9 +6792.4 +6191.8 +39.122 +101.54 +193.04 +0.036409 +0.24783 +0.39837 +0.050049 +0.13898 +0.071489 +0.15832 +0.12409 +0.024948 +0.02717 +452.57 +94.975 +125.14 +183.78 +212.71 +459.83 +1083.7 +783.08 +31.626 +34.915 +1104.8 +846.78 +587.09 +493.19 +353.47 +295.52 +329.9 +501.04 +218.75 +63.826 +235.55 +39.531 +76.067 +102.75 +0.025146 +0.081144 +0.033627 +0.017223 +181.02 +15.509 +173.78 +389.62 +396.68 +613.92 +28.719 +23.036 +46.045 +77.145 +85.617 +42.264 +13.291 +29.488 +2690.1 +10504 +10224 +6468.9 +7848.9 +5778.2 +116.14 +255.67 +0.046071 +0.23661 +0.23892 +0.26159 +0.36131 +0.015283 +0.18383 +0.047899 +0.03856 +0.032439 +0.27664 +109.79 +172.77 +168.4 +113.13 +24.335 +173.53 +48.974 +48.538 +2315.7 +1026.2 +840.83 +551.05 +313.03 +249.76 +344.58 +307.28 +135.96 +177.99 +428.03 +0.043837 +0.41669 +2624.1 +762.69 +727.96 +0.046257 +0.14633 +0.075508 +182.56 +34.696 +96.186 +131.53 +420.43 +1467 +143.31 +8.5592 +50.311 +47.216 +43.768 +240.3 +107.82 +29.467 +1813.8 +3962 +8994.7 +5268.8 +7004.7 +3779.8 +78.952 +246.37 +0.12059 +0.075028 +0.15795 +0.15238 +0.27144 +0.098843 +0.0699 +0.213 +0.15767 +0.381 +0.60497 +799.89 +107.68 +99.013 +71.833 +75.325 +206.53 +37.644 +38.616 +1900.7 +609.88 +637.64 +918.04 +90.394 +481.77 +221.92 +187.56 +0.2294 +0.46302 +0.06562 +0.031653 +267.83 +1186.8 +795.53 +370.82 +0.077734 +0.03083 +0.043048 +174.83 +54.818 +52.029 +76.192 +188.3 +319.68 +120.25 +238.01 +191.25 +38.755 +158.48 +135.68 +181.29 +406.91 +282.7 +3311.4 +4814.6 +3585.9 +7761.7 +3881.2 +846.31 +0.086949 +0.10202 +0.052249 +0.28253 +0.10332 +0.18271 +0.10702 +0.17144 +0.55987 +0.15518 +2.0496 +73.8 +133.71 +126.26 +155.91 +94.883 +90.031 +119.32 +35.375 +1227.9 +2271.3 +550.51 +98.403 +85.911 +83.981 +0.29934 +0.13344 +0.14333 +0.077316 +0.12509 +0.064666 +0.10513 +274.43 +1265.3 +983.17 +0.051347 +0.018314 +0.091159 +0.019621 +0.099907 +1.0825 +51.356 +86.534 +100.99 +312.72 +532.08 +391.66 +228.79 +34.181 +125.81 +298.69 +437 +689.64 +354.82 +5237.1 +11255 +3628.4 +9770.9 +5856.3 +1778.5 +0.13399 +0.023454 +0.087332 +0.037313 +0.15404 +0.048491 +0.052891 +0.061447 +0.22213 +43.282 +67.874 +116.76 +72.129 +54.182 +63.863 +122.55 +162.21 +81.504 +20.63 +33.49 +4785.4 +1832.1 +6520.8 +162.25 +91.154 +0.14583 +0.15027 +0.08683 +0.023238 +0.020849 +0.46043 +229.6 +379.55 +811.65 +1626.5 +0.039916 +0.012936 +0.13504 +0.0431 +0.60974 +0.46007 +0.064702 +82.252 +143.08 +632.33 +501.52 +488.26 +270.64 +7.6214 +90.725 +125.28 +936.31 +763.32 +624.63 +549.46 +2602.5 +1461.7 +9422.5 +11755 +3087.1 +4066.4 +0.082078 +0.061463 +0.035707 +0.44105 +0.053522 +0.089714 +0.039575 +55.468 +28.521 +117.1 +203.69 +202.94 +147.25 +157.56 +380.54 +108.5 +97.104 +163.15 +92.388 +4457.4 +5335.4 +6532.4 +5788 +0.33996 +0.45049 +0.49725 +0.20038 +0.42904 +0.071308 +267.39 +164.13 +488 +701.77 +0.085081 +0.044189 +0.026306 +0.11488 +0.20757 +201.13 +0.10324 +0.020678 +0.20478 +184.35 +605.83 +519.96 +460.74 +485.89 +622.06 +422.35 +159.38 +3313.4 +352.9 +935.27 +1279.9 +1473.4 +2156.4 +1300.5 +4967.8 +3252.6 +4246.7 +1252.4 +0.052149 +0.3079 +67.434 +75.049 +320.34 +58.434 +99.523 +57.999 +137.92 +65.159 +153.36 +541.38 +209.39 +357.34 +110.93 +129.27 +142.69 +93.651 +312.27 +10347 +11399 +9693.4 +2540.1 +0.19946 +0.38728 +38.135 +139.72 +527.38 +305.19 +194.73 +582.86 +0.25537 +0.45171 +0.29298 +0.13606 +0.069507 +0.096938 +127.4 +0.067033 +0.08114 +0.072745 +234.64 +921.34 +671.36 +259.89 +613.15 +535.76 +325.93 +2210.8 +3704.4 +64.302 +3399.2 +1954.2 +1198 +1236.4 +771.21 +907.98 +118.77 +60.177 +57.668 +57.181 +166.76 +132.06 +128.17 +430.11 +83.075 +664.71 +189.25 +93.583 +33.572 +17.382 +27.138 +0.15643 +98.319 +58.568 +139.78 +145.37 +214.59 +202.92 +11568 +9209.5 +56.101 +33.927 +21.344 +216.71 +84.914 +151.41 +591.12 +0.034204 +0.042723 +0.12519 +0.26055 +0.041349 +0.62342 +0.31893 +0.017328 +0.18152 +87.708 +0.11709 +0.12679 +0.065251 +427.03 +132.26 +658.26 +406.39 +608.25 +237.26 +148.45 +609.6 +120.12 +54.01 +7079.5 +6846.2 +1047.2 +1231.4 +518.96 +17.765 +16.125 +71.669 +33.905 +38.618 +111.37 +40.705 +0.24985 +528.05 +309.16 +360.2 +331.01 +77.411 +41.965 +0.31075 +0.31499 +0.63556 +46.76 +90.775 +71.922 +166.56 +211.69 +647.67 +158.57 +67.439 +47 +33.179 +54.502 +132.33 +217.83 +0.33456 +0.4556 +0.16832 +0.039423 +0.01732 +0.031499 +0.14294 +0.30992 +0.082471 +0.061064 +0.086414 +161.11 +0.24199 +94.826 +7.5736 +160.47 +46.843 +62.732 +248.94 +255.64 +145.1 +167.18 +1431.5 +96.352 +188.22 +151.82 +7009.8 +955.22 +23.798 +5.8709 +15.955 +67.27 +61.509 +173.23 +3467.1 +3358.1 +340.26 +0.1087 +175.6 +347.31 +409.32 +181.72 +0.020412 +0.43702 +0.23997 +0.19749 +1087.6 +739.29 +258.94 +114.74 +175.14 +24.965 +590.07 +191.2 +160.37 +119.23 +56.37 +48.726 +2694.9 +0.17876 +0.29649 +0.27614 +0.11797 +0.041392 +0.029639 +0.059356 +0.43379 +0.2951 +0.06078 +0.073678 +0.09094 +110.14 +0.032875 +72.236 +12.499 +119.4 +43.02 +1212.4 +197.09 +91.781 +66.608 +165.16 +571.38 +189.41 +87.048 +12131 +8930.2 +544.84 +16.451 +7.6139 +10.072 +385.99 +414.53 +331.22 +2722.3 +3730.4 +726.2 +0.066391 +293.48 +319.4 +286.56 +198.93 +0.21951 +0.30589 +0.22702 +0.35649 +1128.2 +1270.1 +795.65 +621.67 +245.36 +55.523 +45.343 +242.87 +102.26 +135.57 +95.17 +1105.7 +3243.5 +2443.7 +0.12618 +0.039646 +0.092272 +0.019015 +0.049392 +0.13788 +0.29458 +0.38693 +0.11744 +0.14648 +0.10673 +0.0909 +0.14405 +0.052876 +16.981 +29.422 +19.697 +266.75 +251.86 +135.32 +39.383 +235.9 +391.03 +130.08 +15.036 +17.366 +5406.4 +664.88 +900.34 +3.0586 +6.2398 +37.197 +454.16 +386.48 +3780.2 +3191.3 +0.064868 +0.12711 +314.4 +489.83 +754.37 +498.65 +0.036711 +0.16258 +0.17232 +0.18831 +2229.8 +1412.8 +1410.5 +324.31 +231.47 +34.193 +13.419 +9.1415 +12.812 +195.79 +107.12 +133.26 +1748.8 +906.83 +0.19532 +0.23695 +0.314 +0.1709 +0.14633 +0.20825 +0.15526 +0.29746 +0.32529 +0.072272 +0.089327 +260.09 +0.063145 +93.052 +9.6554 +25.427 +17.852 +221.4 +194.89 +172.49 +30.199 +249.35 +379.56 +763.34 +186.2 +26.149 +3026.2 +692.78 +723.21 +315.18 +3.0772 +21.304 +393.17 +246.61 +4271.9 +0.060919 +0.046626 +0.029377 +654.32 +333.56 +1338.4 +1098.4 +0.11303 +0.90226 +1.3895 +3366.2 +2411.3 +1054.4 +1000.3 +277.56 +153.2 +34.629 +30.943 +14.62 +13.599 +36.955 +70.606 +88.729 +47.73 +907.49 +1619.4 +0.069392 +0.053491 +0.2081 +0.082038 +0.31546 +0.16645 +0.18893 +0.97556 +0.13254 +0.043768 +733.47 +547.99 +161.23 +50.288 +9.3552 +53.824 +154.03 +75.496 +102.25 +55.905 +433.64 +933.58 +852.92 +32.672 +852.94 +421.81 +685.36 +602.51 +314.85 +109.95 +26.05 +3.2997 +357.36 +0.053596 +0.053042 +0.056365 +0.071051 +0.059369 +290.48 +1081.4 +1135.5 +0.3802 +203.72 +297.87 +2148.7 +1160.7 +1972.9 +698.74 +42.374 +52.705 +18.381 +15.618 +12.723 +11.885 +25.529 +41.156 +111.99 +45.488 +1386.9 +1187.6 +0.085396 +0.22767 +0.079375 +0.41602 +0.45795 +0.13486 +0.23069 +0.17411 +0.073808 +0.039912 +951.34 +180.92 +42.837 +44.92 +13.294 +44.696 +74.187 +30.373 +92.036 +28.542 +486.42 +447.17 +1746.4 +3610.7 +1197.2 +244.98 +480.04 +1316 +438.55 +148.34 +127.92 +2.4026 +4.301 +7.3373 +5.1145 +0.1194 +0.23882 +0.054546 +520.7 +1099.1 +3755.4 +2360.6 +1544.9 +334.44 +2940.2 +2360.2 +1715.7 +88.508 +98.399 +69.571 +27.698 +21.688 +16.703 +11.3 +13.157 +60.59 +41.459 +59.17 +2544.4 +842.38 +1049.9 +0.31323 +0.55603 +0.10551 +0.29991 +0.024167 +0.016651 +0.052495 +0.094912 +0.18037 +191.82 +158.57 +122.34 +66.923 +21.741 +68.479 +112.96 +876.82 +582.08 +982.02 +538.5 +5203.7 +2959.4 +3914.2 +501.39 +293.79 +870.55 +2222.3 +619.4 +1147.8 +327.87 +258.82 +4.7098 +1.8105 +8.2864 +3.3241 +0.15997 +0.33156 +0.20342 +1462.9 +4944.5 +5239 +1275.5 +214.71 +1638.8 +5050.7 +1614.2 +84.125 +94.556 +44.072 +15.984 +36.715 +27.435 +6.5033 +10.267 +91.466 +59.405 +968.65 +2216.9 +832.26 +1054.5 +651.58 +0.19969 +0.18527 +0.054305 +0.10823 +0.037332 +0.027316 +0.082641 +0.13353 +290.28 +417.81 +91.493 +93.026 +23.152 +73.085 +1171.5 +583.13 +554.53 +5963.4 +4200.4 +2515.3 +6321 +4449.1 +1047.5 +460.64 +1966.2 +683.61 +555.77 +1028.4 +280.78 +244.74 +510.85 +3.254 +4.3246 +7.8743 +5.6469 +186.84 +678.8 +1366.3 +3388.3 +2437.8 +1217.1 +1138.4 +1947.5 +5538.5 +111.19 +78.119 +65.127 +36.123 +14.116 +13.35 +11.48 +4.6086 +12.245 +24.563 +1434.5 +407.44 +762.2 +469.99 +616.19 +488.6 +0.17245 +0.13277 +0.068116 +0.53689 +0.080141 +0.21701 +0.064639 +0.43209 +205.5 +292.56 +141.74 +144.65 +52.802 +147.63 +2286.2 +1123.9 +1103.6 +1604.4 +5023.1 +2617.7 +3409.5 +7741.7 +818.84 +1323.4 +3132.8 +731.03 +394.11 +619.52 +552.56 +455.54 +631.72 +0.39564 +0.26183 +16.051 +19.122 +117.11 +200.16 +943.09 +4720.9 +1936.3 +1225 +633.51 +11.427 +18.259 +99.629 +28.145 +46.964 +28.572 +8.9142 +15.233 +5.3705 +3.1412 +6.8421 +0.037312 +4069.8 +697.2 +460.84 +347.69 +639.37 +304.68 +0.10547 +0.27055 +0.11715 +52.078 +0.041982 +0.2702 +0.059777 +0.13009 +408.22 +550.12 +296.14 +289.4 +115.23 +179.51 +876.69 +767.14 +2202.2 +2010.4 +5082.8 +3432 +2299 +2044 +573.66 +335.86 +1015.9 +444.93 +442.93 +519.13 +200.91 +234.86 +1166.4 +0.10979 +134.56 +118.02 +33.468 +10.456 +16.116 +93.107 +211.61 +908.18 +1614 +542.83 +18.869 +18.769 +61.91 +25.595 +33.321 +32.171 +7.3741 +4.9261 +3.7732 +7.7995 +0.15224 +0.049007 +0.21298 +743.64 +716.26 +234.54 +281.05 +320.82 +0.079058 +0.049581 +0.056477 +0.058339 +121.73 +88.976 +142.79 +0.084129 +358.96 +714.44 +473.74 +495.39 +111.94 +214.81 +1482.5 +1608.2 +1560.5 +996.76 +5466.6 +7466.3 +860.15 +34.31 +76.165 +376.09 +940.98 +648.1 +259.02 +343.05 +237.32 +429.58 +1284.2 +0.35656 +203.06 +92.915 +38.74 +1952.8 +57.5 +16.034 +15.171 +144.9 +146.6 +386.64 +13.552 +25.337 +49.745 +9.3368 +32.106 +21.814 +10.057 +8.3833 +3.4628 +0.31986 +0.44443 +0.031781 +0.24833 +483.19 +701.32 +354.28 +192.43 +209.7 +237.15 +0.036185 +0.10056 +0.071706 +266.71 +84.15 +90.284 +325.55 +730.94 +663.1 +561.57 +391.81 +90.439 +0.015546 +3261.2 +1657.2 +1785 +1281 +4926.5 +7388 +189.66 +47.789 +111.6 +385.84 +826.85 +733.14 +770.03 +1389.6 +720.64 +942.37 +0.094865 +0.34804 +361.38 +44.217 +52.052 +55.382 +55.763 +135.04 +11.165 +46.845 +155.18 +84.62 +14.106 +27.621 +30.876 +32.422 +23.38 +6.5055 +5.5295 +0.032178 +0.067851 +0.92011 +0.10991 +0.35937 +0.36764 +253.72 +204.32 +261.34 +132.96 +121.03 +164.39 +0.063615 +0.30102 +0.039288 +0.060661 +287.73 +130.21 +315.86 +1012.5 +406.59 +967.14 +466.26 +67.718 +415.6 +2500.3 +1952.1 +1514.4 +1331 +6187.9 +37.46 +122.8 +65.286 +64.479 +572.95 +525.35 +587.39 +974.17 +3823.8 +458.61 +83.664 +0.13177 +71.58 +270.96 +48.323 +97.772 +60.059 +43.288 +170.48 +688.02 +166.21 +234.4 +103.27 +29.945 +115.2 +54.189 +21.057 +11.543 +6.9722 +0.054221 +0.036881 +0.20741 +0.12757 +0.082005 +0.20037 +0.19051 +265.27 +347.57 +478.71 +145.93 +106.95 +125.97 +180.21 +0.37074 +0.3512 +0.11881 +782.51 +118.94 +190.28 +2246.3 +1446.3 +1310.1 +643.15 +392.78 +473.62 +2065.7 +3092.9 +848.06 +1078 +3044.3 +39.578 +89.87 +103.36 +113.57 +782.41 +953.63 +143.16 +711.19 +102.85 +89.746 +94.361 +0.020802 +83.937 +109.24 +71.171 +89.005 +68.735 +85.852 +93.225 +338.5 +219.85 +119.01 +151.15 +49.583 +128.24 +235.5 +13.677 +3.9162 +3.4719 +0.036448 +0.016638 +0.10974 +0.025776 +0.17872 +0.051307 +409.19 +214.74 +170.31 +171.8 +178.89 +99.285 +121.7 +3.25 +0.46682 +0.27197 +0.038411 +0.11383 +220.85 +128.53 +3456.6 +2369.7 +133.38 +904.17 +868.23 +1260.2 +3292.2 +1504.7 +1165.8 +2589.1 +4327.9 +46.512 +130.75 +174.84 +127.76 +783.3 +287.67 +235.85 +575.19 +61.65 +104.44 +92.054 +78.274 +65.097 +20.35 +103.39 +81.509 +50.337 +45.021 +251.01 +142.09 +960.98 +161.4 +161.57 +97.999 +185.49 +176.66 +20.015 +6.2954 +525.24 +68.706 +0.22691 +0.066399 +0.057007 +46.673 +116.12 +534.63 +442.88 +392.69 +179.41 +152.85 +65.772 +0.095101 +0.25768 +0.033214 +0.17778 +0.014181 +0.060031 +0.16431 +20.129 +3236 +61.693 +343.21 +965.7 +834.12 +713 +3136.9 +2154.5 +1684.5 +2235.7 +190.79 +21.416 +97.067 +145.73 +297.62 +128.56 +168.29 +224.18 +70.085 +1201.3 +302.88 +240.3 +108.07 +61.823 +32.249 +85.159 +39.965 +388.2 +319.55 +413.41 +224.91 +768.18 +245.77 +665.64 +62.988 +148.35 +125.86 +154.12 +233.24 +447.69 +79.678 +58.148 +0.12035 +153.03 +70.147 +138.95 +338.78 +339.17 +206.98 +95.374 +119.32 +0.061426 +0.084487 +1.1804 +0.29996 +0.019248 +0.026253 +0.027998 +62.864 +24.047 +21.726 +64.381 +207.61 +189.7 +563.36 +1214.8 +3294.3 +1658 +2824.1 +86.644 +145.2 +27.612 +70.64 +106.62 +28.807 +43.086 +56.782 +3162.7 +1376.1 +1386.1 +118.63 +250.56 +156.23 +176.66 +544.03 +159.88 +146.33 +898.93 +198.91 +447.5 +353.27 +627.32 +341.92 +63.292 +68.802 +153.75 +153.29 +185.97 +153.71 +524.92 +416.46 +259.45 +0.027143 +393.46 +96.603 +59.025 +147.99 +236.23 +234.55 +165.65 +0.41817 +0.10333 +0.11642 +0.069868 +0.13281 +0.10186 +0.060185 +45.732 +60.076 +21.233 +36.585 +48.326 +130.62 +189.66 +845.24 +780.01 +1908.3 +208.62 +167.75 +90.478 +60.41 +897.06 +263.36 +56.516 +39.65 +705.76 +1966.9 +1397.9 +1315.7 +1115.8 +623.37 +232.61 +146.36 +385.61 +197.86 +159.9 +90.327 +653.81 +279.15 +440.25 +150.54 +324.71 +188.91 +131.97 +138.71 +76.791 +179.92 +60.628 +27.495 +40.028 +105.76 +26.723 +738.87 +414.74 +56.036 +114.41 +123.45 +194.09 +91.101 +184.3 +0.25979 +0.019588 +0.099334 +0.21981 +0.099103 +0.024215 +0.088715 +66.723 +103.2 +17.681 +42.349 +69.797 +190.81 +288.01 +990.07 +1043.5 +48.275 +12.072 +288.3 +50.763 +810.42 +31.41 +80.397 +28.468 +92.216 +466.96 +2019.2 +997.98 +1088.8 +812.79 +417.17 +180.77 +56.066 +159.04 +222.37 +176.28 +105.5 +1115.1 +344.83 +330.7 +106.94 +297.76 +186.75 +343.78 +343.12 +58.288 +246.61 +104.77 +40.482 +25.593 +60.988 +28.976 +317.12 +900.53 +110.85 +165.11 +295.52 +160.01 +109.18 +212.56 +0.22673 +0.047076 +0.056549 +0.27241 +0.14521 +0.039006 +34.946 +119.14 +68.839 +20.158 +26.525 +109.2 +84.181 +180.95 +107.23 +26.654 +41.926 +12.439 +20.542 +0.62664 +91.266 +60.013 +48.837 +26.944 +85.27 +844 +2678.3 +1574.1 +1237.7 +334.01 +461.17 +235.47 +113.44 +91.406 +191.4 +115.61 +125.97 +1193.8 +740.37 +286.37 +91.103 +542.14 +232.26 +539.56 +112.08 +120.87 +212.24 +85.426 +91.637 +32.967 +99.588 +12.455 +10.973 +407.4 +175.17 +286.11 +312.26 +355.07 +150.02 +238.14 +0.034484 +0.013058 +0.0192 +0.10105 +68.43 +53.583 +72.121 +68.19 +55.213 +30.108 +36.227 +171.6 +157.41 +3075.8 +964.19 +27.825 +68.663 +12.995 +10.282 +12.274 +172.28 +36.891 +87.62 +26.678 +637.13 +1510.6 +3177.3 +1644.3 +1406.2 +517.34 +507.96 +400.61 +200.69 +180.53 +73.393 +193.07 +173.73 +1250.9 +796.15 +576.58 +515.23 +259.83 +344.4 +481.8 +159.91 +74.569 +124.6 +74.994 +106.75 +22.688 +176.46 +12.388 +502.16 +349.64 +2976.5 +331.75 +333.69 +328.73 +182.37 +191.19 +743.18 +755.27 +0.03503 +0.10898 +29.441 +35.312 +35.826 +111 +70.684 +72.816 +55.644 +58.629 +101.67 +2471.6 +860.18 +766.9 +883.26 +25.6 +5.1439 +8.7378 +15.627 +33.325 +211.9 +60.397 +101.69 +1332.5 +3060 +4609.7 +1957.1 +212.12 +530.62 +459.73 +188.94 +107.74 +168.26 +140.91 +162.16 +627.7 +725.06 +1303.5 +418.4 +361.09 +553.24 +477.98 +257.37 +0.068583 +62.281 +74.97 +38.838 +24.013 +56.757 +13.842 +877.41 +633.51 +1581.6 +0.047724 +268.64 +458.73 +169.88 +80.418 +677.29 +695.39 +255.96 +37.205 +16.765 +49.366 +63.452 +57.471 +123.72 +170.14 +66.505 +65.926 +5430.1 +2961.3 +1700.5 +1172.6 +928.9 +1575.7 +0.21461 +9.7226 +24.895 +429.78 +234.85 +61.834 +249.54 +740.19 +3068.4 +5828.7 +1520 +1229 +491.2 +627.36 +75.631 +141.23 +285.98 +133.21 +178.42 +319.06 +308.66 +1294.3 +461.18 +447.44 +529.36 +654.58 +0.14097 +0.15739 +42.862 +43.728 +62.933 +14.411 +45.803 +8.4943 +435.44 +819.18 +0.072792 +0.038644 +0.012103 +0.19201 +118.95 +105.25 +945.04 +357.43 +241.32 +874.51 +10.599 +44.553 +95.873 +95.984 +92.944 +131.29 +47.153 +3520.4 +3212.7 +4248.5 +2582.6 +2092.5 +1678.6 +53.135 +0.069471 +7.6486 +53.938 +206.7 +110.02 +74.563 +424.97 +1881.9 +5918.7 +4586.8 +1687.3 +1662 +465.73 +622.63 +0.037337 +164.78 +293.03 +103.96 +327.39 +463.18 +471.76 +391.69 +211.72 +320.64 +344.15 +931.69 +0.094937 +0.0906 +35.584 +60.108 +41.609 +13.12 +15.302 +779.02 +363.35 +306.45 +0.089787 +0.030569 +0.033739 +0.64366 +114.74 +92.952 +387.66 +228.84 +112.24 +803.74 +332.45 +1272.9 +134.58 +71.012 +45.468 +119.03 +58.841 +267.25 +2309.6 +2630.8 +1756.5 +2424 +2443.7 +60.331 +0.11907 +0.14167 +63.106 +187.46 +104.66 +185.77 +186.8 +26.522 +9706.3 +3577.8 +1967.4 +924.07 +375.15 +582.36 +1425.1 +1132.3 +409.33 +100.11 +233.65 +281.67 +800.7 +381.51 +504.34 +423.49 +731.06 +410.49 +347.21 +0.074024 +0.019557 +42.297 +38.303 +9.8744 +18.558 +229.57 +248.25 +407.76 +0.26271 +0.06502 +0.12599 +0.15635 +0.094413 +253.74 +530.71 +347.99 +164.4 +1678.3 +645.46 +1617.5 +403.34 +56.769 +54.905 +204.75 +74.958 +136.17 +636.16 +1576.1 +3172.8 +5961.7 +1326.8 +868.74 +53.337 +52.886 +0.066584 +155.57 +116.53 +210.28 +112.91 +71.816 +5.6472 +3418.1 +1590.3 +541.64 +602.74 +393 +2265.5 +1488.6 +0.037064 +167.37 +276.11 +264.12 +279.67 +1058.9 +527.69 +521.93 +642.74 +713.74 +128.96 +1093.4 +37.365 +49.628 +28.63 +9.1692 +16.203 +177.19 +295.33 +95.657 +0.061756 +0.091459 +0.24849 +0.33318 +0.086877 +501.08 +1349.8 +823.09 +316.56 +1861.4 +1065.3 +718.59 +271.42 +346.54 +92.738 +142.07 +61.35 +312.77 +503.15 +356.05 +3065.2 +14441 +3915.6 +1743.8 +325.8 +88.939 +118.41 +0.15326 +140.31 +217.4 +174.92 +48.1 +8.0063 +1607.6 +1693.6 +440.18 +416.11 +167.17 +3106 +211.86 +211.42 +268.28 +264.78 +282.61 +318.27 +1025.1 +1196.8 +846.18 +375.89 +354.41 +233.28 +65.734 +26.272 +25.831 +39.663 +12.807 +533.47 +379.67 +368.2 +164.27 +0.078384 +0.11554 +0.082844 +0.31618 +553 +198.53 +723.76 +484.41 +442 +3142.8 +2471.6 +1773.3 +193.73 +241.07 +358.73 +211.15 +56.826 +255.63 +262.19 +741.48 +459.67 +12887 +6208.7 +3007 +386.33 +2103.1 +77.422 +160.82 +128.79 +217.44 +131.81 +101.89 +11.502 +1738.5 +822.3 +1040.2 +179.04 +103.33 +464.96 +66.585 +207.9 +277.95 +311.92 +449.82 +248.89 +812.64 +1627.6 +709.11 +453.64 +378.45 +491.83 +64.011 +29.601 +35.975 +29.799 +664.47 +297.62 +513.99 +722.17 +142.55 +0.20575 +0.058017 +0.15077 +207.84 +560.63 +454.59 +563.35 +1058.5 +351.9 +3496.2 +2501.5 +3437.6 +270.15 +457.24 +409.05 +249.73 +114.22 +213.91 +426.6 +297.57 +262.89 +938.64 +7730.1 +2040.3 +838.85 +1542.2 +168.08 +307.29 +143.34 +294.1 +212.66 +115.91 +9.7039 +12.762 +1601 +377.93 +597.62 +138.19 +171.62 +65.317 +231.28 +138.16 +302.66 +1388.8 +457.5 +614.03 +686.75 +638.82 +440.39 +120.63 +77.634 +76.019 +51.889 +76.537 +0.22543 +284.39 +352.74 +367.84 +547.59 +381.31 +0.13935 +0.25902 +203.51 +90.192 +273.14 +538.77 +424.09 +1983.5 +473.25 +2627.3 +1195.4 +5353.6 +1206.2 +532.9 +673.63 +165.7 +162.53 +141.46 +408.17 +317.96 +271.79 +753.58 +1009.3 +0.072567 +1032.2 +187.01 +311.51 +268.02 +126.12 +110.86 +189.38 +150.68 +33.989 +15.462 +231.63 +316.34 +380.13 +115.43 +130.05 +71.707 +562.86 +477.46 +527.93 +1558.3 +1960.3 +224.8 +525.93 +416.59 +191.89 +82.503 +140.25 +106.87 +57.258 +0.021598 +431.39 +455.88 +904.79 +550.3 +393.87 +423.39 +145.38 +51.405 +108.13 +51.997 +362.21 +364.75 +656.58 +2086.6 +528.73 +1289.6 +923.89 +2732.1 +331.25 +884.78 +341.21 +155.31 +149.71 +218.46 +119.18 +174.57 +452.53 +773.07 +679.24 +266.37 +142.94 +97.683 +380.37 +149.4 +134.4 +121.81 +500.84 +501.78 +67.229 +31.939 +462.75 +341.69 +879.5 +209.23 +55.529 +86.01 +82.324 +928.47 +291.68 +522.37 +1145 +306.36 +218.21 +705.79 +134.13 +151.92 +179.66 +97.813 +24.116 +0.010359 +0.010067 +1127 +1205.6 +656.76 +620.3 +267.97 +216.94 +88.884 +165.88 +98.846 +377.21 +183.35 +700.05 +3735.4 +572.4 +1132.6 +730.33 +446.4 +287 +632.54 +393.18 +434.06 +158.4 +191.33 +84.412 +83.693 +939.47 +443.7 +941.02 +199.8 +115.8 +223.6 +465.88 +246.73 +136.06 +261.98 +700.52 +1562.8 +146.32 +127.78 +592.48 +263.74 +190.22 +161.35 +46.306 +56.946 +82.659 +2114 +115.17 +463.11 +0.14831 +245.82 +191.73 +184.58 +371.8 +326.49 +258.87 +63.576 +0.019762 +431.93 +159.85 +475.11 +1040.9 +1296 +841.54 +402.99 +480.07 +51.768 +164.51 +35.035 +215.17 +0.18259 +0.059901 +0.022297 +0.057724 +1241.7 +511.46 +711.68 +609.18 +666.9 +465.13 +290.3 +197.53 +139.85 +73.956 +47.989 +380.39 +311.4 +436.29 +507.97 +186.51 +99.542 +245.37 +266.8 +279.22 +332.02 +665.03 +1611 +1773.7 +4378.1 +74.561 +1272.9 +70.506 +187.63 +112.83 +107.31 +81.716 +1565.5 +187 +0.12202 +0.062345 +136.1 +293.82 +95.402 +315.8 +902.47 +118.94 +150.4 +96.962 +273.84 +1142.5 +801.58 +2156.8 +928.56 +834.15 +251.38 +1995.9 +0.0414 +0.1812 +0.083538 +0.049005 +0.020769 +0.037798 +0.088131 +0.11301 +484 +287.66 +884.71 +751.57 +661.48 +659.77 +887.06 +49.447 +41.445 +43.865 +90.55 +189.94 +189.66 +340.72 +485.29 +172.36 +376.19 +761.83 +5097.5 +1003.5 +652.8 +812.82 +920.85 +1189.6 +4819.4 +6391 +0.16031 +578.67 +96.86 +209.33 +141.24 +79.787 +254.55 +173.46 +0.1296 +0.13914 +0.067583 +305.9 +145.44 +168.87 +1369.7 +2647.2 +307.19 +105.53 +45.156 +1113.6 +707.42 +1885.1 +444.49 +508.44 +338.09 +762.05 +0.052344 +0.21712 +0.19312 +0.067138 +0.079995 +0.20295 +0.45774 +0.22191 +0.078884 +269.33 +1023.1 +1164.5 +1257.6 +660.13 +967.61 +47.455 +73.362 +25.471 +136 +288.71 +177.45 +287.67 +678.17 +280.27 +676.46 +2562.5 +5777.9 +858.92 +1096.5 +1223.6 +1513.9 +1692.3 +5694.7 +2247.1 +3084.9 +2246.8 +155.06 +93.068 +248.55 +57.639 +353.78 +174.1 +244.1 +0.2585 +0.096308 +0.067533 +290.04 +243.93 +1592.3 +3479 +1057 +726.94 +1480.3 +716.51 +357.35 +980.22 +430.01 +382.69 +354.13 +439.31 +0.11339 +0.30329 +0.094161 +0.15305 +0.092782 +0.95161 +0.29201 +0.12462 +1.1793 +116.13 +949.25 +1969.5 +1249.3 +2114.1 +1140.5 +58.849 +118.01 +21.139 +142.71 +196.98 +137.62 +259.94 +1482.5 +238.6 +462.89 +2906.3 +6953.8 +649.48 +178.38 +863.76 +1543.3 +1559.9 +2029.5 +1731.5 +1787.4 +2129 +795.17 +0.32004 +28.991 +50.484 +612.57 +141.55 +122.37 +134.45 +0.041731 +70.702 +51.923 +216.28 +993.01 +2016 +2013.5 +438.78 +1260.8 +746.74 +444.52 +351.23 +325.06 +543.78 +0.16315 +0.28269 +1.9011 +0.20684 +0.11267 +0.13311 +0.29577 +0.21237 +0.14125 +0.20694 +1143.2 +287.82 +1023.5 +1540.8 +1572.5 +1975.2 +1300.3 +46.896 +223.61 +110.88 +119.06 +144.77 +230.61 +362.28 +1128.7 +377.61 +743.6 +850.51 +499.9 +79.682 +81.761 +473.11 +1312.9 +1521.3 +1697.9 +1057.8 +1481.2 +138.08 +234.67 +482.04 +41.854 +70.885 +852.37 +208.12 +102.56 +431.75 +800.76 +149.19 +1667.3 +366.58 +567.42 +1308.7 +2441.6 +427.12 +204.49 +373.9 +393.3 +677.59 +54.114 +105.66 +0.19516 +0.86463 +0.40842 +0.63739 +0.11629 +0.20011 +0.12786 +0.2272 +0.65623 +0.145 +293.95 +435.86 +1092.5 +2019.2 +2179.2 +2114.2 +958.5 +52.593 +257.85 +326.96 +131.97 +129.86 +236.59 +369.02 +633.38 +383 +617.52 +562.76 +264.44 +46.024 +78.95 +426.66 +341.95 +752.15 +2187.7 +1842.8 +1619.1 +0.17471 +0.028696 +0.069955 +0.10603 +66.076 +10.379 +3.3762 +180.07 +171.89 +530.07 +1285.9 +918.53 +609.83 +670.38 +1298.7 +1063.2 +302.36 +235.14 +518 +592.44 +845.55 +0.11983 +71.873 +36.694 +0.38875 +0.19726 +0.43545 +0.04583 +0.077717 +0.12011 +0.10777 +0.211 +0.0708 +402.34 +404.73 +1402 +1299.1 +1455.1 +1231.3 +842.34 +109.15 +852 +392.77 +195.78 +93.879 +420.81 +595.3 +957.1 +134.47 +523.36 +629.52 +369.6 +47.113 +165.11 +450.18 +918.71 +1559.8 +2983.5 +866.86 +0.2149 +0.23093 +0.025442 +0.05904 +0.060502 +0.42906 +5.5339 +2.0516 +25.895 +18.375 +1486 +1062.2 +870.07 +878.63 +523.94 +1583.7 +1303.7 +606.72 +315.82 +263.27 +720.26 +1001.4 +0.32825 +0.19151 +0.04952 +28.273 +25.594 +0.17304 +0.10358 +0.062688 +0.032039 +0.066776 +0.11724 +0.053414 +338.72 +356.68 +670.42 +651.9 +1206.8 +2563.6 +2207.4 +123.79 +1133.4 +227.94 +99.542 +251.43 +420.14 +675.36 +190.71 +142.36 +305.95 +529.74 +381.57 +34.02 +281.94 +408.38 +1053.2 +1533.1 +85.86 +54.615 +0.045374 +0.018717 +0.052816 +0.15296 +0.10399 +0.26042 +2.0728 +10.824 +26.506 +33.959 +26.444 +1596.8 +715.5 +647.18 +437.92 +1536.1 +1037.4 +151.9 +143.99 +0.23796 +0.26085 +440.9 +987.14 +1110.2 +0.04756 +42.925 +31.724 +0.063343 +0.11335 +0.11661 +0.33646 +0.081637 +0.044376 +0.033464 +399.57 +634.47 +378.25 +251.18 +2234 +3176.5 +5028.2 +119.39 +191.37 +432.28 +1214.4 +259.53 +402.38 +399.25 +135.9 +120.39 +288.26 +1529.4 +715.89 +64.168 +235.29 +296.25 +67.732 +89.798 +80.856 +47.942 +84.504 +0.016953 +217.84 +25.735 +116.31 +42.733 +4.3546 +8.2096 +3.1987 +29.043 +87.264 +2195.9 +1737.5 +271.35 +907.2 +90.34 +154.6 +1210 +499.89 +365.24 +0.088524 +0.035878 +738.84 +339.29 +1786.6 +73.325 +41.285 +0.062174 +0.31851 +0.31385 +0.069932 +0.029129 +0.010351 +1044.1 +132.81 +151.32 +199.84 +217.41 +1888.5 +1323.9 +11074 +87.675 +162.49 +616.44 +1663.6 +379.04 +439.35 +378.99 +218.68 +161.71 +383.25 +1563.3 +639.04 +0.10046 +85.418 +114.94 +211 +97.754 +48.24 +55.1 +395.76 +303.97 +87.969 +18.556 +33.902 +9.5661 +2.7022 +4.9639 +10.163 +10.762 +193.61 +240.11 +1197.4 +390.26 +1074.4 +88.767 +0.12781 +964.92 +465.55 +250.53 +188.62 +0.062791 +0.1782 +0.058732 +3739 +108.34 +50.934 +41.785 +0.34159 +0.13706 +0.15684 +0.061521 +895.89 +356.27 +1748.3 +138.95 +107.55 +402.15 +1097.2 +956.96 +2323.6 +108.27 +287.88 +738.59 +1166.4 +486.63 +1031.1 +549.68 +1884.8 +131.24 +1201.6 +539.86 +90.43 +271.83 +40.584 +109.68 +190.63 +40.99 +49.597 +45.415 +333.59 +154.69 +138.68 +44.657 +36.135 +19.532 +4.7297 +7.7976 +8.9658 +5.7267 +56.34 +158.58 +681.4 +501.84 +3357.1 +4292.1 +104.53 +0.1353 +0.051941 +207.97 +375.6 +166.84 +457.15 +0.13671 +0.058822 +149.74 +110.95 +105.9 +114.77 +25.11 +0.05079 +2001.1 +652.04 +560.69 +2134.2 +692.44 +887.08 +217.61 +591.85 +1140.4 +2569.6 +577.13 +498.42 +318.15 +841 +1848.2 +36.32 +574.8 +917.55 +1476.8 +786.21 +265.55 +116.76 +258.44 +59.16 +104.83 +144.92 +69.731 +24.484 +129.36 +159.51 +214.09 +14.247 +32.715 +38.476 +20.739 +8.9799 +7.2342 +16.101 +16.781 +488.44 +538.64 +398.34 +828.09 +106.67 +41.871 +126.78 +0.086474 +0.10149 +0.069468 +1189.7 +189.32 +639.72 +1187.5 +113.05 +132.44 +292.97 +146.56 +64.735 +38.816 +18.292 +21.443 +669.52 +600.39 +123.62 +157.3 +571.08 +1317.9 +523.64 +1525.3 +0.11599 +756.27 +282.38 +699.47 +625.81 +159.69 +53.169 +1012.5 +593.44 +700.98 +433.49 +486.72 +42.075 +151.78 +65.416 +92.607 +102.08 +80.555 +63.733 +130.89 +112.36 +40.615 +16.801 +18.013 +33.207 +17.977 +7.4554 +7.0424 +0.035235 +502.52 +440.23 +178.9 +140.41 +418.76 +178.72 +153.36 +144.63 +0.034636 +0.01696 +0.066269 +37.02 +7.4215 +3.465 +49.714 +384.99 +0.2156 +0.97349 +0.53516 +96.312 +75.404 +50.96 +51.966 +24.959 +465.32 +130.91 +71.074 +89.912 +208.03 +54.671 +25.457 +25.383 +1533.3 +644.72 +280.6 +148.63 +205.22 +1.6084 +0.17917 +470.91 +798.8 +30.033 +116.39 +21.94 +163.12 +188.65 +78.267 +82.16 +87.656 +130.2 +78.487 +64.52 +63.097 +23.338 +41.577 +22.427 +0.26698 +0.07227 +2772.6 +1398.9 +643.92 +225.64 +217.87 +371.62 +340.65 +12.813 +54.096 +103.33 +29.891 +54.058 +57.133 +119.67 +18.702 +273.22 +804.63 +355.27 +255.94 +502.37 +320.26 +310.2 +153.4 +114.34 +24.718 +15.925 +112.02 +217.94 +7.3534 +39.109 +44.272 +22.159 +38.782 +52.373 +30.385 +426.14 +424.47 +718.53 +1029.4 +0.19847 +0.20153 +215.77 +376.5 +44.385 +73.167 +18.186 +297.67 +212.72 +199.79 +166.16 +89.559 +96.9 +153.11 +65.36 +35.015 +32.336 +69.954 +89.352 +143.53 +2648.3 +2124.5 +2055.1 +778.89 +283.17 +221.32 +300.02 +38.698 +15.083 +46.053 +10.561 +71.144 +91.034 +82.09 +0.12253 +0.89744 +0.076039 +477.82 +501.41 +400.27 +441.93 +193.22 +339.72 +257.01 +72.82 +28.552 +43.439 +52.568 +19.558 +46.297 +24.858 +121.14 +17.47 +37.452 +0.072465 +48.038 +581.68 +1130.3 +626.42 +360.05 +0.062185 +197.74 +365.28 +180.19 +68.968 +67.71 +41.945 +277.72 +402.31 +154.34 +143.06 +338.26 +158.11 +62.766 +20.549 +41.364 +33.542 +106.77 +82.653 +200.85 +2148.6 +1275 +1298.1 +265.27 +323.46 +379.42 +0.32796 +47.903 +41.26 +58.991 +31.091 +173.39 +0.1605 +0.12609 +0.17936 +0.64501 +0.17449 +0.074845 +113.57 +260.54 +464.95 +494.73 +31.947 +234.32 +68.536 +63.576 +47.772 +25.674 +18.393 +142.49 +0.024056 +0.097862 +0.073398 +0.21122 +0.41314 +451.36 +1749.5 +589.68 +442.76 +721.83 +3023.2 +220.99 +703.55 +231.9 +106.1 +47.596 +72.048 +107.79 +357.36 +195.69 +185 +37.987 +42.876 +36.504 +134.01 +139.19 +24.233 +109.73 +126.86 +198.37 +759.91 +530.42 +310.9 +180.98 +0.1226 +36.767 +77.535 +64.672 +48.156 +52.085 +31.238 +0.10014 +0.15015 +0.10824 +0.1616 +0.1384 +0.12659 +0.098371 +69.073 +103.85 +276.22 +386.44 +63.309 +24.329 +56.721 +46.97 +26.884 +23.512 +998.77 +34.931 +87.25 +0.067415 +0.86133 +0.076759 +0.18656 +48.34 +27.538 +736.54 +381.83 +246.49 +3545.6 +1.2773 +923.19 +247.82 +293.97 +146.83 +129.83 +71.032 +143.47 +157.1 +70.291 +57.068 +18.112 +256.04 +95.5 +150.79 +19.047 +106.18 +142.36 +627.8 +854.45 +482.76 +0.041095 +482.13 +479.89 +34.668 +32.237 +11.149 +21.67 +36.577 +0.055264 +0.030211 +0.18916 +0.041197 +0.23012 +0.25767 +0.18535 +68.385 +34.255 +114.24 +558.09 +375.53 +67.427 +124.55 +66.604 +131.56 +26.305 +1926.7 +785.01 +0.44827 +0.04744 +59.846 +0.77496 +2.5935 +0.54714 +29.221 +17.378 +5.937 +209.38 +259.79 +868.79 +1739.2 +1014.6 +299.42 +205.64 +153.05 +85.944 +126.24 +188.37 +648.38 +172.7 +138.04 +66.191 +181.49 +95.369 +199.56 +22.052 +47.261 +74.439 +1052.5 +1013.8 +0.021778 +0.03919 +337.48 +1055.3 +50.16 +0.021448 +0.063402 +17.59 +12.243 +0.039517 +0.038394 +0.025718 +0.10192 +0.36288 +0.32193 +0.54223 +30.582 +16.386 +92.145 +304.81 +383.42 +138.95 +179.72 +16.896 +92.312 +860.9 +628.1 +657.3 +290.21 +0.07433 +0.073695 +0.48336 +0.87667 +0.71858 +15.273 +10.698 +8.2003 +12.525 +168.34 +1166.4 +844.42 +586.8 +232.44 +608.06 +115.58 +94.907 +161.09 +231.07 +520.7 +1039 +0.13615 +0.18525 +171.62 +1927.5 +104.85 +39.486 +30.53 +114.67 +594.84 +178.76 +0.071796 +0.11671 +755.1 +1745.4 +186.86 +0.024138 +19.824 +27.499 +18.195 +197.23 +0.30233 +0.083009 +0.5889 +0.79994 +0.21453 +0.28394 +0.090087 +29.891 +24.294 +145.38 +179.98 +147.61 +210.05 +92.321 +41.721 +619.25 +295.13 +556.6 +379.09 +596.95 +0.12375 +0.40087 +0.88514 +0.32101 +13.412 +7.8664 +2.9874 +11.833 +11.58 +18.667 +681.14 +311.61 +316.88 +342.53 +179.22 +157.69 +266.2 +252.09 +525.57 +348.8 +0.070855 +0.11907 +117.89 +1087.3 +1101.7 +49.618 +31.649 +45.615 +221.72 +138.91 +226.83 +1036.4 +875.82 +2119.6 +211.48 +0.018352 +0.028232 +13.519 +36.264 +169.34 +0.066552 +0.13617 +0.6378 +4542.5 +726.64 +30.05 +51.642 +25.493 +30.622 +157.78 +67.765 +139.04 +177.89 +37.449 +44.514 +0.14375 +487.75 +558 +265.24 +443.11 +1384.5 +0.80981 +0.38665 +0.33736 +4.7574 +26.617 +4.7194 +14.607 +14.744 +147.59 +90.592 +456.43 +408.08 +81.184 +67.094 +31.248 +27.379 +281.48 +324.56 +176.9 +0.13061 +71.589 +181.24 +254.15 +573.5 +466.88 +20.069 +55.479 +70.557 +139.58 +127.47 +1490.6 +788.72 +1028 +0.038751 +0.015453 +37.693 +20.275 +32.217 +167.26 +125.91 +4867.5 +8877.5 +4744 +817.33 +35.749 +59.325 +958.25 +195.81 +258.71 +63.075 +156.37 +150.81 +431.78 +1187.2 +0.028357 +375.99 +838.73 +222.5 +394.75 +1870.8 +0.30641 +0.14258 +0.42786 +20.021 +11.69 +5.4684 +19.84 +652.16 +492.08 +174.88 +328.01 +51.1 +97.463 +65.539 +55.23 +7.7214 +14.614 +37.193 +102.32 +2533.2 +585.09 +185.49 +216.1 +651.95 +520.27 +300.72 +58.958 +81.609 +97.312 +75.948 +1433.3 +907.35 +1241.7 +0.05995 +0.070423 +0.44508 +20.826 +59.671 +697.72 +274.65 +346.65 +169.15 +241.8 +290.14 +71.349 +0.47021 +793.28 +224.12 +273.63 +146.82 +148.06 +179.88 +232.27 +613.69 +9.4024 +0.096808 +760.82 +345.81 +430.79 +2224 +459.39 +0.19736 +0.1455 +62.836 +18.177 +204.45 +121.54 +632.85 +862.34 +70.088 +138.22 +129.8 +47.968 +29.455 +66.806 +13.889 +14.37 +43.484 +36.818 +854.44 +1062 +255.67 +201.24 +550.02 +5286.2 +296.44 +155.38 +99.316 +40.106 +169.44 +740.98 +1306.1 +1103.8 +0.25605 +0.35843 +2106 +484.96 +2220.6 +834.45 +330.34 +509.35 +2414.1 +2819.7 +635.36 +0.07977 +0.32448 +520.02 +222.09 +241.45 +226.28 +125.64 +340.08 +299.6 +435.55 +9.7728 +0.1244 +0.05853 +206.18 +827.09 +2866.4 +1257.7 +0.45667 +0.36313 +83.731 +167.17 +190.1 +97.632 +296.33 +335.35 +85.532 +310.68 +219.25 +155.37 +31.289 +61.146 +27.941 +13.055 +46.185 +183.23 +1213.5 +784.46 +318.82 +195.94 +110.56 +3865.2 +3891.2 +85.209 +224.04 +34.712 +115.14 +518.04 +876.01 +1716.3 +428.32 +315.64 +846.44 +372.49 +1481.4 +1189.4 +261.56 +580.89 +3189 +2509.4 +0.10297 +0.046378 +0.074906 +0.31122 +145.46 +334.43 +538.64 +393.19 +74.503 +114.16 +135.53 +5.8721 +11.169 +0.13823 +124.64 +418.85 +1429.5 +710.15 +335.69 +0.52072 +88.318 +59.52 +152.28 +128.36 +459 +248.28 +117.47 +450.69 +0.17389 +288.08 +27.099 +112.61 +40.598 +28.644 +49.515 +394.32 +3566.4 +1099.1 +335.89 +1098.3 +0.011366 +3284.4 +2602.6 +4333 +127.79 +51.8 +264.84 +499.72 +373.39 +557.13 +436.43 +493.29 +660.56 +479.86 +276.32 +203 +210.16 +391.62 +0.20188 +0.070393 +0.049973 +0.08111 +0.073274 +0.095156 +681.82 +942.6 +465.85 +217.13 +103.9 +65.016 +96.499 +13.8 +9.1091 +37.956 +79.985 +234.87 +999.19 +610.2 +454.25 +0.091811 +85.753 +61.127 +121.42 +96.061 +446.39 +237.38 +101.94 +1025.5 +489.33 +242.65 +325.84 +156.06 +40.599 +67.447 +148.68 +1049.7 +2957.5 +1510.6 +630.23 +1094.6 +113.4 +1730.1 +1956.6 +2528 +1088.7 +129.32 +634.36 +369.34 +410.17 +476 +469.77 +14.374 +17.996 +126.14 +289.74 +605.85 +210.27 +391 +0.042449 +0.16027 +0.016946 +0.015409 +0.068875 +43.138 +290.34 +818.35 +641.98 +482.93 +136.26 +77.203 +2.7069 +4.0845 +5.8779 +15.019 +44.188 +414.64 +1083.9 +921.65 +251.23 +0.13003 +90.357 +42.585 +86.969 +64.45 +876.14 +234.04 +56.997 +607.64 +490.28 +44.936 +354.53 +80.268 +27.515 +89.532 +155.06 +906.25 +904.35 +1330.4 +535.8 +1563.8 +3740.5 +1248.5 +2045.5 +1590.2 +2510.2 +52.266 +111.12 +459.63 +683.51 +685.6 +15.426 +12.24 +19.932 +150.57 +189.68 +286.29 +189.83 +0.08544 +0.18577 +0.023424 +0.08264 +0.052771 +55.624 +134.85 +504.88 +1489.3 +827.4 +517.05 +122.22 +8.8171 +1.9658 +2.0627 +7.633 +16.331 +23.068 +960.95 +2077 +774.08 +132.74 +0.36926 +82.21 +110.38 +54.136 +184.39 +196.02 +205.28 +125.46 +452.06 +313.96 +58.049 +14.138 +53.612 +25.246 +81.582 +266.45 +1284.3 +1107.6 +1339.7 +1063.3 +1211 +24.905 +1164.2 +1491.3 +1946.3 +0.085308 +0.019249 +48.907 +759.51 +1457.7 +64.646 +14.602 +18.561 +35.899 +60.252 +611.88 +506.13 +753.37 +0.097946 +0.025892 +0.035392 +0.045721 +0.15179 +172.56 +350.25 +776.41 +765.26 +720.35 +453.6 +16.471 +13.518 +34.595 +0.026014 +10.297 +7.36 +19.813 +39.628 +2455 +1968.5 +172.31 +0.52791 +85.927 +79.914 +106.9 +181.64 +348.37 +271.77 +180.58 +339.07 +240.03 +81.512 +15.008 +58.916 +45.367 +70.907 +126.54 +1357.8 +734.45 +844.5 +1266 +1131.1 +22.526 +0.17569 +539.77 +577.78 +267.14 +310.94 +375.76 +181.61 +875 +74.623 +284.96 +293.64 +2150.2 +803.33 +530.64 +825.42 +470.08 +0.017569 +0.055829 +0.045731 +0.063918 +220.91 +345.71 +335.74 +768 +1187.2 +0.1844 +10.574 +24.056 +11.499 +20.784 +18.517 +0.049389 +7.2861 +9.3063 +31.541 +46.434 +4960 +111.13 +0.28127 +132.79 +88.241 +178.62 +197.21 +640.15 +541.34 +522.28 +294.69 +405.12 +273.26 +38.131 +420.76 +45.479 +91.787 +0.85474 +1272.7 +679.76 +582.39 +567.89 +955.26 +32.407 +889.39 +1324.6 +355.64 +295.44 +221.51 +557.73 +42.52 +72.62 +102.29 +150.01 +133.33 +143.63 +212.3 +370.14 +309.8 +558.49 +0.023853 +0.12282 +0.24652 +172.19 +208.16 +204.22 +383.75 +327.65 +2180.6 +0.32733 +10.5 +8.8149 +20.456 +25.376 +13.497 +150.37 +45.274 +11.425 +18.958 +46.069 +19.463 +0.30165 +0.16494 +129.46 +71.32 +1351.9 +214.33 +1241.8 +455.46 +1405.8 +186.4 +301.11 +422.31 +77.404 +161.28 +235.82 +0.70436 +0.50665 +10294 +578.6 +205.7 +378.31 +247.09 +1722.7 +1064.5 +860.58 +59.366 +125.87 +251.88 +142.26 +50.057 +4358.2 +123.92 +233.85 +317.28 +230.24 +323.35 +237.27 +685.12 +401.23 +466.28 +0.11989 +394.21 +218.89 +144.43 +225.62 +236.91 +0.030465 +0.11116 +0.095551 +0.55263 +9.072 +18.694 +17.052 +13.882 +71.084 +31.57 +128.3 +20.847 +42.064 +17.91 +7.5684 +0.40808 +130.04 +147.14 +590.84 +1294.9 +967.55 +851.26 +475.61 +141.3 +411.69 +802.86 +162.96 +134.36 +230.06 +117.62 +0.36558 +6324.8 +169.88 +296.16 +473.38 +336.53 +1806.5 +2030.7 +173.86 +62.638 +100.26 +440.71 +114.14 +0.40009 +0.30926 +117.54 +110.41 +152.75 +119.06 +193.18 +212.46 +369.12 +0.1836 +508.84 +728.21 +938.31 +292.01 +231.21 +293.95 +304.89 +0.033314 +0.10135 +0.15282 +0.6723 +7.3363 +237.48 +66.958 +12.629 +61.721 +42.823 +253.66 +73.954 +24.763 +18.83 +8.2548 +30.659 +75.263 +970.26 +541.67 +799.48 +1033.2 +581.86 +502.57 +940.34 +420.19 +800.28 +209.65 +101.09 +41.289 +142.82 +62.857 +59.003 +176.32 +115.49 +300.26 +303.52 +3794.6 +87.911 +60.359 +65.53 +112.22 +173.64 +106.76 +34.379 +126.42 +137.34 +91.491 +101.56 +62.362 +173.72 +145.94 +232.28 +9.5405 +0.1921 +0.16813 +664.93 +610.52 +130.54 +192.13 +313.85 +0.15819 +0.1108 +0.052321 +252.69 +93.038 +123.49 +34.536 +19.187 +13.554 +40.676 +133.78 +0.012091 +40.135 +28.928 +20.715 +35.891 +1993.6 +571.15 +581.84 +466.08 +877.04 +470.9 +65.902 +1482.9 +2285.2 +635.27 +305.04 +130.16 +38.112 +97.83 +127.99 +46.226 +96.815 +74.322 +52.556 +149.49 +25.225 +72.068 +72.47 +143.92 +157.84 +0.16203 +37.039 +39.236 +75.323 +232.44 +1630.5 +2434 +121.68 +456.96 +227.48 +130.49 +29.916 +0.58132 +0.067805 +57.089 +239.3 +1148 +136.89 +112.34 +79.663 +0.13417 +0.19175 +0.12631 +260.86 +194.99 +63.405 +9.054 +15.465 +40.581 +0.023232 +0.021142 +0.0293 +21.144 +22.945 +87.37 +1917.5 +915.26 +612.26 +668.67 +735.86 +141.87 +736.14 +560.49 +3120 +354.12 +556.35 +73.302 +59.177 +126.23 +101.26 +32.884 +73.783 +39.784 +42.599 +46.013 +55.69 +63.69 +127.89 +361.11 +44.252 +48.617 +76.659 +47.136 +36.383 +0.086091 +0.13785 +1529.2 +83.681 +918.35 +329.61 +238.79 +34.485 +384.83 +0.40877 +0.11751 +184.83 +853.47 +937.13 +625.27 +30.09 +98.193 +66.893 +0.16512 +712.46 +250.24 +239.78 +16.532 +0.022769 +97.087 +0.082615 +0.030556 +0.039495 +0.076921 +0.03297 +0.13081 +1880.1 +790.72 +571.21 +130.62 +97.113 +83.986 +188.47 +3240.8 +2285.4 +424.58 +533.96 +822.4 +790.61 +190.68 +530.97 +1025.2 +517.29 +57.51 +46.469 +32.37 +68.906 +35.758 +46.614 +37.095 +22.332 +41.674 +128.95 +33.061 +59.754 +0.061617 +0.16163 +0.085615 +61.675 +2246.1 +529.12 +196.44 +70.135 +506.35 +1803.9 +321.68 +842.86 +568.03 +722.48 +340.02 +0.11562 +0.42642 +0.78126 +52.659 +60.41 +115.34 +138.52 +18.54 +0.013211 +0.0147 +0.067439 +0.055727 +0.094388 +0.17427 +0.029811 +0.090882 +2428 +830.66 +617.91 +78.124 +109.96 +48.02 +205.06 +157.11 +116.5 +147.26 +622.43 +677.23 +447.27 +366.81 +599.54 +999.03 +1350.8 +430.52 +54.272 +48.573 +115.9 +84.68 +86.391 +9.7096 +6.48 +30.083 +60.887 +0.055544 +0.11493 +0.29547 +0.10904 +0.046772 +164.55 +848.45 +770.61 +155.78 +219.23 +620.98 +668.22 +1321.1 +659.43 +823.87 +295.02 +227.58 +0.33073 +0.21478 +0.21812 +0.88187 +87.352 +94.317 +79.113 +55.839 +25.99 +0.11826 +0.0463 +0.20368 +0.15934 +0.20266 +0.078118 +0.17133 +1269.2 +694.96 +898.92 +130.92 +98.952 +19.79 +274.99 +67.228 +61.322 +407.21 +242.26 +738.27 +357.11 +250.49 +633.53 +1035.8 +1193.8 +66.531 +119.53 +8.9408 +65.479 +131.95 +109.4 +20.582 +17.322 +19.266 +0.25694 +0.30751 +0.21913 +0.1033 +0.032373 +0.1699 +370.56 +1102.2 +899.91 +310.19 +116.45 +471.68 +2196 +0.2517 +539.89 +367.52 +279.07 +248.3 +120.78 +1.4623 +0.56745 +0.12788 +0.16452 +0.2811 +69.861 +120.9 +24.2 +0.057783 +0.053848 +0.34549 +0.30368 +0.11393 +0.13671 +0.049957 +4577.6 +1355.6 +1169.1 +1865.3 +1300.1 +22.046 +276.4 +38.201 +112.11 +141.8 +121.27 +812.69 +339.75 +340.72 +1749.8 +1232.2 +790.75 +119.01 +35.604 +19.792 +55.792 +91.544 +83.599 +39.487 +14.554 +28.944 +0.095537 +0.34267 +0.12202 +0.072427 +0.092746 +0.10909 +0.055135 +1129.7 +1053 +659.98 +118.1 +280.91 +1990.4 +0.10124 +0.095934 +186.43 +173.01 +231.54 +162.3 +160.33 +170 +0.19699 +0.084227 +0.12183 +50.555 +115.97 +239.76 +202.39 +565.23 +0.050472 +0.13295 +0.15889 +0.00915 +0.064198 +0.16449 +2256.4 +936.02 +795.29 +1198 +346.32 +722.52 +22.909 +74.286 +417.16 +113.5 +453.31 +206.37 +727.65 +1359.7 +2645 +266.94 +111.19 +46.713 +35.39 +33.117 +92.538 +93.318 +40.804 +22.519 +73.753 +202.11 +0.18169 +0.10232 +0.088391 +0.24022 +392.76 +1537.5 +3303.2 +1546.3 +473.38 +327.6 +569.55 +506.92 +181.99 +504.2 +0.20371 +108.06 +205.52 +163.71 +209.54 +235.48 +308.7 +615.5 +0.025609 +0.10415 +15.16 +18.585 +206.75 +614.82 +1118.3 +0.061337 +0.079986 +0.060736 +0.079614 +0.2289 +144.87 +46.092 +68.88 +1366.4 +380.28 +200.68 +315.58 +111.99 +209.48 +163.25 +277.06 +295.44 +219.27 +2084.6 +3052.7 +132.12 +176.53 +92.845 +66.584 +54.093 +46.612 +78.561 +34.317 +146.96 +86.729 +205.64 +55.682 +0.079042 +0.14217 +0.1425 +739.8 +1316.8 +2588 +4526.7 +2313.3 +380.75 +135.57 +379.73 +367.82 +560.19 +970.25 +71.486 +79.599 +97.699 +82.987 +105.01 +882.96 +489.95 +599.38 +698.06 +453.94 +22.206 +75.62 +335.74 +587.02 +282.35 +0.040447 +0.088218 +0.16329 +77.803 +77.391 +119.72 +12.219 +5.9061 +156.03 +278.35 +376.06 +437.36 +190.64 +122.54 +565.25 +682.91 +359.68 +2707.6 +0.072793 +95.906 +114.09 +75.068 +34.858 +60.153 +26.578 +47.649 +282.6 +130.3 +84.802 +140.3 +67.09 +30.589 +0.059206 +742.48 +875.83 +639.03 +1406.1 +4081.3 +929.86 +1336.9 +323.74 +254.24 +241.76 +661.21 +1313.4 +43.589 +42.922 +66.418 +49.554 +134.98 +60.055 +1197.3 +761.6 +986.42 +399.33 +482.13 +162.2 +407.89 +1052.3 +304.01 +0.063463 +0.047209 +0.024671 +63.195 +66.695 +51.83 +53.94 +113.37 +140.95 +114.71 +229.29 +1029.4 +1612.3 +5387.4 +5003.9 +243.19 +9380.7 +923.37 +50.165 +186.82 +277.69 +113.39 +67.843 +59.106 +15.583 +25.626 +20.198 +222.9 +23.408 +83.357 +48.15 +48.912 +0.16764 +656.39 +509.97 +250.51 +527.53 +822.98 +763.49 +1325.4 +441.61 +384.69 +252.12 +0.62489 +0.050631 +41.746 +43.172 +74.317 +60.967 +55.314 +5334.2 +3800 +2996.8 +1119.5 +260.93 +231.5 +307.88 +213.3 +443.96 +392.29 +0.22197 +0.08749 +0.030671 +727.22 +124.38 +84.005 +81.797 +292.63 +247.03 +115.11 +291.74 +881.73 +2682.8 +4328 +5540.3 +5323.4 +86.462 +281.39 +81.598 +179.21 +151.75 +65.767 +112.55 +32.61 +10.206 +19.956 +117.73 +109.03 +57.502 +53.756 +37.745 +80.822 +385.81 +659.12 +674.45 +468.03 +562.78 +1135.6 +460.75 +1074.8 +499.6 +283.92 +395.5 +1236.5 +1638.2 +53.248 +112.71 +69.911 +128.9 +60.747 +4309.6 +2865.6 +2328.2 +624.18 +185.71 +353.75 +239.71 +253.09 +286.23 +0.1082 +0.13238 +0.064563 +0.03965 +334.88 +505.95 +86.81 +178.3 +663.96 +1075.5 +818.29 +577.13 +1774.9 +632.49 +164.9 +5470.9 +8943.5 +3742.9 +1345 +115.24 +144.01 +112.14 +107.65 +89.546 +41.104 +7.1019 +20.637 +43.597 +89.798 +75.311 +74.725 +116.86 +259.26 +455.68 +498.77 +502.82 +704.79 +523.69 +0.41684 +1301.5 +941.47 +1015.1 +251.64 +1433 +1582 +1398.3 +40.127 +198.85 +76.973 +120.06 +7388.2 +3835.5 +251.31 +244.94 +615.07 +301.95 +535.92 +374.12 +0.20206 +0.050042 +0.056924 +0.26609 +0.087839 +0.022109 +368.45 +438.24 +111.09 +132.05 +921.37 +808.9 +1019.5 +531.18 +2149.3 +435.63 +144.87 +230.64 +10643 +5898.3 +2026.1 +40.111 +188.47 +138.91 +168.82 +203.81 +42.116 +5.2948 +22.695 +35.925 +121.14 +612.33 +188.1 +57.532 +293 +570.36 +540.93 +408.08 +579.63 +0.15926 +0.81058 +0.04284 +803.55 +555.01 +437.07 +896.91 +1378.6 +159.61 +68.162 +254.39 +88.432 +14250 +2836.4 +31.255 +285.21 +323.57 +214.99 +90.656 +0.0804 +0.14419 +0.14268 +0.13 +0.053223 +0.15144 +0.29863 +0.035042 +492.88 +210.98 +94.369 +305.37 +662.38 +721.62 +1181.4 +489.78 +438.51 +1218.3 +97.78 +75.163 +4984.5 +4091.3 +60.795 +31.678 +124.76 +198.52 +176.61 +206.67 +37.318 +3.6301 +9.1312 +18.701 +134.01 +231.5 +97.791 +70.328 +279.16 +551.86 +816.88 +349.68 +563.94 +0.85929 +0.42366 +0.18717 +1002.1 +315.58 +666.87 +1031.4 +124.97 +86.975 +97.122 +217.14 +89.2 +872.74 +126.94 +53.245 +546.53 +572.12 +229.6 +0.059899 +0.017263 +0.16697 +0.16621 +0.3571 +0.18074 +0.022769 +0.047176 +0.23812 +434.36 +151.43 +38.136 +218.13 +882.65 +782.61 +1342.9 +1696 +1006.5 +357.73 +634.14 +49.816 +5397.2 +5469.8 +46.838 +33.119 +66.15 +185.11 +105.78 +225.73 +35.267 +14.78 +20.735 +27.536 +24.715 +121.73 +113.63 +55.759 +323.64 +206.89 +763.23 +0.42954 +0.12588 +0.38625 +0.29449 +0.043779 +0.27847 +543.34 +460.2 +1147.8 +238.92 +61.311 +181.05 +208.56 +508.39 +339.02 +175.28 +125 +164.62 +0.043501 +0.02866 +0.062457 +0.040213 +0.11443 +0.21913 +0.11669 +0.04374 +0.016654 +0.17227 +0.062289 +247.2 +218.31 +67.361 +200.25 +612.29 +242.55 +647.37 +2424.1 +1143.5 +952.74 +137.37 +53.519 +7754.5 +79.312 +94.58 +32.569 +77.014 +105.6 +98.382 +187.66 +23.153 +16.673 +23.345 +33.799 +50.45 +64.834 +157.59 +42.568 +261.19 +185.93 +614.25 +0.33103 +0.28102 +0.13799 +0.15294 +0.073055 +0.8494 +127.22 +462.39 +582.03 +179.22 +129.21 +983.13 +763.44 +137.08 +345.52 +88.9 +165.44 +27.223 +0.1583 +0.096839 +0.071621 +0.043791 +0.050473 +0.061135 +0.022685 +0.083898 +0.038899 +0.7427 +0.6071 +267.54 +198.31 +69.754 +84.708 +390.57 +708.21 +2934.1 +1721.4 +1116.8 +1230.7 +174.38 +9386.7 +108.48 +139.66 +75.38 +26.515 +120.66 +108.66 +89.76 +344.93 +74.355 +68.365 +34.298 +28.465 +48.124 +70.851 +96.992 +61.976 +371.84 +1575.1 +1094.2 +342.1 +0.077362 +0.076971 +0.05553 +0.12666 +295.68 +252.99 +382.44 +483.03 +458.97 +85.039 +498.06 +810.13 +103.07 +208.19 +161.99 +125.81 +0.1919 +0.12191 +0.037021 +0.29284 +0.052602 +0.32042 +0.046684 +0.1262 +0.44467 +0.64395 +0.06337 +0.2208 +223.39 +273.76 +67.621 +70.992 +506.43 +851.67 +2396.2 +1877.6 +62.199 +28.433 +732.63 +765.14 +220.15 +235.48 +61.016 +26.896 +87.236 +70.419 +203.86 +357.74 +58.619 +70.907 +334.52 +60.353 +98.742 +99.331 +142.46 +37.093 +187.75 +1227.5 +1563.1 +300.69 +0.064358 +0.18656 +81.927 +46.866 +250.13 +291.85 +794.61 +735.84 +667.5 +206.08 +413.8 +139.57 +101.27 +34.505 +106.77 +0.10019 +0.11337 +0.081098 +0.13903 +0.17152 +0.057469 +0.27896 +0.089418 +0.73589 +0.32431 +0.64672 +0.34203 +0.065661 +160.32 +80.67 +123.31 +179.51 +350.25 +5073 +3533.3 +115.99 +157.95 +8106.2 +1879.3 +648.6 +84.411 +303.74 +100.71 +38.849 +86.472 +161.51 +263.09 +195.46 +89.781 +39.924 +225.73 +42.995 +78.674 +53.808 +94.261 +88.364 +373.94 +996.86 +1341.8 +464.36 +0.039879 +65.058 +91.046 +81.726 +381.79 +1495.5 +683.13 +1123.8 +517.43 +163.17 +24.442 +40.156 +38.388 +25.15 +94.066 +0.024743 +0.068258 +0.19848 +0.93696 +1.4281 +0.11725 +0.15148 +0.1642 +0.23464 +0.22145 +0.19224 +2.505 +0.70668 +201.05 +90.126 +126.88 +1190 +777.07 +4899.7 +678.77 +1130.2 +6.7953 +10596 +3770.2 +779.21 +176.74 +157.91 +168.41 +66.738 +76.78 +96.715 +182.56 +18.197 +54.624 +44.979 +83.368 +60.242 +73.634 +65.679 +70.81 +537.25 +451.41 +719.55 +1099.7 +340.66 +322.84 +40.488 +616.53 +3816.4 +1162.9 +1224.5 +416.71 +1044.3 +9063.2 +70.761 +17.786 +76.351 +27.221 +10.547 +16.9 +0.021039 +0.045338 +0.095938 +0.13353 +0.31105 +0.055649 +0.083421 +0.044455 +0.016204 +0.14049 +0.34422 +0.09559 +0.34635 +140.15 +1944.3 +836.85 +359.34 +380.13 +902.41 +896.1 +916.53 +260.12 +5520.8 +1990 +487.75 +384.89 +111.42 +189.71 +50.02 +137.73 +165.61 +67.841 +17.14 +69.179 +42.488 +52.427 +84.819 +103.17 +44.679 +83.167 +342.59 +1181.8 +378.38 +1105.3 +410.63 +8129.5 +2901.9 +627.33 +1594.8 +725.26 +1002.6 +0.09602 +0.063524 +6443.4 +103.58 +26.237 +86.196 +51.087 +25.939 +31.543 +0.014291 +0.004506 +0.030525 +0.15593 +0.18315 +0.043413 +0.24672 +0.046868 +0.14889 +0.18599 +1.9303 +0.37693 +0.41698 +630.52 +944.82 +97.564 +296.6 +185.71 +986.83 +1218 +1653.2 +469.28 +3312.5 +1509.8 +443.92 +330.44 +123.85 +136.11 +39.228 +159.79 +0.73861 +30.21 +40.968 +27.758 +59.848 +46.37 +1098.8 +43.889 +98.104 +40.548 +235.48 +669.96 +348.12 +370.51 +243.04 +4807.6 +3606.9 +576.44 +1256.6 +0.30355 +0.17953 +0.29701 +0.053853 +5896.5 +50.044 +46.258 +47.816 +42.806 +69.952 +106.56 +0.34318 +0.025863 +0.1704 +0.13901 +0.095444 +0.092367 +0.12837 +0.018696 +0.016011 +0.044065 +0.1034 +0.068349 +0.1808 +619.98 +312.02 +129.54 +279.42 +216.25 +123.29 +983.97 +3944.9 +543.57 +3465.9 +1794.2 +315.24 +364.92 +128.76 +316.27 +40.732 +118.16 +1.2723 +46.693 +17.538 +73.975 +108.89 +99.22 +125.81 +113.48 +227.24 +75.975 +202.5 +902.64 +434.51 +241.82 +7366.6 +5050.8 +5326 +98.017 +69.843 +0.16565 +0.25871 +0.077979 +0.077727 +202.77 +44.166 +74.829 +52.991 +37.051 +79.419 +245.29 +188.46 +0.022691 +0.013789 +0.14137 +0.053556 +0.10356 +0.11882 +0.10259 +0.019621 +0.043758 +0.20601 +0.11421 +0.42741 +1109.6 +2030.4 +2451.1 +313.58 +596.71 +125.66 +135.84 +442.03 +778.45 +810.21 +738.1 +315.35 +382.64 +106.18 +173.69 +84.679 +92.843 +17.735 +65.789 +39.076 +56.094 +163.55 +164.85 +495.57 +125.21 +269.44 +118.81 +242.01 +929.05 +716.76 +4381 +4876.5 +4573 +148.31 +96.322 +59.475 +0.042397 +0.076226 +0.13975 +456.51 +118.43 +34.431 +67.079 +45.391 +34.866 +59.594 +104.74 +147.49 +0.10363 +0.056511 +0.14809 +0.098921 +0.031666 +0.025205 +0.11921 +0.045407 +0.094984 +0.23079 +0.096631 +0.10193 +1.6416 +4695.7 +294.95 +3856.5 +302.47 +31.979 +65.641 +462.15 +704.75 +917.91 +575.57 +175.31 +231.62 +176.22 +98.136 +80.741 +111.14 +19.508 +34.909 +14.136 +30.208 +186.59 +73.34 +291.55 +276.49 +240.13 +418.12 +234.08 +607.79 +2757.4 +4920 +2799.4 +4729.3 +2626.9 +128.68 +46.913 +0.0726 +0.072401 +841.44 +646.64 +224.38 +45.655 +60.483 +67.441 +355.93 +571.9 +179.15 +58.79 +197.9 +0.13627 +0.30573 +0.11765 +0.067013 +0.018219 +0.016733 +0.057497 +0.064122 +0.13514 +0.090312 +0.066371 +4.7209 +2.5143 +943.4 +322.96 +0.23517 +30.915 +100.11 +376.11 +337.24 +723 +1056.2 +761.33 +176.87 +55.933 +104.28 +81.898 +96.379 +71.783 +21.72 +10.677 +22.403 +153.35 +63.851 +97.804 +165.95 +296.34 +496.23 +184.7 +412.73 +43.664 +5602.1 +4002.9 +1860.3 +2679.2 +59.8 +50.525 +38.697 +775.63 +572.89 +1475.9 +336.99 +115.05 +649.9 +2193 +245.61 +744.1 +191.27 +84.952 +170.41 +0.026531 +0.1137 +0.027563 +0.028579 +0.017583 +0.017441 +0.005683 +0.024632 +0.040253 +0.13334 +0.18874 +4.8316 +5.5234 +535.21 +98.258 +998.54 +653.23 +20.796 +9.0748 +360.11 +1302.8 +1828.5 +1244 +933.62 +55.069 +69.321 +40.333 +36.342 +121.36 +10.116 +15.08 +36.442 +168.15 +122.2 +124.15 +278.44 +425.85 +468.23 +154.97 +126.34 +23.184 +50.346 +3712.7 +1466 +1793.8 +1386.8 +72.252 +51.122 +178.73 +551.67 +1585.6 +331.67 +348.35 +353.49 +1277.2 +635.25 +392.83 +91.123 +96.079 +227.47 +0.006421 +0.049285 +0.044429 +0.008224 +0.047792 +0.068893 +0.017327 +0.039469 +0.08043 +0.13022 +0.082486 +5.1338 +4.1562 +16.882 +141.76 +734.8 +2930.1 +323.75 +0.52506 +21.982 +1693.4 +1727.6 +1895.2 +957.11 +1074.9 +70.258 +52.68 +45.589 +210.09 +42.13 +10.354 +19.661 +79.071 +222.31 +67.117 +218.7 +193.49 +238.43 +296.85 +85.012 +40.904 +59.337 +3410.2 +1700.5 +1296.7 +2115.4 +2930.4 +20.937 +123.49 +62.511 +141.19 +327.3 +221.18 +240.25 +612.72 +330.89 +233.97 +80.032 +61.025 +116.47 +281.4 +0.35713 +0.029346 +0.027064 +0.035857 +0.045525 +0.006328 +0.048262 +0.072376 +0.089183 +0.25604 +3.9534 +6 +84.076 +112.48 +471.24 +1950 +230.46 +226.41 +233.52 +152.13 +1310.9 +1663.7 +779.52 +758.12 +405.68 +66.272 +65.105 +85.09 +58.834 +60.204 +18.779 +234.33 +104.95 +30.056 +12.884 +330.23 +366.01 +526.89 +130.22 +41.978 +39.877 +83.094 +672.33 +1758.8 +1338.8 +2849.5 +73.871 +95.442 +131.27 +78.909 +294.33 +273.98 +396.63 +483.5 +493.7 +244.6 +137.36 +84.581 +165.83 +181.96 +0.24078 +0.047571 +0.042202 +0.11999 +0.03037 +0.009228 +0.021816 +0.030977 +0.17975 +0.24829 +7.4315 +7.293 +52.933 +6.5971 +293.88 +4863.8 +928.3 +112.59 +183.04 +21.641 +15.022 +717.13 +1614.8 +629.28 +542.28 +142.76 +73.015 +66.367 +18.333 +61.114 +41.806 +59.816 +43.447 +37.07 +16.375 +455.18 +601.62 +1983.8 +127.05 +63.564 +9.1131 +81.932 +65.859 +145.19 +665.97 +3082.9 +4975.3 +277.61 +181.54 +86.337 +81.146 +293.29 +327.72 +1073.8 +512.55 +347.1 +134.98 +157.76 +265.3 +0.054571 +0.18742 +0.082125 +0.033194 +0.081653 +0.049311 +0.058793 +0.020303 +0.067323 +0.13689 +0.20344 +13.834 +9.772 +48.885 +12.516 +16.256 +4965.6 +1659.5 +141.05 +193.06 +35.968 +34.877 +52.472 +1344.1 +493.89 +612.7 +188.02 +52.916 +39.841 +20.352 +33.753 +15.054 +41.654 +106.28 +51.689 +14.346 +536.01 +672.32 +1050.8 +98.978 +107.55 +15.315 +67.565 +25.825 +90.562 +551.62 +3907.9 +2211.4 +297.49 +141.52 +74.294 +84.463 +497.94 +321.86 +798.51 +997.35 +245.92 +207.91 +289.35 +0.067189 +0.12025 +0.11858 +0.3864 +0.10523 +0.3428 +0.18746 +0.034576 +0.089765 +0.059297 +0.10473 +0.15225 +13.86 +12.321 +31.326 +8.9195 +323.04 +134.71 +145.97 +451.24 +59.115 +55.685 +85.474 +88.555 +15.423 +555.67 +479.14 +128.05 +150.63 +41.16 +23.577 +29.607 +19.572 +39.653 +43.109 +160.17 +80.801 +224.67 +1174.8 +861.35 +152.29 +315.12 +194.56 +111.59 +30.172 +65.475 +134.45 +87.755 +1186.3 +223.71 +353.59 +128.69 +151.5 +268.89 +968.96 +1414 +744.6 +320.58 +282.53 +249.62 +0.24849 +0.29093 +0.25982 +0.99116 +0.3283 +0.11002 +0.048244 +0.043303 +0.072392 +0.17545 +0.15748 +0.36863 +23.905 +11.748 +21.218 +14.339 +882.83 +0.18589 +229.16 +67.704 +51.019 +60.503 +77.169 +186.56 +51.586 +226.58 +404.33 +171.54 +152.9 +60.561 +24.917 +57.242 +9.1754 +32.435 +40.515 +80.929 +348.09 +111.32 +215.36 +47.265 +134.04 +321.31 +58.288 +80.063 +73.861 +51.005 +122.88 +61.66 +84.99 +103.96 +163.11 +97.962 +366.93 +65.736 +1681.3 +891.47 +1001.1 +361.26 +0.066279 +1.296 +0.32493 +0.25601 +0.095479 +0.46714 +0.24702 +0.89324 +0.098013 +0.035136 +0.018783 +0.17505 +0.072354 +0.055295 +33.351 +16.96 +8.6701 +8.6353 +1357.9 +17071 +40.055 +73.379 +11.504 +60.006 +75.506 +97.137 +81.796 +176.72 +449.69 +284.16 +284.44 +64.221 +22.822 +42.988 +6.3771 +31.072 +155.39 +84.027 +343.38 +102.21 +129.57 +151.28 +89.326 +0.3188 +71.084 +105.42 +165.84 +125.81 +80.866 +98.395 +400.75 +125.72 +136.44 +81.719 +165.66 +63.942 +32.455 +527.23 +0.2479 +0.61274 +0.17505 +0.083339 +0.040549 +0.11917 +0.023824 +0.012139 +0.084957 +0.17797 +0.031481 +0.033224 +0.097474 +0.072072 +0.25574 +0.021377 +81.456 +41.589 +17.169 +15.404 +18.925 +137.16 +71.361 +64.516 +24.209 +43.195 +48.634 +196.69 +93.569 +225.12 +269.47 +95.372 +97.168 +79.84 +43.41 +64.213 +22.325 +161.14 +161.91 +112.26 +381.76 +61.769 +42.907 +56.459 +53.078 +28.73 +21.702 +67.963 +330.26 +135.12 +75.358 +329.75 +213.26 +188.26 +198.99 +64.303 +75.372 +47.043 +56.7 +0.032864 +0.29714 +1.2298 +0.13757 +0.43475 +0.17595 +0.20137 +0.32128 +0.013389 +0.067862 +0.076756 +0.0317 +0.008228 +0.026471 +0.065689 +0.084098 +0.020856 +108.99 +86.414 +21.645 +10.701 +114.78 +275.89 +59.646 +39.61 +30.829 +74.772 +1519 +233.41 +523.44 +182.64 +333.42 +103.08 +112.67 +156.47 +93.292 +161.39 +46.35 +53.415 +141.95 +93.537 +384.86 +79.639 +28.888 +48.559 +25.837 +23.973 +30.127 +25.532 +187.03 +189.41 +289.04 +406.55 +210.14 +606.31 +187.78 +47.317 +82.751 +0.23591 +0.1827 +0.036279 +0.14376 +0.18934 +0.13446 +0.16527 +0.4125 +0.46207 +0.34286 +0.021036 +0.032588 +0.12984 +0.038536 +0.014503 +0.013669 +0.071847 +0.14763 +0.14067 +90.213 +65.786 +15.323 +7.8638 +65.005 +306.02 +47.255 +681.07 +1381.9 +351.98 +609.14 +100.44 +312.94 +193.92 +265.78 +138.72 +154.29 +101.86 +70.404 +457.99 +81.21 +172.72 +137.15 +127.15 +260.87 +49.476 +44.337 +79.109 +98.754 +24.538 +17.166 +293.03 +160.9 +458.07 +274.75 +165.74 +188.53 +320.87 +140.04 +51.183 +1.2868 +0.49845 +0.069229 +0.068235 +0.023328 +0.14641 +0.55429 +0.32456 +0.11474 +0.18441 +0.037657 +0.033751 +0.046685 +0.052535 +0.43469 +0.091557 +0.053914 +0.12411 +0.26058 +0.044777 +57.603 +39.499 +18.982 +23.733 +427.31 +876.15 +463.67 +1407.7 +853.21 +730.83 +330.03 +72.821 +112.34 +173.86 +193.12 +8.4912 +8.216 +11.125 +183.18 +505.43 +13.04 +75.922 +145.12 +70.374 +165.03 +85.525 +0.03948 +0.063966 +51.063 +33.086 +16.826 +817.65 +290.85 +646.82 +213.6 +303.6 +161.68 +255.62 +0.6356 +0.17687 +0.94067 +0.55357 +0.16547 +0.062933 +0.061666 +0.011768 +0.049334 +0.10235 +0.032313 +0.18103 +0.056532 +0.17429 +0.091581 +0.16587 +0.11756 +1.0874 +0.31652 +0.22127 +0.070532 +0.033851 +57.026 +23.962 +1257.1 +1294.5 +626.19 +498.79 +287.61 +1541.1 +794.01 +508.54 +268.58 +147.68 +230.31 +75.688 +49.627 +6.2095 +217.31 +1197.9 +321.83 +191.44 +14.379 +79.972 +97.126 +136.82 +0.021514 +0.007827 +20.047 +0.053468 +41.131 +51.024 +1131.7 +902.49 +339.53 +1130.6 +302.85 +378.92 +145.17 +0.057038 +0.19252 +0.48657 +0.90054 +0.38425 +0.38058 +0.12796 +0.16751 +0.031015 +0.063999 +0.082118 +0.1279 +0.01472 +0.22981 +0.40355 +0.62896 +0.10493 +0.22375 +0.41069 +0.15286 +0.053713 +0.43361 +0.060175 +104.99 +14.189 +1179.7 +1157.6 +622.49 +753.82 +221.04 +1166.6 +955.65 +193.41 +287.64 +994.52 +114.24 +87.471 +35.783 +186.41 +359.33 +511.98 +160.38 +104.18 +32.682 +117.91 +270.65 +0.03439 +0.00761 +0.036021 +0.054414 +0.055327 +1908.1 +733.07 +902.34 +1231.9 +862.63 +832.6 +193.6 +281.07 +216.62 +0.055577 +0.055177 +0.1469 +0.11132 +0.62654 +0.35621 +0.084066 +0.12204 +0.54041 +0.026394 +0.063307 +0.01806 +0.069225 +0.21656 +0.38735 +0.16511 +0.044637 +0.14374 +0.44954 +0.40793 +0.022452 +0.022494 +0.017912 +204.88 +192.87 +219.84 +1139.2 +799.04 +585.47 +169.12 +944.73 +1292 +648 +2201.8 +532.67 +157.91 +60.103 +765.2 +288.78 +37.104 +41.414 +214.75 +68.606 +36.105 +1728.9 +0.087427 +0.091913 +0.14966 +0.24793 +0.097395 +0.15154 +1643.4 +1339 +507.75 +988.36 +14.16 +6.465 +67.495 +278.63 +608.36 +20000 +0.29726 +0.081376 +0.13631 +0.15145 +0.24469 +0.078288 +0.21849 +0.25451 +0.10246 +0.042455 +0.009998 +0.43855 +0.1858 +0.23549 +0.28397 +0.034734 +0.56939 +0.065779 +0.2423 +0.022365 +0.037905 +0.064475 +152.41 +183.65 +179.18 +484.45 +976.5 +598.33 +368.57 +687.21 +2370.9 +358.39 +1192.2 +397.32 +240.24 +136.75 +114.15 +27.8 +50.863 +42.337 +302.4 +381.22 +292.89 +3380.7 +0.4495 +0.37642 +0.47346 +0.40705 +38.559 +24.115 +7.0979 +20.524 +8.2543 +579.13 +441 +7.0297 +463.65 +149.05 +914.35 +11424 +5306.7 +0.065776 +0.083743 +0.17129 +0.12881 +0.098865 +0.099205 +0.36675 +0.076694 +0.050893 +0.10022 +0.22813 +0.19426 +0.054389 +0.052722 +0.052901 +0.15553 +0.10725 +0.16306 +0.36958 +0.23806 +0.23328 +128.38 +271.95 +268.3 +460.67 +926.67 +609.86 +576.22 +777.15 +2205.7 +845.24 +186.52 +343.57 +70.418 +87.967 +64.561 +16.164 +30.278 +3450.5 +254.44 +515.36 +466.31 +1601.7 +0.062995 +198.11 +63.856 +8.2241 +28.476 +37.953 +67.873 +38.098 +15.502 +14.066 +390.38 +9.3938 +14.959 +264.15 +330.88 +4883.9 +6483.2 +0.027342 +0.080711 +0.26539 +0.14223 +0.036764 +0.068373 +0.086826 +0.061436 +0.09274 +0.11073 +0.034654 +0.053774 +0.058785 +0.04813 +0.068237 +0.045184 +0.05324 +0.15088 +0.45824 +0.064929 +0.56958 +153.19 +474.61 +285.46 +548.46 +429.69 +752.81 +222.22 +1052.4 +1125.2 +1019.4 +301.31 +318.53 +40.414 +61.805 +47.064 +19.572 +2912 +2965.7 +1285 +1100 +368.53 +1106.3 +1524.8 +3244.8 +18.927 +11.331 +11.707 +40.729 +108.74 +25.58 +35.538 +15.585 +403.6 +79.298 +10.801 +26.854 +1.0501 +2549.3 +9614.1 +1000.4 +0.014624 +0.12442 +0.046415 +0.11215 +0.061612 +0.045251 +0.003685 +0.050648 +0.08627 +0.27103 +0.12599 +0.033378 +0.14017 +0.069181 +0.03481 +0.072204 +0.032787 +0.28272 +0.34053 +1.5226 +204.37 +3370 +959.85 +695.88 +580.35 +361.46 +701.47 +240.6 +353.84 +84.332 +196.92 +434.97 +23.003 +33.641 +27.741 +17.255 +5490.5 +5361.9 +5047.3 +1393.5 +957.77 +2251 +2576.6 +8013.5 +18.239 +16.713 +23.37 +35.998 +93.786 +47.002 +45.523 +449.01 +501.89 +17.411 +13.378 +23.224 +8.6063 +0.36344 +7010.9 +768 +1165.5 +0.20792 +0.14701 +0.096241 +0.22517 +0.070283 +0.016705 +0.040251 +0.017631 +0.13341 +0.049896 +0.25569 +0.23034 +0.12899 +0.064062 +0.034764 +0.028653 +0.25073 +0.31567 +1.0596 +345.68 +592.28 +2134.2 +1202.9 +539.47 +330.7 +409.63 +1199.2 +668.86 +124.53 +101.03 +15.569 +146.77 +32.936 +52.947 +13.684 +38.817 +5523.1 +5910.9 +558.18 +781.59 +5226 +5629.1 +7637.8 +7.106 +13.787 +34.437 +19.076 +35.607 +43.835 +56.498 +306.37 +372.91 +41.495 +21.882 +11.719 +9.6909 +0.40136 +0.1059 +841.57 +938.07 +487.94 +0.010238 +0.10553 +0.046506 +0.11898 +0.062395 +0.074887 +0.037402 +0.041439 +0.085629 +0.12357 +0.48259 +0.05641 +0.02809 +0.008891 +0.078475 +0.35253 +0.59843 +0.30841 +146.21 +95.998 +674.8 +1106.9 +441.7 +156.68 +447.74 +203.49 +320.22 +42.279 +114.12 +17.376 +116.68 +25.078 +60.922 +36.217 +45.414 +88.563 +6366.7 +491.95 +1182.1 +6178.2 +4796.2 +4481.3 +0.20407 +11.856 +21.926 +16.243 +23.729 +0.093971 +61.36 +361.93 +277.8 +46.069 +13.812 +16.442 +18.608 +4.5053 +0.034962 +0.063652 +1385.7 +386.44 +246.84 +0.14137 +0.45911 +0.34995 +0.26907 +0.36218 +0.19126 +0.1741 +0.022072 +0.16994 +0.038305 +0.050812 +0.069623 +0.006206 +0.021296 +0.292 +0.34715 +1.0713 +112.36 +43.416 +190.52 +686.82 +413.38 +220.37 +834.74 +748.82 +253.5 +57.745 +150.11 +21.212 +125.76 +36.243 +80.544 +84.903 +47.81 +51.836 +4049.5 +490.62 +194.32 +170.38 +5763.9 +4597.6 +0.90267 +0.86948 +0.81293 +0.25663 +0.2 +0.26418 +79.064 +141.85 +153.54 +35.027 +9.3936 +9.1993 +7.5821 +5.5996 +20.028 +0.044108 +0.11056 +240.89 +200.69 +123 +3.858 +3.0067 +0.40047 +0.25624 +0.61325 +0.57434 +0.35709 +0.11586 +0.034646 +0.02964 +0.068849 +0.014857 +0.005365 +0.35297 +0.50582 +1.1016 +113.23 +42.231 +111.29 +474.44 +468.83 +138.11 +277.49 +864.62 +201.23 +42.901 +62.746 +12.645 +115.77 +56.018 +53.807 +98.567 +70.706 +51.033 +24.592 +24.543 +210.43 +311.09 +80.96 +1853.7 +1440.3 +0.54587 +0.83071 +0.06988 +0.051265 +0.082991 +112.97 +320.2 +941.72 +2241.3 +19.074 +6.5456 +4.8211 +14.334 +6.48 +0.065746 +0.1132 +161.3 +61.142 +35.962 +13.512 +0.32989 +0.2049 +0.17805 +0.56547 +0.4957 +0.37138 +0.053374 +0.063802 +0.2806 +0.061452 +0.33847 +0.034291 +0.23814 +0.39771 +0.21901 +202.85 +43.508 +169.32 +52.427 +532.14 +1187.8 +233.47 +1208.8 +1634.6 +27.691 +38.937 +14.39 +7.947 +108.84 +68 +180.3 +106.66 +98.757 +25.396 +26.562 +52.594 +446.93 +75.141 +1957.7 +1161.5 +0.23214 +0.07412 +0.024165 +0.26018 +534.5 +116.63 +253.85 +190.13 +1612.9 +2283.9 +4.503 +4.6024 +10.57 +7.8631 +0.036369 +0.096908 +170.91 +53.093 +24.879 +27.583 +0.9919 +0.32218 +0.13575 +0.76685 +0.55023 +0.15789 +0.1557 +0.19741 +0.27046 +0.17342 +0.32438 +0.41117 +0.53851 +0.18219 +0.12775 +258.79 +76.91 +70.134 +83.549 +435.83 +103.45 +227.57 +1113.3 +1388 +655.59 +2554.8 +8.1038 +84.266 +232.55 +67.19 +153.73 +125.53 +431.86 +421.9 +23.984 +82.514 +49.544 +64.313 +83.672 +0.14088 +0.18529 +0.31038 +0.10529 +0.046473 +105.35 +76.261 +176.49 +137.31 +906.64 +1079.8 +287.75 +5.4632 +8.6178 +8.0025 +0.057809 +0.26716 +185.3 +35.779 +29.912 +51.068 +3.3967 +0.2249 +0.13473 +0.48103 +2.0001 +0.40828 +0.50174 +0.20536 +1.2002 +0.54592 +0.073546 +0.13058 +0.087965 +0.17538 +0.051666 +11951 +571.83 +65.441 +83.139 +100.29 +254.07 +481.44 +423.91 +313.72 +1852.2 +1201.8 +2723 +149.5 +281.99 +109.16 +119.64 +178.39 +32.871 +133.76 +202.18 +142.37 +91.291 +49.243 +67.492 +0.23922 +0.072452 +0.059104 +53.378 +81.514 +62.733 +69.171 +178.6 +78.902 +881.99 +789.59 +229.26 +345.68 +0.33845 +0.169 +0.65015 +653.95 +115.03 +40.762 +28.143 +18.116 +0.056281 +0.074211 +0.063786 +0.22665 +1.1135 +1.8627 +1.0306 +0.46698 +0.32024 +0.36744 +0.30865 +0.68378 +0.054778 +0.022752 +0.098575 +695.26 +314.55 +48.36 +116.48 +120.29 +758.04 +492.65 +387.25 +802.26 +364.69 +362.89 +2585 +1731.8 +813.71 +164.31 +118.89 +270.48 +47.187 +138.89 +257.83 +334.57 +185.02 +35.568 +65.29 +91.223 +74.021 +58.67 +89.157 +42.217 +144.56 +116.89 +382.92 +178.73 +1253.8 +413.14 +328.28 +191.12 +124.56 +66.652 +221.72 +485.79 +142.67 +22.968 +50.586 +0.065482 +0.096258 +0.07727 +0.45136 +0.7232 +0.50779 +0.35879 +1.3405 +0.9348 +0.25919 +0.31328 +0.30467 +0.11207 +0.078028 +0.092702 +0.044516 +3911.3 +117.63 +47.884 +44.938 +153.72 +631.03 +409.18 +363.28 +406.72 +1529.7 +1943.4 +752.7 +2317.6 +1037.6 +205.51 +175.65 +215.92 +410.92 +136.63 +40.846 +10.936 +0.035188 +0.037047 +94.905 +79.32 +76.547 +28.58 +97.661 +90.744 +341.78 +915.11 +463.13 +203.47 +1214.2 +187.42 +93.426 +102.97 +247.47 +122.24 +379.72 +949.23 +184.88 +34.48 +0.14067 +0.16036 +0.32147 +0.55511 +1.6732 +1.485 +0.30166 +0.35656 +0.87711 +1.5999 +1.2133 +0.071639 +0.097078 +0.062833 +0.078319 +0.11189 +0.052087 +75.47 +327.33 +810.94 +48.94 +112.36 +135.99 +564.03 +428.81 +325.42 +943.08 +1018.4 +446.23 +115.62 +1086.5 +84.748 +333.55 +335.2 +170.43 +90.889 +30.856 +18.218 +0.08446 +289.18 +35.908 +116.06 +150.16 +50.736 +87.845 +84.283 +686.2 +1359.7 +1156.3 +5158.4 +0.03407 +0.012671 +33.992 +0.16328 +0.23849 +0.10527 +0.19088 +0.14316 +0.049323 +0.25146 +0.13173 +0.05233 +0.29288 +3.2381 +1.7772 +1.2188 +0.30211 +0.45187 +0.81733 +0.95902 +0.82853 +0.13628 +0.24409 +0.073842 +0.071618 +0.091826 +0.007311 +56.215 +191.47 +864.48 +130.37 +81.244 +94.073 +450.03 +246.6 +80.84 +431.87 +546.67 +590.07 +120.21 +112.54 +123.52 +283.8 +398.25 +75.39 +81.79 +55.74 +0.080217 +0.18078 +72.451 +16.982 +90.54 +162.77 +33.063 +488.43 +174.03 +1234.7 +1039.1 +42.749 +274.46 +0.019462 +0.12007 +0.19701 +0.27779 +0.19921 +0.31658 +0.19006 +0.20798 +0.14864 +0.30309 +0.18967 +0.12345 +0.19997 +0.16787 +0.24989 +0.099583 +0.51502 +0.28993 +0.28413 +0.60542 +0.1241 +0.11731 +0.16837 +0.093039 +0.056192 +0.078605 +0.18962 +55.558 +30.342 +1549.3 +189.7 +89.231 +140.53 +480.34 +598.94 +109.5 +266.7 +378.21 +548.59 +412.09 +145.58 +94.823 +363.46 +287.54 +64.579 +48.83 +79.264 +54.063 +29.332 +41.572 +14.703 +134.29 +177.88 +41.869 +419.71 +197.37 +385.14 +1603.4 +16.175 +0.23558 +0.047942 +0.057576 +0.54416 +0.48425 +0.30715 +0.70684 +0.27651 +0.29715 +0.20019 +0.1284 +0.43112 +0.1543 +0.10444 +0.086 +0.78884 +0.31419 +0.38494 +0.57546 +5.5527 +0.67306 +0.28949 +0.032038 +0.25226 +0.12284 +0.093856 +0.12448 +0.37224 +132.87 +61.206 +1156.4 +232.62 +124.87 +109.49 +347.17 +358.27 +209.4 +177.35 +436.02 +421.17 +378.35 +402.46 +346.72 +180.53 +83.654 +64.524 +78.777 +229.11 +72.587 +29.299 +38.82 +179.89 +221.37 +407.22 +3216.7 +3847.9 +73.903 +30.069 +69.121 +20.66 +0.31024 +2.3437 +0.28557 +0.2806 +0.52248 +0.55234 +1.6657 +0.10042 +0.20653 +0.44536 +0.2626 +0.12362 +0.021098 +0.009823 +0.066443 +0.15849 +0.035409 +0.020897 +0.38456 +1.5403 +1.7864 +0.92947 +0.1211 +0.18169 +0.03437 +0.068512 +0.0726 +0.063071 +127.7 +102.22 +41.982 +143.75 +132.75 +75.615 +202.33 +306.12 +238.7 +208.67 +423.31 +827.72 +818.41 +633.15 +892.4 +165.11 +94.909 +106.2 +179.32 +471.13 +53.886 +104.46 +30.052 +303.97 +175.25 +384.58 +83.087 +3380.1 +62.574 +46.787 +130.47 +1.6314 +1.4338 +0.68098 +0.23397 +0.28988 +0.36032 +0.12572 +0.55654 +0.33438 +0.086464 +0.14357 +0.088183 +0.030601 +0.01347 +0.030183 +0.068391 +0.06299 +0.16731 +0.11754 +0.19204 +0.10179 +0.48884 +0.83021 +0.15179 +0.11309 +0.15335 +0.051284 +0.11109 +0.26902 +130.47 +111.1 +39.982 +324.16 +212.63 +80.125 +92.203 +198.71 +146.07 +139.22 +61.682 +2072.5 +1101.5 +1160.8 +2828.3 +2712.6 +144.74 +197.01 +317.23 +254.66 +614.69 +46.991 +276.81 +240.28 +421.74 +174.91 +123.19 +47.067 +30.73 +27.222 +0.79767 +0.93031 +0.6527 +0.18686 +0.57061 +0.16706 +0.39984 +0.35152 +0.18556 +0.26583 +0.35237 +0.091806 +0.032438 +0.030631 +0.025176 +0.026231 +0.24591 +1.3939 +0.51838 +0.32738 +0.16568 +0.097878 +0.25571 +0.86376 +0.17641 +0.033889 +0.014991 +0.026878 +0.087333 +0.16469 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/layer84_permy.geos b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/layer84_permy.geos new file mode 100644 index 00000000000..d83867f1511 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/layer84_permy.geos @@ -0,0 +1,13200 @@ +0.064542 +0.034083 +0.033865 +12.584 +25.506 +49.557 +110.05 +3.1658 +1864.7 +554.89 +778.92 +166.98 +1152.9 +430.23 +940.06 +345.37 +229.37 +390.37 +744.79 +110.79 +189.92 +61.175 +45.341 +299.3 +268.93 +51.619 +25.666 +116.14 +0.10857 +0.30584 +0.11793 +0.097815 +0.18215 +0.13971 +0.091116 +0.046364 +0.10297 +0.079578 +0.013536 +0.03645 +0.10576 +0.45575 +0.19143 +0.081675 +521.47 +588.83 +425.18 +60.599 +71.636 +285.38 +361.31 +17.056 +47.555 +148.49 +65.429 +34.797 +111.85 +136.38 +98.327 +169.98 +0.11286 +0.10634 +0.081667 +0.052393 +32.541 +36.477 +166.46 +2237.7 +678.13 +492.44 +793.61 +285.87 +1633.4 +676.45 +371.46 +426.83 +379.78 +369.9 +288.81 +69.299 +67.002 +25.327 +39.998 +379.97 +257.87 +65.124 +28.595 +98.913 +0.28881 +0.33028 +0.25872 +0.1233 +0.048856 +0.22513 +0.37565 +0.026637 +0.059152 +0.034875 +0.01443 +0.019086 +0.11767 +0.099196 +0.07389 +0.034775 +432.54 +324 +52.078 +142.62 +195.34 +231.22 +246.73 +317.3 +61.988 +65.189 +258.83 +34.475 +138.53 +276.58 +166.55 +293.29 +0.065883 +0.097745 +0.20938 +0.79875 +0.49302 +0.23443 +44.765 +200.05 +608.83 +190.16 +566.79 +230.07 +998.9 +648.59 +145.2 +617.66 +574.48 +340.95 +139.57 +73.181 +85.964 +22.285 +47.058 +120.34 +235.96 +27.214 +24.529 +70.772 +0.63261 +0.18382 +0.19455 +0.12733 +0.086306 +0.15792 +0.23827 +0.38131 +0.15722 +0.24469 +0.043473 +0.12284 +0.25926 +0.087617 +0.036858 +0.055697 +246.6 +376.72 +87.035 +252.94 +338.94 +141.44 +308.2 +237.84 +47.03 +90.055 +141.26 +38.305 +423.1 +231.6 +144.91 +193.52 +0.19582 +0.029963 +0.16623 +0.18874 +0.63653 +0.13589 +0.46928 +0.069859 +84.093 +297.66 +709.97 +332.23 +1179.3 +960.02 +99.835 +679.55 +690.79 +230.29 +64.782 +74.962 +63.969 +29.326 +31.055 +62.858 +78.211 +49.509 +27.538 +52.3 +0.14683 +0.073425 +0.079791 +0.23118 +0.15686 +0.37766 +0.23192 +0.18254 +0.13246 +0.36985 +0.28115 +0.45961 +0.2039 +0.14442 +0.12089 +0.035193 +51.816 +279.09 +98.52 +165.48 +205.67 +84.122 +126.41 +144.61 +141.12 +84.454 +98.735 +29.543 +30.702 +32.005 +64.901 +190.82 +0.24328 +0.045128 +0.27136 +0.17964 +0.28686 +0.31372 +0.10344 +0.027707 +65.548 +192.02 +1056.6 +451.14 +568.55 +884.24 +143.95 +218.63 +354.26 +223.68 +182.13 +73.648 +12.494 +23.241 +24.469 +120.55 +87.03 +59.859 +63.365 +57.563 +205.47 +0.10258 +0.036084 +0.22701 +0.34276 +0.15466 +0.037823 +0.042638 +0.41338 +0.31336 +1.0557 +0.074098 +0.12464 +0.063393 +0.15806 +0.071952 +0.1078 +161.37 +108.25 +289.25 +122.91 +205.05 +483.29 +86.51 +38.502 +49.36 +34.694 +21.44 +222.37 +340.5 +35.465 +382.73 +0.17405 +0.24344 +0.21956 +0.11204 +0.50225 +0.40387 +0.13347 +44.621 +49.595 +205.14 +110.97 +231.59 +598.07 +241.89 +127.55 +257.68 +301.45 +264.14 +205.78 +945.86 +406.89 +33.532 +88.773 +139.35 +43.266 +31.504 +50.983 +70.095 +116.72 +0.012884 +0.021406 +0.11139 +0.13991 +0.23014 +0.083808 +0.14631 +0.4154 +0.39946 +0.58834 +0.10903 +0.023152 +0.062313 +0.44326 +0.042737 +0.11187 +0.20606 +833.41 +200.2 +185.46 +139.76 +433.92 +115.96 +43.992 +58.488 +38.38 +15.999 +142.26 +272.44 +125.73 +374.02 +0.36356 +0.23023 +0.34597 +0.57646 +0.69528 +0.18271 +12.786 +22.28 +72.075 +293.26 +69.144 +144.89 +185.07 +65.641 +227.53 +69.682 +112.23 +163.93 +110.52 +557.42 +414.41 +44.922 +90.015 +218.6 +32.666 +31.722 +28.023 +82.649 +82.841 +0.2781 +0.15826 +0.2424 +0.26436 +0.079702 +0.068927 +0.1803 +0.22496 +0.30583 +0.92788 +0.13457 +0.011549 +0.072593 +0.26906 +0.1108 +1005.4 +403.63 +357.54 +179.15 +227.94 +169.22 +248.56 +256.55 +135.76 +46.386 +87.288 +80.658 +268.25 +110.56 +70.52 +354.73 +0.17062 +0.19122 +1.4683 +0.28591 +1.1344 +0.61433 +14.97 +31.062 +70.954 +232.54 +179.12 +120.54 +133.6 +89.496 +52.812 +379.81 +200.82 +100.85 +75.243 +157.67 +347.75 +206.1 +229.32 +114.01 +20.654 +33.827 +40.613 +76.305 +22.376 +63.505 +0.11355 +0.14114 +0.011373 +0.057265 +0.20586 +0.21325 +0.055662 +0.093884 +0.14534 +0.048081 +0.041314 +0.046246 +0.03562 +760.16 +1217 +745.93 +795.84 +99.913 +204.06 +123.77 +253.1 +204.19 +152.04 +138.02 +84.878 +82.619 +104.82 +76.898 +59.541 +152.44 +0.29373 +0.13717 +0.29431 +4.3611 +0.32076 +0.83081 +27.533 +64.722 +31.243 +177.8 +211.94 +158.24 +69.265 +56.738 +307.65 +339.36 +257.26 +60.568 +76.742 +169.22 +444.62 +208.19 +372.92 +89.071 +34.606 +36.319 +27.375 +106.42 +24.527 +75.613 +2362.9 +0.072295 +0.033354 +0.018601 +0.089319 +0.086002 +0.066354 +0.17864 +0.32434 +0.066334 +0.061923 +0.1465 +0.20517 +459.33 +444.1 +699.99 +768.6 +99.921 +170.93 +233.83 +1389.3 +377.83 +235.73 +251.35 +104.14 +64.791 +76.809 +0.16251 +0.24275 +0.030701 +0.45119 +0.20232 +0.5466 +0.65022 +0.55413 +0.10716 +46.39 +83.23 +37.374 +213.88 +51.885 +22.977 +74.532 +168.72 +187.73 +234.98 +232.28 +30.974 +294.42 +566.89 +529.52 +245.32 +313.32 +257.05 +385.16 +157.47 +129.16 +135.72 +27.896 +78.059 +3242.2 +975.66 +0.072112 +0.029737 +0.06779 +0.035362 +0.083346 +0.22955 +0.071457 +0.12459 +0.11444 +3172.4 +278.98 +589.88 +584.53 +403.27 +750.9 +217.59 +194.54 +164.41 +467.93 +1360.8 +290.77 +253.07 +355.59 +196.4 +326.85 +0.14956 +0.11366 +0.15315 +0.37969 +0.23949 +0.10672 +0.079027 +0.080941 +0.064121 +72.658 +43.561 +50.816 +137.24 +25.553 +16.117 +53.033 +347.26 +201.64 +299.23 +176.54 +33.877 +462.13 +136.41 +112.91 +138.66 +221.94 +188.74 +803.49 +116.76 +912.63 +127.61 +125.75 +166.11 +101.56 +911.79 +186.47 +0.08453 +0.039313 +0.049767 +0.40395 +0.10691 +0.016847 +161.96 +577.41 +2099.7 +241.99 +319.12 +2261.6 +2442.1 +209.19 +146.51 +159.46 +348.49 +263.67 +462.89 +129.9 +107.08 +133.09 +711.3 +275.4 +0.055833 +0.14019 +0.06268 +0.20509 +0.2143 +0.25294 +0.52994 +0.079145 +0.090655 +47.828 +26.751 +31.94 +55.881 +172.71 +31.025 +83.53 +472.45 +473.52 +180.58 +68.023 +18.186 +513.8 +87.376 +62.507 +172.49 +268.2 +211.04 +371.53 +41.53 +79.049 +533.62 +218.18 +33.722 +149.07 +76.799 +505.42 +0.028038 +0.12757 +0.098478 +0.40759 +0.23775 +352.3 +361.97 +507.75 +1063 +463.21 +934.6 +1800.2 +2441.5 +161.96 +71.926 +129.75 +276.79 +752.58 +373.23 +55.897 +222.43 +267.63 +855 +547.59 +754.28 +0.12624 +0.056341 +0.091799 +0.18029 +0.54194 +0.17822 +0.24298 +0.22995 +115.58 +55.764 +51.966 +60.55 +83.883 +40.962 +111.47 +437.03 +625.37 +60.861 +110.38 +35.098 +344.29 +228.48 +232.04 +284.52 +453.57 +223.13 +454.08 +79.732 +78.156 +327.48 +269.76 +928.72 +373.5 +51.307 +107.01 +0.027685 +0.049666 +0.1022 +0.21973 +60.967 +291.13 +482.85 +889.98 +1986.5 +279.88 +2971.5 +1887.5 +1686.1 +177.06 +246 +239.78 +133.89 +475.95 +498.08 +73.064 +150.48 +197.38 +1038 +828.51 +0.054693 +0.027247 +0.042157 +0.034732 +0.01816 +0.1158 +0.22036 +0.023251 +0.041459 +224.57 +76.117 +70.432 +230.56 +57.266 +57.341 +263.94 +298.04 +535.68 +44.06 +238 +335.79 +115.85 +1013.3 +547.52 +490.85 +748.42 +196.51 +235.21 +38.992 +174.13 +614.47 +508.34 +1093.2 +207.76 +76.966 +2303.5 +6468.3 +3378 +3568.4 +232.79 +102.71 +154.52 +296.64 +666.62 +0.044901 +0.033646 +0.074568 +1040.8 +1456 +484.49 +372.73 +165.15 +117.14 +69.967 +328.01 +411.26 +271.49 +2909.1 +1338.5 +0.10492 +0.09618 +0.17501 +0.042574 +0.045451 +0.032037 +0.064184 +0.13178 +0.045783 +0.1872 +380.62 +112.71 +86.495 +250.1 +79.037 +90.322 +220.58 +328.97 +146.02 +33.509 +428.75 +129.38 +131.41 +141.74 +518.04 +652.16 +824.41 +224.94 +455.9 +903.34 +368.35 +741.47 +394.17 +825.35 +719.21 +126.73 +53.909 +1682.2 +3920.8 +5337.6 +7227.1 +63.056 +196.31 +207.31 +0.018731 +0.081244 +0.03119 +0.034039 +1053 +1256.4 +457.57 +714.14 +210.8 +436.48 +71.696 +183.29 +303.12 +691.12 +467.88 +0.043608 +0.057146 +0.34246 +0.13845 +0.050325 +0.10604 +0.022569 +0.10474 +0.17147 +0.26691 +0.66749 +375.88 +96.477 +186.03 +255.69 +93.254 +55.775 +109.36 +129.54 +117.51 +30.112 +702.12 +153.61 +217.21 +2400.3 +390.82 +528.63 +678.78 +169.76 +902.57 +786.16 +583.42 +1555.4 +273.07 +796.46 +692.55 +157.24 +64.409 +693.8 +1953.5 +4344.9 +4908.8 +6861.6 +115.13 +196.53 +0.010065 +0.005226 +0.015142 +0.044592 +841.66 +701.51 +569.97 +1404.1 +420 +945.03 +91.569 +372.7 +479.58 +867.86 +0.14671 +0.022754 +0.058072 +0.25578 +0.373 +0.12615 +0.10488 +0.040757 +0.038922 +0.1141 +1.5126 +5.2666 +0.50732 +1.732 +57.488 +162.49 +111.95 +109.48 +146.69 +203.31 +60.671 +24.116 +83.11 +271.01 +83.895 +1165.8 +506.66 +704.71 +537.11 +226.38 +486.78 +850.98 +792.5 +221.86 +97.752 +287.8 +506.4 +259.7 +63.291 +259.46 +281.67 +4594.3 +2977.5 +5929.5 +154.72 +0.18093 +0.023153 +0.013063 +0.062635 +1468.4 +93.999 +988.36 +1146.2 +1007.5 +631.03 +1563.5 +555.79 +373.58 +897.79 +510.13 +1.5394 +0.071805 +0.41543 +0.22775 +0.16103 +0.14905 +0.3836 +0.059474 +0.068608 +0.37691 +0.56713 +4.4797 +0.21818 +0.065353 +45.733 +83.197 +154.54 +98.953 +44.568 +100.51 +36.408 +38.667 +107.35 +26.764 +36.915 +691.38 +423.64 +503.46 +211.26 +398.14 +109.26 +933.74 +664.61 +245.23 +97.1 +911.37 +794.12 +234.75 +101.76 +94.315 +292.58 +825.85 +2257.3 +1809.7 +65.881 +1.2157 +0.20489 +0.041237 +0.055386 +0.22325 +252.36 +123.01 +3059.1 +383.73 +219.59 +460.94 +1039.4 +352.3 +127.91 +0.057797 +0.60867 +0.15544 +0.21043 +0.25787 +0.2688 +0.20647 +0.5459 +0.072486 +0.041144 +0.061576 +0.37612 +0.22198 +0.061339 +0.018407 +77.257 +137.34 +199.79 +93.143 +69.812 +97.414 +41.885 +30.648 +41.72 +51.445 +670.2 +421.82 +327.57 +761.36 +250.34 +271.42 +128.38 +230.9 +86.811 +177.7 +0.046207 +1417.1 +447.81 +359.22 +225.09 +85.249 +398.68 +1450.6 +1573.5 +3203.5 +2303.9 +0.085812 +0.12855 +0.058119 +0.058183 +82.827 +338.13 +24.439 +351.91 +600.56 +371.71 +288.02 +777.4 +126.96 +135.74 +748.38 +0.28827 +0.92401 +0.099892 +0.063414 +0.047237 +0.23694 +0.1953 +0.016815 +0.062956 +0.10603 +0.20299 +0.068023 +0.015586 +0.079782 +0.069472 +70.9 +168.8 +83.003 +66.23 +89.389 +39.068 +11.904 +33.453 +148.55 +689.3 +510.42 +255.16 +396.9 +233.01 +234.7 +148.23 +192.56 +132.09 +377.94 +20000 +641.09 +535.18 +422.13 +203.7 +103.14 +164.08 +384.23 +3595.2 +3326.6 +0.43644 +0.87682 +0.21329 +216.08 +67.867 +88.226 +332.5 +40.323 +75.919 +571.44 +681.47 +703.88 +751.92 +96.307 +55.034 +817.01 +857.88 +1.8641 +0.30399 +0.023181 +0.095362 +0.085263 +0.02839 +0.069068 +0.045199 +0.077594 +0.14852 +0.08044 +0.045626 +0.029042 +0.062378 +38.99 +97.05 +125.67 +129.75 +182.08 +45.691 +58.096 +471.37 +87.832 +407.89 +519.4 +270.96 +490.63 +379.78 +260.58 +235.88 +4558.9 +101.19 +220.15 +20000 +183.09 +491.78 +784.9 +192.65 +266.35 +321.63 +260.47 +3947.8 +0.15472 +0.1247 +0.086955 +0.15396 +17.211 +197.68 +92.417 +434.23 +30.135 +188.99 +381.47 +3151.1 +1147.3 +222.12 +171.38 +7.9534 +559.02 +608.7 +281.97 +0.22344 +0.082356 +0.052349 +0.04474 +0.006468 +0.085523 +0.055831 +0.16622 +0.071888 +0.051486 +0.010634 +0.10723 +94.868 +34.1 +112.63 +81.7 +125.74 +102.26 +30.577 +327.97 +341.43 +87.525 +262.53 +432.91 +77.231 +391.52 +312.13 +246.19 +3986.3 +3196.6 +391.99 +250 +217.76 +199.5 +1131.3 +322.69 +290.15 +257.5 +376.57 +0.32552 +0.20756 +0.41813 +0.46419 +0.42621 +10.378 +15.666 +43.303 +927.56 +735.71 +103.51 +149.84 +381.74 +2065.3 +108.7 +155.15 +74.238 +9.7458 +564.77 +739.74 +318.89 +254.18 +0.05016 +0.15938 +0.44953 +0.64601 +0.021304 +0.046599 +0.037551 +0.050755 +0.049153 +670.11 +313.38 +202.78 +25.986 +138.02 +74.498 +167.35 +896.58 +477.79 +617.6 +187.95 +76.598 +386.53 +705.47 +172.13 +444.19 +508.81 +1394.4 +2491.8 +140.81 +363.63 +1131.9 +402.83 +125.62 +989.79 +768.08 +217.83 +93.863 +0.073146 +0.1392 +0.066525 +0.064315 +0.086 +0.062137 +11.013 +11.121 +89.624 +505.35 +227.03 +59.997 +179.86 +623.13 +167.34 +145.28 +106.3 +183.74 +23.414 +353.03 +346.34 +118.33 +0.38988 +0.048508 +0.14228 +0.059671 +0.058192 +0.15036 +0.42229 +0.22523 +0.10655 +0.17156 +629.91 +505.61 +227.95 +55.159 +147.97 +85.203 +1598 +1243.7 +1036.3 +168.31 +141.9 +180.92 +582.24 +442.22 +261.19 +309.28 +5384.5 +0.29577 +148.73 +99.551 +213.17 +735.85 +767.04 +157.13 +49.371 +999.46 +467.36 +0.15842 +0.031487 +0.040931 +0.20878 +0.15259 +0.33171 +11.363 +8.2247 +6.9178 +208.51 +238.45 +246.52 +124.96 +57.279 +103.69 +133.34 +154.73 +198.42 +606.44 +49.994 +543.56 +310.61 +254.47 +0.094992 +0.086519 +0.12653 +0.068546 +0.09167 +0.047976 +0.080055 +0.18503 +0.065935 +436.44 +383.64 +177.41 +189.57 +89.964 +289.68 +975.21 +341 +109.23 +51.145 +165.32 +79.5 +220.37 +1144.4 +564.87 +6233.4 +326.03 +258.97 +80.484 +104.37 +70.665 +172.14 +607.39 +1315.4 +2035.7 +411.98 +953.81 +0.037991 +0.056282 +0.039962 +0.059559 +0.1805 +0.27062 +1.4387 +4.6608 +138.79 +113.75 +10.047 +15.914 +60.87 +56.757 +23.284 +144.9 +133.17 +242 +76.539 +366.93 +67.01 +439.08 +601.39 +292.76 +1679.2 +0.20646 +0.090226 +0.051762 +0.16651 +0.063797 +0.03858 +0.053665 +0.053837 +342.42 +357.26 +0.14388 +207.49 +364.89 +243.9 +677.55 +177.9 +172.02 +39.464 +144.03 +163.96 +106.44 +9344.4 +7339.1 +134.06 +283.62 +697.86 +107.66 +112.39 +175.22 +626.53 +0.13755 +992.8 +1401 +411.5 +847.72 +1832.8 +0.26055 +0.37582 +0.081309 +0.17563 +0.12407 +625.01 +1241.6 +80.451 +17.904 +18.647 +6.8496 +2.6433 +84.082 +46.953 +144.48 +145.76 +229.34 +112.21 +175.66 +133.41 +493.73 +777.01 +438.79 +2223.4 +0.24289 +0.090909 +0.054286 +0.035886 +0.042054 +0.017021 +0.036003 +0.033485 +0.056762 +714.37 +112.05 +302.28 +827.07 +292.39 +458.93 +363.44 +172.85 +108.84 +252.63 +234.15 +12024 +102.83 +134.89 +254.97 +507.3 +693.86 +234.78 +224.19 +0.21142 +0.15445 +0.069956 +494.82 +610.78 +622.52 +1029.1 +1772.1 +301.51 +0.18088 +0.12615 +0.083816 +332.2 +0.045379 +0.018357 +0.024315 +14.364 +14.716 +7.4866 +58.744 +77.545 +79.97 +223.5 +171.29 +236.06 +163.15 +255.84 +516.74 +0.011899 +717.16 +296.42 +2101.7 +733.89 +0.012212 +0.024235 +0.027301 +0.02557 +0.010744 +0.024276 +0.04748 +94.542 +80.874 +99.301 +307.32 +868.22 +682.78 +437.97 +482.38 +372.26 +307.69 +36.34 +155.75 +81.583 +127.78 +106.65 +101.24 +424.24 +433.57 +202.87 +0.13553 +0.020352 +0.054023 +0.037423 +0.023142 +372.85 +519 +526.58 +834.26 +298.72 +90.51 +597.77 +1087.5 +0.026311 +0.032221 +0.067858 +0.037855 +0.067948 +0.059987 +104.08 +95.129 +147.7 +143.52 +323.02 +148.59 +487.15 +596.4 +863.81 +937.84 +355.45 +198.74 +179.55 +2036.5 +0.017805 +0.027843 +0.037913 +0.039088 +0.02631 +0.022821 +235.55 +117.99 +43.88 +90.053 +129.31 +249.62 +1078.8 +1344 +496.9 +430.09 +374.78 +29.099 +94.298 +143.63 +162.17 +142.08 +71.208 +92.798 +222.48 +2987.3 +0.04223 +0.023116 +0.16845 +0.029541 +0.043063 +988.46 +276.95 +668.82 +306.4 +721.62 +381.79 +817.32 +2100 +7.8004 +0.029002 +0.063596 +0.032126 +164.94 +166.56 +162.23 +144.35 +91.474 +103.39 +87.628 +244.26 +319.17 +553.78 +654.83 +461.8 +511.82 +208.13 +340.31 +392 +786.86 +0.036235 +0.080712 +0.089838 +0.16975 +0.051504 +227.24 +147.28 +82.719 +23.627 +46.817 +132.27 +188.31 +860.68 +575.89 +288.7 +763.1 +73.746 +116.37 +96.039 +164.91 +73.634 +144.24 +70.428 +70.998 +3815.2 +2041.4 +0.13388 +0.13954 +0.13916 +0.023716 +0.019203 +921.26 +287.58 +790.68 +1085 +998.12 +371.65 +545.76 +1367.7 +11.845 +0.011215 +5747.8 +10258 +841.05 +117.53 +153.13 +169.41 +120.66 +144.86 +285.1 +289.18 +130.82 +217.66 +205.8 +288.47 +432.23 +181.83 +251.83 +1077.2 +736.78 +0.32814 +0.064353 +0.18512 +0.041463 +120.27 +190.09 +106.56 +93.094 +25.747 +79.519 +192.22 +230.07 +1161.7 +550.42 +341.85 +177.41 +134.28 +177.31 +105.5 +164.13 +120.76 +59.415 +40.681 +45.245 +2568.5 +3029.3 +4473 +8542.1 +0.022298 +0.035673 +0.035346 +977.49 +394.62 +913.86 +646.09 +2371.4 +297.66 +279.83 +977.18 +124.68 +0.031991 +4585.1 +9669.5 +970.54 +171.93 +84.455 +211.19 +1630 +2793 +465.26 +144.91 +148.96 +147.98 +133.03 +416.29 +324.25 +118.46 +236.1 +1085.5 +790.89 +0.3891 +0.13582 +0.083521 +0.044139 +100.48 +89.16 +120.24 +87.716 +73.05 +68.88 +144.98 +387.36 +938.04 +528.41 +1160 +458.76 +175.31 +148.55 +59.324 +170.47 +178.92 +48.419 +70.68 +4090.7 +5340.3 +3119.6 +6201.5 +8242.8 +16749 +12469 +102.8 +660.59 +217.71 +879.71 +649.42 +2004.5 +212.34 +288.94 +225.95 +308.23 +562.39 +5784.4 +5212.6 +351 +125.83 +75.04 +476.05 +0.054004 +619.38 +227.82 +191.05 +71.829 +204.96 +161.22 +178.01 +193.32 +163.02 +433.27 +1454.6 +754.13 +271.06 +0.019848 +0.11036 +0.047296 +106.88 +95.278 +95.915 +111.79 +50.32 +153.07 +200.04 +365.17 +1101.2 +729.67 +1837.1 +0.02878 +195.7 +202.86 +72.614 +212.57 +189.85 +51.696 +176.23 +150.16 +6093.7 +3746.3 +4104.9 +18194 +33.859 +83.221 +62.64 +272.86 +306.46 +910.8 +624.76 +1693.9 +175.95 +291.47 +156.22 +514.46 +696.38 +345.06 +4924.7 +730.5 +211.28 +210.53 +895.53 +0.10021 +18.802 +183.56 +236.6 +65.828 +161.85 +79.685 +318.64 +453.92 +841.64 +805.6 +1730.2 +751.39 +190.02 +0.048484 +0.050683 +0.038711 +244.93 +180.15 +90.256 +106.18 +51.704 +591.79 +180.03 +479.85 +496.25 +1132.1 +1525 +46.547 +156.02 +224.87 +129.04 +391.41 +260.57 +53.318 +82.291 +19.442 +66.122 +4506.7 +271.49 +105.16 +60.001 +155.7 +91.994 +244.82 +966.31 +514.52 +338.86 +1287.5 +104.38 +271.78 +281.53 +894.33 +757.46 +334.09 +5967 +1082.9 +256.95 +157.1 +1930.3 +0.16706 +0.23357 +20.546 +135.89 +57.231 +71.034 +63.959 +268.83 +538.06 +364.27 +1327.3 +577.67 +453.41 +471.46 +0.032577 +0.096693 +0.030402 +0.094 +0.074792 +78.624 +65.998 +39.28 +306.65 +344.83 +510.79 +772.37 +694.05 +0.03337 +69.284 +270.64 +290.06 +142.75 +261.81 +144.63 +35.737 +83.141 +27.761 +1207.6 +538.28 +198.34 +222.84 +161.79 +336.02 +119.24 +226.28 +747.55 +1313.5 +339.85 +831.74 +102.72 +0.18271 +0.088591 +369.18 +764.11 +302.49 +30.472 +2402.1 +432.65 +316.17 +2418.3 +0.35435 +33.611 +32.474 +98.578 +117.95 +91.226 +102.23 +233.26 +279.37 +279.32 +280.64 +370.97 +731.11 +595.38 +889.63 +0.36594 +0.019786 +0.10423 +0.040005 +32.878 +117.14 +73.209 +232.31 +252.47 +651 +183.84 +0.10801 +27.506 +188.62 +509.14 +266.7 +168.45 +172.56 +109.56 +55.617 +252.76 +607.03 +865.22 +472.78 +268.46 +632.95 +328.74 +331.95 +83.728 +261.86 +661.03 +1607.8 +329.39 +0.39644 +0.43631 +0.39884 +0.37352 +44.636 +260.62 +246.54 +541.03 +128.29 +3362.3 +602.47 +2247.1 +2084.1 +19.81 +32.902 +110.82 +289.74 +271.99 +370.5 +156.57 +148.43 +271.8 +246.04 +308.34 +513.93 +437.25 +722.29 +0.055349 +0.064215 +0.060211 +35.199 +43.349 +82.321 +116.22 +259.09 +300.14 +914.46 +0.051738 +0.04402 +845.58 +114.58 +867.06 +171.51 +100.07 +45.13 +49.633 +600.8 +400.96 +1189.2 +438.15 +333.41 +334.24 +506.34 +1009.4 +329.67 +193.95 +650.63 +20000 +9786.2 +14168 +0.38846 +0.26615 +0.15357 +0.16432 +0.22051 +284.96 +503.52 +226.77 +172.01 +21.474 +285.29 +2905.1 +2362.1 +1942.4 +83.699 +73.349 +222.87 +209.62 +370.26 +269.28 +1046.7 +189.19 +151.17 +400.13 +284.85 +1056.1 +353.95 +0.055006 +0.037158 +0.058991 +53.239 +74.838 +61.747 +135.69 +136.02 +768.77 +653.57 +1313.4 +1847.1 +958.28 +44.354 +273.64 +80.772 +66.911 +66.443 +15.835 +310.34 +831.23 +874.79 +260.78 +201.9 +514.62 +357.33 +921.11 +20000 +20000 +20000 +20000 +333.48 +401.43 +404.68 +255.02 +0.080324 +0.13234 +0.13573 +0.068013 +140.55 +115.24 +186.85 +25.299 +20.742 +4288.7 +2670.6 +1431.7 +2539.6 +1994.2 +163.74 +126.74 +399.95 +995.58 +896.65 +446.85 +108.79 +239.23 +284.56 +511.5 +543.92 +0.45725 +0.092232 +230.78 +142.68 +65.559 +185.2 +158.98 +306.39 +1413.1 +0.07376 +0.090521 +0.16032 +1730.2 +37.544 +178.01 +141.25 +115.97 +51.94 +15.798 +542.98 +640.16 +1060 +245.69 +0.32582 +0.32508 +0.15372 +20000 +13832 +16616 +20000 +20000 +17596 +1783.3 +563.1 +180.11 +696.35 +0.059353 +159.76 +75.456 +118.69 +258.25 +1071 +129.54 +100.61 +9.3211 +1943.4 +2179.4 +2620 +1787.8 +154.85 +104.89 +45.203 +277.6 +885.44 +383.8 +79.739 +94.45 +904.37 +651.6 +0.067856 +1.7106 +0.041091 +170.08 +53.609 +83.895 +228.6 +157 +445.71 +1656.3 +215.4 +214.53 +323.24 +263.59 +722.11 +1039.8 +128.05 +172.71 +35.944 +11.673 +384.68 +0.054976 +0.056484 +0.54125 +0.3867 +0.40171 +0.29226 +20000 +20000 +8921.1 +20000 +20000 +12660 +6466.7 +1395.4 +147.94 +356.31 +0.05831 +0.24296 +86.243 +153.72 +331.3 +674.56 +551.37 +132.56 +13.224 +9.2287 +1452 +1480.5 +1856.3 +2736.7 +924.97 +42.436 +61.555 +114.05 +89.524 +156.76 +59.733 +584.63 +384.05 +0.092109 +0.22831 +0.29556 +109.33 +107.95 +123.46 +112.61 +120.59 +422.5 +2442.1 +3099.1 +307.89 +538.93 +460.33 +408.81 +2071.4 +4612.8 +225.9 +28.076 +17.87 +11.689 +9.242 +0.25543 +0.26083 +0.18224 +0.56139 +15142 +20000 +20000 +10371 +20000 +20000 +49.477 +36.952 +1063.7 +202.47 +196.9 +0.21012 +0.097823 +64.417 +174.78 +533.15 +413.96 +11.479 +68.185 +43.638 +13.485 +10.291 +1656.3 +1165.1 +2048.9 +102.33 +68.549 +71.977 +238.51 +103.31 +101.99 +48.875 +43.378 +0.13187 +0.046404 +0.16419 +0.64175 +0.29613 +49.225 +195.35 +288.27 +177.93 +207.91 +1662.8 +2651.5 +219.76 +498.8 +594.19 +527.32 +2374.4 +3434.4 +262.9 +49.239 +15.312 +9.3444 +5.436 +0.076231 +0.017327 +0.36808 +20000 +13640 +20000 +20000 +9387.2 +20000 +64.693 +36.159 +23.757 +771.4 +0.081627 +0.033605 +0.031971 +89.904 +79.553 +127.75 +395.49 +11.296 +43.573 +91.118 +47.1 +77.163 +17.461 +63.621 +180.78 +2007.6 +181.5 +145.37 +35.083 +170.21 +95.539 +60.156 +41.245 +23.391 +69.86 +0.307 +0.077237 +0.53307 +0.58566 +0.23657 +77.484 +112.25 +930.2 +143.83 +1019.6 +2324.4 +362.98 +243.42 +419.78 +1374 +5187.8 +3194.1 +398.6 +47.299 +9.0425 +13.18 +4.9446 +0.11462 +0.07608 +0.11186 +20000 +20000 +20000 +13096 +4292.8 +20000 +20.069 +25.817 +46.058 +38.489 +0.047873 +0.038792 +0.20183 +0.60446 +0.067169 +0.18499 +0.084948 +12.808 +60.674 +79.399 +53.937 +20.307 +20.734 +92.872 +180.4 +980.75 +299.44 +113.78 +25.021 +41.784 +65.546 +64.539 +55.268 +32.824 +59.059 +75.303 +0.20485 +0.30454 +0.80804 +0.30306 +0.21426 +272.83 +488.85 +639.85 +1251 +1381.8 +756.77 +224.57 +542.77 +2310.6 +4436 +251.9 +57.621 +0.12822 +22.411 +4.2519 +6.105 +34.843 +6.9776 +0.60394 +20000 +19465 +17455 +4239.9 +4172.6 +16588 +65.404 +32.694 +65.236 +78.405 +0.036713 +0.19119 +0.31752 +0.56851 +0.039968 +0.029245 +30.799 +26.298 +227.98 +129.25 +61.616 +26.855 +33.661 +93.855 +116.68 +700.72 +213.94 +126.5 +25.579 +84.178 +49.549 +8.5375 +28.304 +26.286 +106.17 +45.605 +0.049351 +0.17173 +0.69811 +0.052192 +0.35938 +243.35 +315.11 +1604.8 +3327.6 +1522.5 +3306.4 +687.62 +412.38 +1979.8 +571.65 +891.01 +95.9 +779.36 +871.37 +3.5137 +9.9101 +32.84 +15.585 +25.363 +20000 +8196.4 +8226.6 +3601.3 +7732.2 +5508.6 +5874.1 +23.066 +51.827 +60.333 +154.1 +0.71506 +0.056885 +0.11326 +0.015941 +197.96 +62.482 +23.728 +213.73 +244.99 +26.328 +9.1281 +45.411 +120.23 +96.569 +907.68 +540.16 +68.777 +94.686 +65.724 +46.961 +12.289 +27.698 +29.001 +108.36 +49.029 +47.646 +0.27776 +0.82964 +0.06854 +99.124 +77.718 +140.85 +1004.8 +7960.1 +2334.2 +4649.5 +1402.8 +1298.7 +1638.8 +0.072125 +688.5 +2079.8 +584.88 +3649 +4.3504 +10.351 +43.181 +21.816 +11.112 +19465 +9088.5 +8617.2 +3232.9 +3562.4 +2620.5 +2983.7 +0.10192 +0.050717 +0.11496 +30.927 +31.204 +77.521 +0.055553 +471.38 +179.76 +100.76 +47.416 +415.41 +29.07 +19.549 +12.258 +52.935 +81.248 +104 +1043.8 +314.65 +138.76 +253.09 +101.64 +56.527 +9.4114 +12.099 +86.919 +145.69 +84.334 +59.532 +3.5592 +1.4952 +0.20445 +126.68 +112.03 +119.11 +351.73 +1289.2 +1421.1 +1711.5 +2364.9 +2012.4 +2515.3 +1119.9 +0.028167 +1173.3 +1219.5 +3030.7 +6.4432 +24.535 +40.614 +20.341 +10.027 +33.453 +5069.9 +4820.1 +4278.2 +5420.9 +1473.5 +0.057922 +0.22536 +0.10497 +0.16221 +0.10651 +0.021999 +433.08 +700.8 +856.04 +361.87 +243.95 +115.59 +55.019 +29.417 +9.5029 +9.9344 +45.165 +166.51 +46.815 +879.39 +193.78 +128.07 +179.34 +108.69 +135.75 +5.5524 +20.318 +49.264 +85.334 +165.48 +63.665 +0.84262 +0.59375 +0.30898 +0.042635 +72.153 +204.03 +130.92 +637.33 +230.95 +2356.6 +1382.4 +1872.7 +1943.6 +20.261 +705.67 +873.58 +1404.3 +15.366 +2.9473 +60.206 +45.805 +26.319 +10.562 +19.043 +29.694 +2600.1 +2673.8 +0.081876 +0.043923 +0.2819 +0.11478 +0.028511 +0.084036 +2.7731 +134.4 +185.52 +112.87 +510.91 +520.47 +345.36 +0.063346 +73.226 +38.148 +9.8193 +11.886 +38.157 +1353.6 +1987.7 +272.93 +203.1 +116.25 +136.02 +105.43 +155.47 +5.4723 +18.547 +32.067 +182.26 +90.351 +109.49 +0.81705 +0.34805 +0.038671 +0.062894 +128.42 +215.59 +178.89 +915.24 +193.08 +886.74 +2050.6 +1852.2 +852.21 +163.03 +1351.8 +553.68 +32.529 +15.394 +7.4316 +33.642 +26.94 +47.707 +16.751 +21.442 +22.55 +1174.5 +2916.1 +0.055861 +0.021274 +0.035199 +0.12111 +0.030879 +0.065266 +7.5117 +74.467 +177.32 +281.32 +281.42 +577.49 +0.050091 +0.18737 +0.1568 +28.529 +27.63 +2517 +738.1 +933.11 +871.79 +320.2 +157.03 +134.77 +168.69 +435.01 +652.92 +1859.8 +925.77 +1486.1 +1661.3 +4411.9 +46.269 +0.20478 +0.39581 +0.14735 +0.025938 +0.007892 +169.87 +198.28 +784.71 +2717.8 +1377.4 +3238.6 +5057.7 +695.24 +195.7 +1475 +1.9986 +13.711 +16.673 +35.938 +15.221 +20.127 +65.248 +20.669 +39.491 +51.869 +1473.4 +0.024469 +0.049945 +0.47797 +0.054648 +0.032764 +0.081617 +0.012342 +10.976 +113.37 +468.65 +442.29 +271.33 +1267.8 +0.02819 +0.053603 +0.054862 +43.035 +350.07 +1881 +1500.1 +950.93 +515.64 +479.51 +1144 +1023 +592.2 +329.2 +947.42 +973.82 +1447.6 +2677.9 +4213.7 +1444.8 +11079 +0.030241 +0.069073 +0.036347 +0.03097 +0.058345 +0.066494 +175.42 +3026.1 +1156.2 +2183 +2936.2 +2181.8 +832.18 +153.02 +706.54 +3.2145 +9.2865 +11.159 +17.896 +17.044 +23.973 +85.297 +34.483 +88.593 +39.678 +0.21368 +0.032631 +0.050632 +1.04 +1.1297 +0.059103 +0.077958 +0.11299 +23.192 +35.882 +438.07 +225.29 +411.25 +791.82 +0.039732 +0.069966 +0.071924 +247.34 +634.64 +2155.8 +872.2 +861.18 +112.31 +98.951 +431.1 +1775.3 +1553 +694.85 +1883 +1581.8 +910.39 +2078.4 +2836.2 +3505.7 +553.37 +0.068438 +0.0474 +0.081545 +0.077128 +0.14198 +0.09065 +0.15977 +2837.4 +1414.8 +1445.8 +6372.8 +4334.1 +1119 +15.122 +11.556 +2.4852 +20.439 +21.996 +28.635 +27.434 +24.46 +138.18 +62.951 +85.102 +143.21 +0.058604 +0.022878 +0.019812 +0.19787 +0.48935 +0.030584 +0.022982 +0.050755 +21.166 +40.382 +159.58 +195.45 +539.41 +193.07 +32.902 +18.827 +73.82 +257.64 +336.34 +2065.9 +58.382 +27.374 +91.346 +178.89 +738.15 +832.97 +2162.5 +234.65 +2058.4 +762.53 +1245 +544.75 +647.57 +285.73 +423.48 +0.13564 +0.15352 +0.23669 +0.21923 +0.040201 +0.052 +0.15072 +51.245 +1021.1 +2010.3 +3525.3 +6405.1 +1013.6 +14.065 +10.346 +3.1605 +15.167 +13.149 +25.728 +22.907 +35.685 +147.94 +23.242 +6649.4 +0.090554 +0.011954 +0.023624 +0.071026 +0.049531 +0.045962 +0.11707 +0.044904 +0.003453 +22.756 +77.47 +204.08 +127.37 +401.03 +291.2 +0.45181 +13.075 +151.26 +97.186 +47.583 +124.12 +75.046 +41.142 +91.46 +182.45 +976.96 +672.16 +687.45 +446.96 +717.36 +517.9 +938.71 +636.23 +1017.9 +515.14 +28.852 +0.21398 +0.24414 +0.17823 +0.55816 +0.085047 +0.31459 +0.09849 +0.079809 +54.552 +3577.8 +2515.6 +1908.1 +1342.8 +8.5413 +5.534 +4.4049 +11.797 +17.816 +20.836 +49.496 +43.551 +101.72 +35.164 +20.077 +0.16516 +0.017769 +0.080451 +0.094329 +0.030378 +0.063156 +0.013578 +0.022231 +0.013782 +0.015439 +127.72 +177.31 +158.85 +541.11 +667.76 +21.918 +117.12 +94.865 +93.768 +28.75 +94.018 +187.67 +111.14 +267.7 +364.4 +1178.8 +1002 +356.12 +982.39 +224.03 +983.79 +154.17 +186.08 +286.98 +88.52 +49.485 +0.17155 +0.021736 +0.29292 +0.12531 +0.42716 +0.91892 +0.20216 +0.38024 +0.52909 +410.89 +1841.5 +1972.3 +27.504 +14.306 +4.465 +11.739 +23.305 +23.479 +17.397 +139.09 +68.664 +82.785 +20.509 +20000 +0.02774 +0.013818 +0.071988 +0.039631 +0.054121 +0.059862 +0.020456 +0.021124 +0.059129 +0.09583 +99.545 +206.83 +121.91 +60.056 +20.178 +63.626 +81.151 +77.169 +63.101 +30.57 +69.759 +92.996 +134.47 +191.73 +170.07 +85.207 +967.41 +10.064 +465.78 +856.99 +543.12 +128.59 +104.4 +509.09 +142.32 +30.173 +0.018056 +0.069506 +0.21218 +0.25674 +0.29171 +0.041781 +0.082685 +0.12274 +0.28577 +514.54 +1315.1 +1134.4 +362.18 +36.529 +5.7158 +13.332 +22.623 +42.637 +27.724 +269 +60.291 +139.61 +20000 +13.809 +0.095444 +0.022126 +0.028104 +0.077474 +0.1055 +0.10579 +0.055851 +0.015427 +0.038735 +0.31868 +0.31549 +323.86 +16.54 +63.47 +33.31 +75.162 +30.931 +49.124 +104.16 +28.062 +64.962 +122.33 +1827.4 +111.14 +125.46 +175.3 +306.12 +622.04 +332.1 +756.65 +332.29 +99.591 +97.807 +617.16 +237.91 +0.075459 +0.09817 +0.036888 +0.050964 +0.079193 +0.13119 +0.13242 +0.14494 +0.031957 +0.17187 +589.53 +1208.2 +631.15 +655.41 +28.047 +1.964 +8.8037 +9.9004 +54.197 +108.86 +292.79 +127.63 +80.943 +20000 +23.485 +0.29382 +0.29789 +0.19878 +0.33962 +0.068099 +0.079467 +0.007288 +0.037506 +0.28082 +0.24958 +0.5342 +138.92 +43.91 +80.864 +75.525 +33.456 +43.745 +35.243 +68.509 +242.97 +111.28 +665.75 +1173.1 +293.92 +63.573 +117.11 +65.458 +437.87 +2401.5 +322.46 +248.79 +0.22628 +0.31325 +0.029867 +0.055075 +0.33352 +0.10808 +0.097961 +0.050965 +0.097559 +0.26001 +0.10609 +0.22272 +0.19604 +0.4478 +0.04884 +2688.5 +517.31 +1947.1 +2998.4 +3050.5 +19.024 +12.228 +36.285 +111.83 +933.51 +384.9 +9.5006 +6.9376 +32.749 +0.14588 +0.63414 +0.23036 +0.19989 +0.096949 +0.13617 +0.17872 +0.22419 +0.49506 +0.1051 +0.23654 +84.427 +69.478 +44.515 +66.773 +22.462 +24.596 +25.031 +51.575 +86.672 +89.458 +274.77 +1748.2 +347.16 +86.336 +160.91 +340.79 +905.96 +918.58 +895.08 +642.69 +0.61904 +0.26566 +0.022074 +0.009777 +0.038808 +0.046555 +0.049495 +0.072805 +0.039843 +412.94 +526.09 +127.76 +681.57 +1018.9 +2207.2 +3223 +460.75 +1377.1 +2722.3 +1138.6 +646.42 +8.875 +19.774 +160 +1286.4 +791 +533.6 +6.5705 +0.093492 +0.22165 +0.15121 +0.10654 +0.031967 +0.096837 +0.18621 +0.33583 +0.58797 +0.61404 +951.81 +750.49 +104.87 +48.109 +32.955 +53.962 +46.786 +15.958 +44.103 +1.6119 +3.2856 +109.51 +557.3 +439.74 +346.32 +119.83 +730.12 +422.69 +34.31 +547.07 +961.38 +1593.4 +657.75 +581.54 +0.086168 +0.016832 +0.14373 +0.036174 +0.12091 +718.86 +371.35 +523.68 +454.24 +395.61 +136.23 +74.243 +199.85 +2667 +339.19 +987.6 +1520.3 +1379.8 +699.36 +137.48 +65.923 +121.29 +1393 +530.65 +475.79 +263.41 +48.472 +0.14855 +0.070753 +0.16731 +0.46154 +0.46442 +0.60423 +0.70573 +0.62273 +0.59138 +2110.8 +644.45 +96.967 +24.153 +46.224 +80.647 +100.5 +22.023 +98.255 +2.7744 +3.3778 +1.4647 +407.64 +477.95 +109.45 +72.38 +0.18236 +704.03 +34.932 +45.493 +70.09 +1557.5 +1527.5 +945.92 +353.64 +0.009963 +0.078112 +0.015346 +1543.1 +814.47 +205.55 +734.18 +586.54 +0.22841 +195.42 +25.252 +4308.7 +2982.5 +381.27 +911.22 +1223.6 +1845.3 +804.02 +256.27 +114.24 +449 +790.84 +371.47 +358.03 +72.74 +111.62 +114.86 +0.092551 +0.33198 +0.24754 +2.024 +0.25662 +0.45082 +0.73555 +3636.6 +1332.3 +736.46 +38.128 +14.932 +75.837 +145.37 +49.5 +30.549 +106.6 +4.1381 +3.8719 +4.404 +55.712 +140.15 +113.51 +110.97 +275.25 +53.031 +27.742 +28.972 +791.02 +1455.2 +803.03 +850 +187.82 +107.59 +0.027439 +406.67 +1281.1 +704.42 +392.19 +472.2 +0.36087 +0.13702 +108.82 +48.818 +2490.1 +1403.5 +598.74 +1206.4 +703.75 +2806.5 +904.82 +339.44 +266.8 +644.84 +1400.6 +213.52 +141.4 +64.925 +59.615 +218.05 +143.68 +156.46 +0.48526 +0.10011 +0.11582 +0.73423 +1.2026 +1077.8 +2833.8 +16.095 +53.049 +132.48 +81.803 +69.067 +23.986 +49.768 +9.1437 +5.7868 +5.7691 +4.7154 +25.75 +67.965 +96.853 +242.67 +299.44 +51.551 +870.16 +1561.1 +542.65 +1431.2 +1150.8 +573.67 +195.28 +120.62 +0.023145 +870.83 +1111.1 +1623.7 +689.16 +0.3522 +0.27709 +0.1833 +84.574 +9416.9 +1964.3 +1223.8 +985.14 +1189.1 +463.23 +2388.6 +339.1 +599.4 +42.319 +24.308 +1690.2 +454.07 +242.87 +92.49 +73.505 +260.17 +109.93 +87.11 +108.57 +0.25691 +0.10643 +0.5489 +0.29398 +1.0334 +0.76915 +23.035 +50.295 +112.1 +42.311 +58.278 +32.938 +56.575 +20.429 +17.221 +4.8275 +3.405 +26.037 +109.89 +262.45 +308.71 +460.05 +424.02 +759.79 +1671.8 +336.06 +494.13 +717.63 +681.86 +289.17 +190.57 +0.18026 +711.92 +1083.2 +1827.5 +1171.1 +524.14 +0.061159 +0.031658 +605.27 +3347.5 +1701.1 +844.35 +456.99 +252.33 +316.51 +1033.5 +289.16 +70.727 +135.95 +582.36 +3156 +436.38 +248.56 +434.39 +52.032 +252.51 +129.67 +64.451 +71.064 +43.197 +0.029187 +0.072202 +0.38776 +2.4376 +181.32 +26.303 +42.276 +129.77 +32.753 +29.461 +99.841 +57.437 +28.765 +16.319 +8.3125 +7.3448 +23.654 +0.20924 +341.65 +422.03 +888.55 +534.11 +0.052916 +2180.4 +554.26 +218.29 +663.52 +1142.7 +817.44 +181.83 +0.089715 +0.032828 +947.58 +770.61 +1104.5 +1372.5 +678.25 +0.03667 +2659.3 +4856.2 +108.41 +123.03 +385.33 +379.59 +289.76 +250.33 +44.122 +260.79 +406.53 +1078.2 +3163.8 +273.69 +143.51 +168.7 +161.71 +171.2 +83.715 +82.244 +82.581 +57.142 +84.223 +0.058064 +0.018525 +0.39208 +0.15717 +16.971 +26.239 +52.178 +14.793 +118.26 +87.222 +61.228 +19.653 +30.895 +16.039 +13.371 +0.076717 +0.042508 +0.14078 +368.6 +666.25 +390.75 +501.48 +1717.7 +227.22 +241.15 +1341.2 +2700.1 +1806.7 +0.19326 +0.62515 +0.083615 +0.068975 +1131.9 +1615.2 +1545.7 +2075.8 +2324 +0.1476 +6878.3 +90.707 +312.39 +208.75 +242.32 +233.34 +151.02 +500.75 +388.44 +272.79 +1254.3 +4917.3 +98.984 +180.57 +198.4 +57.886 +259.46 +261.01 +67.35 +39.523 +42.377 +68.401 +157.25 +0.01787 +0.093927 +180.75 +30.16 +22.477 +30.127 +17.203 +136.04 +33.182 +39.505 +30.61 +43.289 +28.315 +12.101 +0.051425 +0.11961 +0.062837 +404.75 +513.94 +507.17 +864.34 +545.76 +211.6 +321.55 +1383.1 +0.083571 +0.14291 +0.054787 +0.060374 +0.078012 +0.13783 +0.18706 +0.033564 +1573.2 +1813.8 +1907 +165.69 +81.013 +34.524 +163.51 +116.98 +94.782 +221.14 +1203.7 +794.01 +199.88 +328.06 +84.876 +134.85 +307.53 +117.17 +91.555 +149.31 +160.97 +256.08 +534.92 +40.635 +52.465 +52.969 +97.493 +0.016214 +0.036701 +234.14 +24.63 +58.414 +40.832 +18.311 +128.47 +33.194 +52.25 +12.694 +16.668 +32.631 +0.067626 +0.070366 +0.044752 +0.034006 +0.027681 +658.06 +758.61 +390 +426.88 +510.17 +464.74 +0.13617 +0.061527 +0.087851 +0.020834 +0.045807 +0.4487 +0.084579 +0.11244 +0.15476 +0.15494 +419.6 +284.29 +119.32 +93.848 +84.025 +223.19 +177.65 +6307.8 +507.65 +3118.7 +911.39 +391.22 +679.23 +100.11 +126.79 +283.41 +173.7 +113.68 +225.72 +131.52 +225.97 +817.71 +348.18 +372.26 +57.65 +90.304 +20.171 +516.09 +247.33 +63.356 +74.041 +24.325 +8.2242 +58.143 +22.833 +78.461 +18.696 +40.656 +28.866 +93.915 +0.011003 +0.073427 +4526 +10336 +494.75 +304.54 +1025 +237.63 +0.002272 +0.005741 +0.060402 +0.14137 +0.20482 +0.10709 +0.083907 +0.0853 +0.10609 +0.037686 +0.067858 +318.77 +273.43 +400.58 +150.08 +411.98 +51.441 +409.36 +565.16 +1434.6 +299.26 +2137.7 +734.81 +324.33 +967.01 +102.8 +120.28 +180.99 +0.086837 +0.033348 +0.008534 +96.816 +193.99 +313.71 +956.59 +718.23 +850.96 +178.73 +0.1603 +910.03 +183.92 +98.902 +80.227 +24.142 +0.020188 +23.907 +14.608 +28.496 +29.781 +22.497 +77.264 +159.32 +1591.7 +2224.3 +2747.5 +7564.6 +412.89 +493.36 +502.46 +0.012131 +0.008558 +0.026392 +0.085925 +0.1077 +0.071627 +0.094142 +0.046302 +0.048062 +0.034325 +0.21603 +300.71 +177.25 +211.43 +427.51 +146.06 +442.42 +975.6 +335.97 +967.08 +2985.5 +60.42 +54.068 +704.03 +0.02306 +1035.3 +176.47 +127.3 +0.019727 +0.29127 +0.068753 +0.027058 +2487.6 +104.35 +292.43 +1463 +259.57 +170.55 +0.15116 +492.86 +539.76 +457.75 +102.31 +55.297 +38.528 +6.612 +15.844 +7.7647 +14.473 +10.46 +17.294 +8942.5 +4122.4 +594.54 +802.4 +3440.1 +146.86 +126.7 +511.74 +601.7 +0.057692 +0.012538 +0.01099 +0.038868 +0.044684 +0.13979 +0.030668 +0.21989 +0.13407 +0.11574 +0.2496 +199.53 +114.29 +274.94 +33.134 +479.09 +450.39 +982.35 +304.81 +88.049 +209.88 +55.653 +31.25 +113.94 +445.04 +946.55 +151.36 +174.95 +0.049855 +0.13605 +226.8 +34.862 +738.82 +50.615 +1907.3 +996.84 +465.19 +85.041 +276.28 +181.44 +655.15 +919.45 +109.43 +37.833 +27.835 +6.7402 +15.373 +8.2221 +7.6279 +1380.1 +533.43 +194.9 +5635.1 +274.6 +235.42 +62.942 +78.698 +69.16 +0.007722 +0.13023 +0.049211 +0.010245 +0.020563 +0.022641 +0.091124 +0.15535 +0.19873 +0.29305 +0.33786 +0.10192 +0.042678 +0.020192 +23.556 +14.152 +45.576 +307.51 +136.5 +624.89 +858.12 +99.928 +151.83 +71.425 +25.967 +56.879 +472.13 +510.66 +352.05 +79.415 +0.17203 +218.25 +75.95 +56.997 +497.52 +27.933 +270.4 +669.57 +303.85 +105.2 +228.22 +122.79 +637.57 +303.92 +374.63 +245.07 +502.21 +680.14 +1623.2 +8.4624 +8.9577 +629.67 +0.061892 +8909.8 +159.49 +677.37 +153.96 +85.477 +45.226 +60.335 +0.10648 +0.18655 +0.22092 +0.012167 +0.030462 +0.015229 +0.028981 +0.048712 +0.43826 +0.252 +1.0217 +0.018653 +0.036854 +73.349 +16.855 +11.295 +26.129 +347.36 +322.43 +552.6 +890.92 +32.549 +43.508 +73.622 +24.926 +109.28 +238.14 +416.98 +188.04 +449.95 +398.66 +170.41 +79.815 +95.673 +0.27222 +0.18093 +0.099412 +728.63 +279.76 +106.08 +105.93 +114.35 +579.9 +145.47 +350.57 +326.93 +327.06 +404.72 +2442.8 +23.22 +0.13094 +1272.3 +0.061405 +948.63 +670.77 +125.22 +195.95 +34.767 +4.7996 +7.6113 +206.15 +20000 +0.085704 +0.024358 +0.058225 +0.026277 +0.12056 +0.12881 +0.095422 +0.20475 +0.1025 +261.33 +28.282 +79.353 +11.461 +14.806 +46.148 +381.07 +1339.5 +2644.2 +2204 +18499 +13.498 +49.602 +49.291 +104.11 +170.35 +330.54 +179.27 +468.26 +248.86 +294.03 +0.053086 +0.15638 +0.17896 +0.057096 +0.10409 +389.8 +278.98 +138.09 +251.28 +69.998 +487.99 +193.42 +498.54 +583.57 +304.76 +441.69 +795.82 +28.704 +4453.1 +309.73 +218.23 +598.49 +126.07 +191.18 +238.11 +151.22 +4.2604 +16.769 +8.6944 +46.896 +20000 +0.058789 +0.031753 +0.029668 +0.052241 +0.060219 +0.055602 +0.042411 +116.59 +141.78 +33.119 +49.46 +18.537 +107.1 +109.59 +453.53 +856.03 +1966.7 +4702.7 +10483 +21.285 +36.398 +48.881 +57.389 +1738.9 +540.17 +227.33 +630.35 +183.45 +226.62 +0.036326 +0.18052 +0.26416 +0.062086 +165.83 +545.48 +363.39 +98.071 +236.69 +114.21 +793.05 +477.92 +441.84 +267.67 +241.48 +472.05 +22.592 +0.35364 +141.98 +228.99 +224.72 +725.45 +82.94 +194.02 +189.35 +233.12 +489.4 +156.65 +8.6617 +132.28 +274.97 +169.6 +0.050915 +0.20541 +0.15962 +0.040473 +0.075542 +0.018255 +62.153 +123.03 +46.883 +42.171 +5631.1 +156.32 +66.638 +398.24 +674.13 +1072.3 +3557.2 +19321 +39.996 +28.732 +1360 +1106.8 +2210.8 +110.59 +66.505 +42.229 +200.82 +373.87 +595.05 +172.14 +279.86 +89.853 +139.81 +406.56 +220.54 +68.397 +113.36 +94.087 +1111.3 +324.35 +731.92 +95.594 +266.7 +62.053 +0.34574 +0.2113 +210.22 +337.77 +166.75 +9545.1 +62.981 +276.98 +349.55 +394.66 +634.95 +108.46 +0.13416 +107.17 +152.83 +338.19 +364.16 +519.42 +0.07794 +0.033883 +0.2838 +0.19881 +69.799 +49.651 +25.233 +25.888 +114.23 +52.859 +129.04 +423.46 +474.19 +1418.7 +2605 +14113 +6876.4 +632.08 +0.092299 +0.14075 +31.368 +110.51 +51.841 +23.413 +70.669 +550.1 +466.24 +118.63 +261.82 +77.011 +244.97 +433.74 +323.13 +397.83 +86.997 +482.12 +739.15 +143.05 +334.83 +0.10281 +0.22904 +0.15238 +0.022898 +0.097099 +205.89 +566.19 +99.629 +183.24 +74.231 +489.25 +531.23 +396.59 +1122 +528.96 +0.051827 +0.083037 +229.91 +319.65 +531.87 +430.27 +732.83 +7.0731 +0.06587 +0.10876 +75.451 +58.959 +30.712 +16.583 +50.468 +59.804 +154.15 +251.82 +468.08 +1276.3 +1122.8 +8582.5 +10320 +3300.7 +0.15433 +0.20388 +0.63893 +0.18157 +52.929 +24.673 +545.4 +274.18 +278.55 +75.689 +116.33 +162.69 +268.68 +551.12 +0.19239 +0.11292 +60.657 +434.49 +979.98 +21.284 +19.879 +0.099067 +0.27608 +0.11631 +0.30046 +211.34 +202.58 +258.79 +45.264 +203.56 +153.83 +614.78 +936.77 +935.1 +979.13 +0.42986 +0.23606 +0.2249 +0.40697 +369.44 +514.15 +197.64 +180.6 +21.749 +27.009 +17.92 +57.311 +21.804 +23.169 +30.378 +162.28 +143.9 +313.23 +379.54 +711.43 +1728.3 +1246.5 +3557.4 +14315 +4393.6 +0.045182 +0.10496 +141.78 +220.48 +98.791 +352.79 +813.81 +261.83 +233.61 +31.084 +0.065815 +0.16378 +0.2224 +0.20522 +0.23151 +110.96 +75.017 +0.053733 +34.637 +34.584 +25.741 +0.060038 +0.47984 +0.18324 +0.17818 +0.14935 +440.01 +144.25 +90.102 +7591.9 +2420.2 +469.07 +994.25 +256.92 +386.32 +0.4726 +0.2206 +0.10404 +0.25653 +0.21994 +491.04 +171.67 +449.13 +171.95 +14.905 +15.409 +51.898 +18.941 +8.0037 +46.097 +219.13 +210.1 +455.97 +220.09 +0.032572 +1991.2 +1630.7 +7786.8 +20000 +10464 +9506.7 +476.34 +323.28 +125.83 +109.16 +214.58 +521.41 +157.49 +281.17 +7353.2 +0.028334 +0.12307 +0.049167 +0.050323 +0.060093 +0.085251 +0.10346 +0.03905 +0.060784 +68.62 +48.841 +51.48 +55.646 +172.46 +435.81 +564.81 +238.47 +253.22 +55.839 +106.42 +213.26 +1892.6 +1061.9 +427.01 +275.19 +231.97 +0.66456 +0.14827 +0.26272 +0.10371 +0.2377 +165.92 +156.79 +154.46 +16.875 +23.637 +77.109 +27.485 +6.6853 +80.203 +161.46 +342.98 +45.325 +85.355 +0.10149 +634.3 +1968.6 +9329.9 +10999 +2855.7 +11456 +400.77 +1128.2 +70.43 +0.16392 +576.76 +1125.1 +135.97 +191.64 +4497.4 +1402.9 +0.13357 +0.064486 +0.065728 +0.069227 +0.02709 +0.077618 +0.035601 +0.026241 +0.069374 +52.44 +156.85 +15.385 +265.81 +707.69 +1896.8 +1876.6 +122.75 +48.43 +326.29 +163.61 +0.24287 +0.48659 +536.6 +517.08 +269.23 +0.18578 +0.16186 +0.2275 +0.065137 +0.36187 +0.13932 +358.77 +340.26 +505.36 +81.75 +82.705 +20.117 +19.797 +157.64 +279.37 +142.96 +44.14 +0.15828 +922.11 +755.57 +922.31 +14702 +13445 +1706 +12244 +15940 +0.073185 +0.22957 +49.04 +447.54 +320.07 +116.87 +261.78 +938.64 +1081.3 +0.20777 +0.12221 +0.18277 +0.10492 +0.029754 +0.093913 +0.27934 +0.080188 +0.12469 +37.618 +60.276 +80.551 +101.44 +47.278 +1058.1 +3053.7 +121.17 +76.871 +195.09 +107.5 +122.78 +0.30328 +0.68965 +501.64 +134.37 +53.823 +0.09565 +0.018662 +0.11248 +0.063694 +0.29031 +421.38 +525.67 +399.43 +160.19 +45.561 +30.058 +20.207 +189.46 +259.87 +159.38 +330.54 +120.43 +1131.4 +535.07 +998.61 +18824 +11549 +2342.9 +10327 +11622 +20000 +100.18 +138.46 +174.17 +197.57 +131.49 +35.636 +859.09 +755.13 +0.12208 +0.06326 +0.17272 +0.16701 +0.074919 +0.28059 +0.097066 +78.622 +28.389 +51.072 +35.034 +59.461 +19.288 +103.09 +88.101 +4344.6 +0.082997 +47.989 +543.78 +182.17 +222.24 +0.20307 +0.33123 +1.1954 +125.88 +187.31 +245.27 +0.074553 +0.080342 +0.14937 +0.060376 +551.16 +343.73 +552.14 +154.86 +81.622 +28.188 +19.149 +114.79 +167.95 +55.014 +100.81 +281 +570.48 +246.54 +913.15 +902.89 +0.28008 +2308.8 +8697 +18408 +19984 +16036 +222.52 +74.515 +92.665 +69.826 +45.865 +967.5 +0.10053 +0.047957 +0.2536 +0.31526 +0.48919 +0.14268 +0.61258 +29.592 +170.92 +58.489 +98.876 +15.002 +67.972 +273.48 +109.28 +72.592 +36.251 +0.20465 +0.073255 +416.49 +355.74 +330.01 +108.41 +0.31262 +0.24472 +0.50086 +289.54 +305.19 +392.76 +0.046269 +1364.5 +1327.8 +1237.5 +328.25 +443.09 +198.19 +75.954 +30.309 +25.599 +141.79 +96.878 +75.471 +46.122 +16.209 +462.37 +171.34 +1103 +60.938 +0.18159 +2799.2 +5734.3 +20000 +8483 +14129 +3510.5 +55.485 +114.45 +137.68 +23.673 +0.14777 +0.070849 +0.1263 +0.16507 +0.12828 +0.10689 +0.08366 +0.41969 +12.148 +350.06 +102.6 +137.85 +25.573 +116.32 +917.42 +474.11 +87.351 +35.026 +0.024031 +0.077738 +419.87 +456.46 +370.93 +198.7 +0.20856 +0.20605 +0.37574 +0.24119 +0.12551 +304.4 +380.06 +66.674 +71.871 +80.959 +154.45 +174.2 +120.15 +112.93 +30.151 +849.27 +883.1 +68.032 +39.522 +21.946 +16.395 +60.955 +114.05 +474.19 +33.016 +9.7092 +2993.5 +3237.1 +11553 +8108.9 +6792.4 +6191.8 +39.122 +101.54 +193.04 +0.036409 +0.24783 +0.39837 +0.050049 +0.13898 +0.071489 +0.15832 +0.12409 +0.024948 +0.02717 +452.57 +94.975 +125.14 +183.78 +212.71 +459.83 +1083.7 +783.08 +31.626 +34.915 +1104.8 +846.78 +587.09 +493.19 +353.47 +295.52 +329.9 +501.04 +218.75 +63.826 +235.55 +39.531 +76.067 +102.75 +0.025146 +0.081144 +0.033627 +0.017223 +181.02 +15.509 +173.78 +389.62 +396.68 +613.92 +28.719 +23.036 +46.045 +77.145 +85.617 +42.264 +13.291 +29.488 +2690.1 +10504 +10224 +6468.9 +7848.9 +5778.2 +116.14 +255.67 +0.046071 +0.23661 +0.23892 +0.26159 +0.36131 +0.015283 +0.18383 +0.047899 +0.03856 +0.032439 +0.27664 +109.79 +172.77 +168.4 +113.13 +24.335 +173.53 +48.974 +48.538 +2315.7 +1026.2 +840.83 +551.05 +313.03 +249.76 +344.58 +307.28 +135.96 +177.99 +428.03 +0.043837 +0.41669 +2624.1 +762.69 +727.96 +0.046257 +0.14633 +0.075508 +182.56 +34.696 +96.186 +131.53 +420.43 +1467 +143.31 +8.5592 +50.311 +47.216 +43.768 +240.3 +107.82 +29.467 +1813.8 +3962 +8994.7 +5268.8 +7004.7 +3779.8 +78.952 +246.37 +0.12059 +0.075028 +0.15795 +0.15238 +0.27144 +0.098843 +0.0699 +0.213 +0.15767 +0.381 +0.60497 +799.89 +107.68 +99.013 +71.833 +75.325 +206.53 +37.644 +38.616 +1900.7 +609.88 +637.64 +918.04 +90.394 +481.77 +221.92 +187.56 +0.2294 +0.46302 +0.06562 +0.031653 +267.83 +1186.8 +795.53 +370.82 +0.077734 +0.03083 +0.043048 +174.83 +54.818 +52.029 +76.192 +188.3 +319.68 +120.25 +238.01 +191.25 +38.755 +158.48 +135.68 +181.29 +406.91 +282.7 +3311.4 +4814.6 +3585.9 +7761.7 +3881.2 +846.31 +0.086949 +0.10202 +0.052249 +0.28253 +0.10332 +0.18271 +0.10702 +0.17144 +0.55987 +0.15518 +2.0496 +73.8 +133.71 +126.26 +155.91 +94.883 +90.031 +119.32 +35.375 +1227.9 +2271.3 +550.51 +98.403 +85.911 +83.981 +0.29934 +0.13344 +0.14333 +0.077316 +0.12509 +0.064666 +0.10513 +274.43 +1265.3 +983.17 +0.051347 +0.018314 +0.091159 +0.019621 +0.099907 +1.0825 +51.356 +86.534 +100.99 +312.72 +532.08 +391.66 +228.79 +34.181 +125.81 +298.69 +437 +689.64 +354.82 +5237.1 +11255 +3628.4 +9770.9 +5856.3 +1778.5 +0.13399 +0.023454 +0.087332 +0.037313 +0.15404 +0.048491 +0.052891 +0.061447 +0.22213 +43.282 +67.874 +116.76 +72.129 +54.182 +63.863 +122.55 +162.21 +81.504 +20.63 +33.49 +4785.4 +1832.1 +6520.8 +162.25 +91.154 +0.14583 +0.15027 +0.08683 +0.023238 +0.020849 +0.46043 +229.6 +379.55 +811.65 +1626.5 +0.039916 +0.012936 +0.13504 +0.0431 +0.60974 +0.46007 +0.064702 +82.252 +143.08 +632.33 +501.52 +488.26 +270.64 +7.6214 +90.725 +125.28 +936.31 +763.32 +624.63 +549.46 +2602.5 +1461.7 +9422.5 +11755 +3087.1 +4066.4 +0.082078 +0.061463 +0.035707 +0.44105 +0.053522 +0.089714 +0.039575 +55.468 +28.521 +117.1 +203.69 +202.94 +147.25 +157.56 +380.54 +108.5 +97.104 +163.15 +92.388 +4457.4 +5335.4 +6532.4 +5788 +0.33996 +0.45049 +0.49725 +0.20038 +0.42904 +0.071308 +267.39 +164.13 +488 +701.77 +0.085081 +0.044189 +0.026306 +0.11488 +0.20757 +201.13 +0.10324 +0.020678 +0.20478 +184.35 +605.83 +519.96 +460.74 +485.89 +622.06 +422.35 +159.38 +3313.4 +352.9 +935.27 +1279.9 +1473.4 +2156.4 +1300.5 +4967.8 +3252.6 +4246.7 +1252.4 +0.052149 +0.3079 +67.434 +75.049 +320.34 +58.434 +99.523 +57.999 +137.92 +65.159 +153.36 +541.38 +209.39 +357.34 +110.93 +129.27 +142.69 +93.651 +312.27 +10347 +11399 +9693.4 +2540.1 +0.19946 +0.38728 +38.135 +139.72 +527.38 +305.19 +194.73 +582.86 +0.25537 +0.45171 +0.29298 +0.13606 +0.069507 +0.096938 +127.4 +0.067033 +0.08114 +0.072745 +234.64 +921.34 +671.36 +259.89 +613.15 +535.76 +325.93 +2210.8 +3704.4 +64.302 +3399.2 +1954.2 +1198 +1236.4 +771.21 +907.98 +118.77 +60.177 +57.668 +57.181 +166.76 +132.06 +128.17 +430.11 +83.075 +664.71 +189.25 +93.583 +33.572 +17.382 +27.138 +0.15643 +98.319 +58.568 +139.78 +145.37 +214.59 +202.92 +11568 +9209.5 +56.101 +33.927 +21.344 +216.71 +84.914 +151.41 +591.12 +0.034204 +0.042723 +0.12519 +0.26055 +0.041349 +0.62342 +0.31893 +0.017328 +0.18152 +87.708 +0.11709 +0.12679 +0.065251 +427.03 +132.26 +658.26 +406.39 +608.25 +237.26 +148.45 +609.6 +120.12 +54.01 +7079.5 +6846.2 +1047.2 +1231.4 +518.96 +17.765 +16.125 +71.669 +33.905 +38.618 +111.37 +40.705 +0.24985 +528.05 +309.16 +360.2 +331.01 +77.411 +41.965 +0.31075 +0.31499 +0.63556 +46.76 +90.775 +71.922 +166.56 +211.69 +647.67 +158.57 +67.439 +47 +33.179 +54.502 +132.33 +217.83 +0.33456 +0.4556 +0.16832 +0.039423 +0.01732 +0.031499 +0.14294 +0.30992 +0.082471 +0.061064 +0.086414 +161.11 +0.24199 +94.826 +7.5736 +160.47 +46.843 +62.732 +248.94 +255.64 +145.1 +167.18 +1431.5 +96.352 +188.22 +151.82 +7009.8 +955.22 +23.798 +5.8709 +15.955 +67.27 +61.509 +173.23 +3467.1 +3358.1 +340.26 +0.1087 +175.6 +347.31 +409.32 +181.72 +0.020412 +0.43702 +0.23997 +0.19749 +1087.6 +739.29 +258.94 +114.74 +175.14 +24.965 +590.07 +191.2 +160.37 +119.23 +56.37 +48.726 +2694.9 +0.17876 +0.29649 +0.27614 +0.11797 +0.041392 +0.029639 +0.059356 +0.43379 +0.2951 +0.06078 +0.073678 +0.09094 +110.14 +0.032875 +72.236 +12.499 +119.4 +43.02 +1212.4 +197.09 +91.781 +66.608 +165.16 +571.38 +189.41 +87.048 +12131 +8930.2 +544.84 +16.451 +7.6139 +10.072 +385.99 +414.53 +331.22 +2722.3 +3730.4 +726.2 +0.066391 +293.48 +319.4 +286.56 +198.93 +0.21951 +0.30589 +0.22702 +0.35649 +1128.2 +1270.1 +795.65 +621.67 +245.36 +55.523 +45.343 +242.87 +102.26 +135.57 +95.17 +1105.7 +3243.5 +2443.7 +0.12618 +0.039646 +0.092272 +0.019015 +0.049392 +0.13788 +0.29458 +0.38693 +0.11744 +0.14648 +0.10673 +0.0909 +0.14405 +0.052876 +16.981 +29.422 +19.697 +266.75 +251.86 +135.32 +39.383 +235.9 +391.03 +130.08 +15.036 +17.366 +5406.4 +664.88 +900.34 +3.0586 +6.2398 +37.197 +454.16 +386.48 +3780.2 +3191.3 +0.064868 +0.12711 +314.4 +489.83 +754.37 +498.65 +0.036711 +0.16258 +0.17232 +0.18831 +2229.8 +1412.8 +1410.5 +324.31 +231.47 +34.193 +13.419 +9.1415 +12.812 +195.79 +107.12 +133.26 +1748.8 +906.83 +0.19532 +0.23695 +0.314 +0.1709 +0.14633 +0.20825 +0.15526 +0.29746 +0.32529 +0.072272 +0.089327 +260.09 +0.063145 +93.052 +9.6554 +25.427 +17.852 +221.4 +194.89 +172.49 +30.199 +249.35 +379.56 +763.34 +186.2 +26.149 +3026.2 +692.78 +723.21 +315.18 +3.0772 +21.304 +393.17 +246.61 +4271.9 +0.060919 +0.046626 +0.029377 +654.32 +333.56 +1338.4 +1098.4 +0.11303 +0.90226 +1.3895 +3366.2 +2411.3 +1054.4 +1000.3 +277.56 +153.2 +34.629 +30.943 +14.62 +13.599 +36.955 +70.606 +88.729 +47.73 +907.49 +1619.4 +0.069392 +0.053491 +0.2081 +0.082038 +0.31546 +0.16645 +0.18893 +0.97556 +0.13254 +0.043768 +733.47 +547.99 +161.23 +50.288 +9.3552 +53.824 +154.03 +75.496 +102.25 +55.905 +433.64 +933.58 +852.92 +32.672 +852.94 +421.81 +685.36 +602.51 +314.85 +109.95 +26.05 +3.2997 +357.36 +0.053596 +0.053042 +0.056365 +0.071051 +0.059369 +290.48 +1081.4 +1135.5 +0.3802 +203.72 +297.87 +2148.7 +1160.7 +1972.9 +698.74 +42.374 +52.705 +18.381 +15.618 +12.723 +11.885 +25.529 +41.156 +111.99 +45.488 +1386.9 +1187.6 +0.085396 +0.22767 +0.079375 +0.41602 +0.45795 +0.13486 +0.23069 +0.17411 +0.073808 +0.039912 +951.34 +180.92 +42.837 +44.92 +13.294 +44.696 +74.187 +30.373 +92.036 +28.542 +486.42 +447.17 +1746.4 +3610.7 +1197.2 +244.98 +480.04 +1316 +438.55 +148.34 +127.92 +2.4026 +4.301 +7.3373 +5.1145 +0.1194 +0.23882 +0.054546 +520.7 +1099.1 +3755.4 +2360.6 +1544.9 +334.44 +2940.2 +2360.2 +1715.7 +88.508 +98.399 +69.571 +27.698 +21.688 +16.703 +11.3 +13.157 +60.59 +41.459 +59.17 +2544.4 +842.38 +1049.9 +0.31323 +0.55603 +0.10551 +0.29991 +0.024167 +0.016651 +0.052495 +0.094912 +0.18037 +191.82 +158.57 +122.34 +66.923 +21.741 +68.479 +112.96 +876.82 +582.08 +982.02 +538.5 +5203.7 +2959.4 +3914.2 +501.39 +293.79 +870.55 +2222.3 +619.4 +1147.8 +327.87 +258.82 +4.7098 +1.8105 +8.2864 +3.3241 +0.15997 +0.33156 +0.20342 +1462.9 +4944.5 +5239 +1275.5 +214.71 +1638.8 +5050.7 +1614.2 +84.125 +94.556 +44.072 +15.984 +36.715 +27.435 +6.5033 +10.267 +91.466 +59.405 +968.65 +2216.9 +832.26 +1054.5 +651.58 +0.19969 +0.18527 +0.054305 +0.10823 +0.037332 +0.027316 +0.082641 +0.13353 +290.28 +417.81 +91.493 +93.026 +23.152 +73.085 +1171.5 +583.13 +554.53 +5963.4 +4200.4 +2515.3 +6321 +4449.1 +1047.5 +460.64 +1966.2 +683.61 +555.77 +1028.4 +280.78 +244.74 +510.85 +3.254 +4.3246 +7.8743 +5.6469 +186.84 +678.8 +1366.3 +3388.3 +2437.8 +1217.1 +1138.4 +1947.5 +5538.5 +111.19 +78.119 +65.127 +36.123 +14.116 +13.35 +11.48 +4.6086 +12.245 +24.563 +1434.5 +407.44 +762.2 +469.99 +616.19 +488.6 +0.17245 +0.13277 +0.068116 +0.53689 +0.080141 +0.21701 +0.064639 +0.43209 +205.5 +292.56 +141.74 +144.65 +52.802 +147.63 +2286.2 +1123.9 +1103.6 +1604.4 +5023.1 +2617.7 +3409.5 +7741.7 +818.84 +1323.4 +3132.8 +731.03 +394.11 +619.52 +552.56 +455.54 +631.72 +0.39564 +0.26183 +16.051 +19.122 +117.11 +200.16 +943.09 +4720.9 +1936.3 +1225 +633.51 +11.427 +18.259 +99.629 +28.145 +46.964 +28.572 +8.9142 +15.233 +5.3705 +3.1412 +6.8421 +0.037312 +4069.8 +697.2 +460.84 +347.69 +639.37 +304.68 +0.10547 +0.27055 +0.11715 +52.078 +0.041982 +0.2702 +0.059777 +0.13009 +408.22 +550.12 +296.14 +289.4 +115.23 +179.51 +876.69 +767.14 +2202.2 +2010.4 +5082.8 +3432 +2299 +2044 +573.66 +335.86 +1015.9 +444.93 +442.93 +519.13 +200.91 +234.86 +1166.4 +0.10979 +134.56 +118.02 +33.468 +10.456 +16.116 +93.107 +211.61 +908.18 +1614 +542.83 +18.869 +18.769 +61.91 +25.595 +33.321 +32.171 +7.3741 +4.9261 +3.7732 +7.7995 +0.15224 +0.049007 +0.21298 +743.64 +716.26 +234.54 +281.05 +320.82 +0.079058 +0.049581 +0.056477 +0.058339 +121.73 +88.976 +142.79 +0.084129 +358.96 +714.44 +473.74 +495.39 +111.94 +214.81 +1482.5 +1608.2 +1560.5 +996.76 +5466.6 +7466.3 +860.15 +34.31 +76.165 +376.09 +940.98 +648.1 +259.02 +343.05 +237.32 +429.58 +1284.2 +0.35656 +203.06 +92.915 +38.74 +1952.8 +57.5 +16.034 +15.171 +144.9 +146.6 +386.64 +13.552 +25.337 +49.745 +9.3368 +32.106 +21.814 +10.057 +8.3833 +3.4628 +0.31986 +0.44443 +0.031781 +0.24833 +483.19 +701.32 +354.28 +192.43 +209.7 +237.15 +0.036185 +0.10056 +0.071706 +266.71 +84.15 +90.284 +325.55 +730.94 +663.1 +561.57 +391.81 +90.439 +0.015546 +3261.2 +1657.2 +1785 +1281 +4926.5 +7388 +189.66 +47.789 +111.6 +385.84 +826.85 +733.14 +770.03 +1389.6 +720.64 +942.37 +0.094865 +0.34804 +361.38 +44.217 +52.052 +55.382 +55.763 +135.04 +11.165 +46.845 +155.18 +84.62 +14.106 +27.621 +30.876 +32.422 +23.38 +6.5055 +5.5295 +0.032178 +0.067851 +0.92011 +0.10991 +0.35937 +0.36764 +253.72 +204.32 +261.34 +132.96 +121.03 +164.39 +0.063615 +0.30102 +0.039288 +0.060661 +287.73 +130.21 +315.86 +1012.5 +406.59 +967.14 +466.26 +67.718 +415.6 +2500.3 +1952.1 +1514.4 +1331 +6187.9 +37.46 +122.8 +65.286 +64.479 +572.95 +525.35 +587.39 +974.17 +3823.8 +458.61 +83.664 +0.13177 +71.58 +270.96 +48.323 +97.772 +60.059 +43.288 +170.48 +688.02 +166.21 +234.4 +103.27 +29.945 +115.2 +54.189 +21.057 +11.543 +6.9722 +0.054221 +0.036881 +0.20741 +0.12757 +0.082005 +0.20037 +0.19051 +265.27 +347.57 +478.71 +145.93 +106.95 +125.97 +180.21 +0.37074 +0.3512 +0.11881 +782.51 +118.94 +190.28 +2246.3 +1446.3 +1310.1 +643.15 +392.78 +473.62 +2065.7 +3092.9 +848.06 +1078 +3044.3 +39.578 +89.87 +103.36 +113.57 +782.41 +953.63 +143.16 +711.19 +102.85 +89.746 +94.361 +0.020802 +83.937 +109.24 +71.171 +89.005 +68.735 +85.852 +93.225 +338.5 +219.85 +119.01 +151.15 +49.583 +128.24 +235.5 +13.677 +3.9162 +3.4719 +0.036448 +0.016638 +0.10974 +0.025776 +0.17872 +0.051307 +409.19 +214.74 +170.31 +171.8 +178.89 +99.285 +121.7 +3.25 +0.46682 +0.27197 +0.038411 +0.11383 +220.85 +128.53 +3456.6 +2369.7 +133.38 +904.17 +868.23 +1260.2 +3292.2 +1504.7 +1165.8 +2589.1 +4327.9 +46.512 +130.75 +174.84 +127.76 +783.3 +287.67 +235.85 +575.19 +61.65 +104.44 +92.054 +78.274 +65.097 +20.35 +103.39 +81.509 +50.337 +45.021 +251.01 +142.09 +960.98 +161.4 +161.57 +97.999 +185.49 +176.66 +20.015 +6.2954 +525.24 +68.706 +0.22691 +0.066399 +0.057007 +46.673 +116.12 +534.63 +442.88 +392.69 +179.41 +152.85 +65.772 +0.095101 +0.25768 +0.033214 +0.17778 +0.014181 +0.060031 +0.16431 +20.129 +3236 +61.693 +343.21 +965.7 +834.12 +713 +3136.9 +2154.5 +1684.5 +2235.7 +190.79 +21.416 +97.067 +145.73 +297.62 +128.56 +168.29 +224.18 +70.085 +1201.3 +302.88 +240.3 +108.07 +61.823 +32.249 +85.159 +39.965 +388.2 +319.55 +413.41 +224.91 +768.18 +245.77 +665.64 +62.988 +148.35 +125.86 +154.12 +233.24 +447.69 +79.678 +58.148 +0.12035 +153.03 +70.147 +138.95 +338.78 +339.17 +206.98 +95.374 +119.32 +0.061426 +0.084487 +1.1804 +0.29996 +0.019248 +0.026253 +0.027998 +62.864 +24.047 +21.726 +64.381 +207.61 +189.7 +563.36 +1214.8 +3294.3 +1658 +2824.1 +86.644 +145.2 +27.612 +70.64 +106.62 +28.807 +43.086 +56.782 +3162.7 +1376.1 +1386.1 +118.63 +250.56 +156.23 +176.66 +544.03 +159.88 +146.33 +898.93 +198.91 +447.5 +353.27 +627.32 +341.92 +63.292 +68.802 +153.75 +153.29 +185.97 +153.71 +524.92 +416.46 +259.45 +0.027143 +393.46 +96.603 +59.025 +147.99 +236.23 +234.55 +165.65 +0.41817 +0.10333 +0.11642 +0.069868 +0.13281 +0.10186 +0.060185 +45.732 +60.076 +21.233 +36.585 +48.326 +130.62 +189.66 +845.24 +780.01 +1908.3 +208.62 +167.75 +90.478 +60.41 +897.06 +263.36 +56.516 +39.65 +705.76 +1966.9 +1397.9 +1315.7 +1115.8 +623.37 +232.61 +146.36 +385.61 +197.86 +159.9 +90.327 +653.81 +279.15 +440.25 +150.54 +324.71 +188.91 +131.97 +138.71 +76.791 +179.92 +60.628 +27.495 +40.028 +105.76 +26.723 +738.87 +414.74 +56.036 +114.41 +123.45 +194.09 +91.101 +184.3 +0.25979 +0.019588 +0.099334 +0.21981 +0.099103 +0.024215 +0.088715 +66.723 +103.2 +17.681 +42.349 +69.797 +190.81 +288.01 +990.07 +1043.5 +48.275 +12.072 +288.3 +50.763 +810.42 +31.41 +80.397 +28.468 +92.216 +466.96 +2019.2 +997.98 +1088.8 +812.79 +417.17 +180.77 +56.066 +159.04 +222.37 +176.28 +105.5 +1115.1 +344.83 +330.7 +106.94 +297.76 +186.75 +343.78 +343.12 +58.288 +246.61 +104.77 +40.482 +25.593 +60.988 +28.976 +317.12 +900.53 +110.85 +165.11 +295.52 +160.01 +109.18 +212.56 +0.22673 +0.047076 +0.056549 +0.27241 +0.14521 +0.039006 +34.946 +119.14 +68.839 +20.158 +26.525 +109.2 +84.181 +180.95 +107.23 +26.654 +41.926 +12.439 +20.542 +0.62664 +91.266 +60.013 +48.837 +26.944 +85.27 +844 +2678.3 +1574.1 +1237.7 +334.01 +461.17 +235.47 +113.44 +91.406 +191.4 +115.61 +125.97 +1193.8 +740.37 +286.37 +91.103 +542.14 +232.26 +539.56 +112.08 +120.87 +212.24 +85.426 +91.637 +32.967 +99.588 +12.455 +10.973 +407.4 +175.17 +286.11 +312.26 +355.07 +150.02 +238.14 +0.034484 +0.013058 +0.0192 +0.10105 +68.43 +53.583 +72.121 +68.19 +55.213 +30.108 +36.227 +171.6 +157.41 +3075.8 +964.19 +27.825 +68.663 +12.995 +10.282 +12.274 +172.28 +36.891 +87.62 +26.678 +637.13 +1510.6 +3177.3 +1644.3 +1406.2 +517.34 +507.96 +400.61 +200.69 +180.53 +73.393 +193.07 +173.73 +1250.9 +796.15 +576.58 +515.23 +259.83 +344.4 +481.8 +159.91 +74.569 +124.6 +74.994 +106.75 +22.688 +176.46 +12.388 +502.16 +349.64 +2976.5 +331.75 +333.69 +328.73 +182.37 +191.19 +743.18 +755.27 +0.03503 +0.10898 +29.441 +35.312 +35.826 +111 +70.684 +72.816 +55.644 +58.629 +101.67 +2471.6 +860.18 +766.9 +883.26 +25.6 +5.1439 +8.7378 +15.627 +33.325 +211.9 +60.397 +101.69 +1332.5 +3060 +4609.7 +1957.1 +212.12 +530.62 +459.73 +188.94 +107.74 +168.26 +140.91 +162.16 +627.7 +725.06 +1303.5 +418.4 +361.09 +553.24 +477.98 +257.37 +0.068583 +62.281 +74.97 +38.838 +24.013 +56.757 +13.842 +877.41 +633.51 +1581.6 +0.047724 +268.64 +458.73 +169.88 +80.418 +677.29 +695.39 +255.96 +37.205 +16.765 +49.366 +63.452 +57.471 +123.72 +170.14 +66.505 +65.926 +5430.1 +2961.3 +1700.5 +1172.6 +928.9 +1575.7 +0.21461 +9.7226 +24.895 +429.78 +234.85 +61.834 +249.54 +740.19 +3068.4 +5828.7 +1520 +1229 +491.2 +627.36 +75.631 +141.23 +285.98 +133.21 +178.42 +319.06 +308.66 +1294.3 +461.18 +447.44 +529.36 +654.58 +0.14097 +0.15739 +42.862 +43.728 +62.933 +14.411 +45.803 +8.4943 +435.44 +819.18 +0.072792 +0.038644 +0.012103 +0.19201 +118.95 +105.25 +945.04 +357.43 +241.32 +874.51 +10.599 +44.553 +95.873 +95.984 +92.944 +131.29 +47.153 +3520.4 +3212.7 +4248.5 +2582.6 +2092.5 +1678.6 +53.135 +0.069471 +7.6486 +53.938 +206.7 +110.02 +74.563 +424.97 +1881.9 +5918.7 +4586.8 +1687.3 +1662 +465.73 +622.63 +0.037337 +164.78 +293.03 +103.96 +327.39 +463.18 +471.76 +391.69 +211.72 +320.64 +344.15 +931.69 +0.094937 +0.0906 +35.584 +60.108 +41.609 +13.12 +15.302 +779.02 +363.35 +306.45 +0.089787 +0.030569 +0.033739 +0.64366 +114.74 +92.952 +387.66 +228.84 +112.24 +803.74 +332.45 +1272.9 +134.58 +71.012 +45.468 +119.03 +58.841 +267.25 +2309.6 +2630.8 +1756.5 +2424 +2443.7 +60.331 +0.11907 +0.14167 +63.106 +187.46 +104.66 +185.77 +186.8 +26.522 +9706.3 +3577.8 +1967.4 +924.07 +375.15 +582.36 +1425.1 +1132.3 +409.33 +100.11 +233.65 +281.67 +800.7 +381.51 +504.34 +423.49 +731.06 +410.49 +347.21 +0.074024 +0.019557 +42.297 +38.303 +9.8744 +18.558 +229.57 +248.25 +407.76 +0.26271 +0.06502 +0.12599 +0.15635 +0.094413 +253.74 +530.71 +347.99 +164.4 +1678.3 +645.46 +1617.5 +403.34 +56.769 +54.905 +204.75 +74.958 +136.17 +636.16 +1576.1 +3172.8 +5961.7 +1326.8 +868.74 +53.337 +52.886 +0.066584 +155.57 +116.53 +210.28 +112.91 +71.816 +5.6472 +3418.1 +1590.3 +541.64 +602.74 +393 +2265.5 +1488.6 +0.037064 +167.37 +276.11 +264.12 +279.67 +1058.9 +527.69 +521.93 +642.74 +713.74 +128.96 +1093.4 +37.365 +49.628 +28.63 +9.1692 +16.203 +177.19 +295.33 +95.657 +0.061756 +0.091459 +0.24849 +0.33318 +0.086877 +501.08 +1349.8 +823.09 +316.56 +1861.4 +1065.3 +718.59 +271.42 +346.54 +92.738 +142.07 +61.35 +312.77 +503.15 +356.05 +3065.2 +14441 +3915.6 +1743.8 +325.8 +88.939 +118.41 +0.15326 +140.31 +217.4 +174.92 +48.1 +8.0063 +1607.6 +1693.6 +440.18 +416.11 +167.17 +3106 +211.86 +211.42 +268.28 +264.78 +282.61 +318.27 +1025.1 +1196.8 +846.18 +375.89 +354.41 +233.28 +65.734 +26.272 +25.831 +39.663 +12.807 +533.47 +379.67 +368.2 +164.27 +0.078384 +0.11554 +0.082844 +0.31618 +553 +198.53 +723.76 +484.41 +442 +3142.8 +2471.6 +1773.3 +193.73 +241.07 +358.73 +211.15 +56.826 +255.63 +262.19 +741.48 +459.67 +12887 +6208.7 +3007 +386.33 +2103.1 +77.422 +160.82 +128.79 +217.44 +131.81 +101.89 +11.502 +1738.5 +822.3 +1040.2 +179.04 +103.33 +464.96 +66.585 +207.9 +277.95 +311.92 +449.82 +248.89 +812.64 +1627.6 +709.11 +453.64 +378.45 +491.83 +64.011 +29.601 +35.975 +29.799 +664.47 +297.62 +513.99 +722.17 +142.55 +0.20575 +0.058017 +0.15077 +207.84 +560.63 +454.59 +563.35 +1058.5 +351.9 +3496.2 +2501.5 +3437.6 +270.15 +457.24 +409.05 +249.73 +114.22 +213.91 +426.6 +297.57 +262.89 +938.64 +7730.1 +2040.3 +838.85 +1542.2 +168.08 +307.29 +143.34 +294.1 +212.66 +115.91 +9.7039 +12.762 +1601 +377.93 +597.62 +138.19 +171.62 +65.317 +231.28 +138.16 +302.66 +1388.8 +457.5 +614.03 +686.75 +638.82 +440.39 +120.63 +77.634 +76.019 +51.889 +76.537 +0.22543 +284.39 +352.74 +367.84 +547.59 +381.31 +0.13935 +0.25902 +203.51 +90.192 +273.14 +538.77 +424.09 +1983.5 +473.25 +2627.3 +1195.4 +5353.6 +1206.2 +532.9 +673.63 +165.7 +162.53 +141.46 +408.17 +317.96 +271.79 +753.58 +1009.3 +0.072567 +1032.2 +187.01 +311.51 +268.02 +126.12 +110.86 +189.38 +150.68 +33.989 +15.462 +231.63 +316.34 +380.13 +115.43 +130.05 +71.707 +562.86 +477.46 +527.93 +1558.3 +1960.3 +224.8 +525.93 +416.59 +191.89 +82.503 +140.25 +106.87 +57.258 +0.021598 +431.39 +455.88 +904.79 +550.3 +393.87 +423.39 +145.38 +51.405 +108.13 +51.997 +362.21 +364.75 +656.58 +2086.6 +528.73 +1289.6 +923.89 +2732.1 +331.25 +884.78 +341.21 +155.31 +149.71 +218.46 +119.18 +174.57 +452.53 +773.07 +679.24 +266.37 +142.94 +97.683 +380.37 +149.4 +134.4 +121.81 +500.84 +501.78 +67.229 +31.939 +462.75 +341.69 +879.5 +209.23 +55.529 +86.01 +82.324 +928.47 +291.68 +522.37 +1145 +306.36 +218.21 +705.79 +134.13 +151.92 +179.66 +97.813 +24.116 +0.010359 +0.010067 +1127 +1205.6 +656.76 +620.3 +267.97 +216.94 +88.884 +165.88 +98.846 +377.21 +183.35 +700.05 +3735.4 +572.4 +1132.6 +730.33 +446.4 +287 +632.54 +393.18 +434.06 +158.4 +191.33 +84.412 +83.693 +939.47 +443.7 +941.02 +199.8 +115.8 +223.6 +465.88 +246.73 +136.06 +261.98 +700.52 +1562.8 +146.32 +127.78 +592.48 +263.74 +190.22 +161.35 +46.306 +56.946 +82.659 +2114 +115.17 +463.11 +0.14831 +245.82 +191.73 +184.58 +371.8 +326.49 +258.87 +63.576 +0.019762 +431.93 +159.85 +475.11 +1040.9 +1296 +841.54 +402.99 +480.07 +51.768 +164.51 +35.035 +215.17 +0.18259 +0.059901 +0.022297 +0.057724 +1241.7 +511.46 +711.68 +609.18 +666.9 +465.13 +290.3 +197.53 +139.85 +73.956 +47.989 +380.39 +311.4 +436.29 +507.97 +186.51 +99.542 +245.37 +266.8 +279.22 +332.02 +665.03 +1611 +1773.7 +4378.1 +74.561 +1272.9 +70.506 +187.63 +112.83 +107.31 +81.716 +1565.5 +187 +0.12202 +0.062345 +136.1 +293.82 +95.402 +315.8 +902.47 +118.94 +150.4 +96.962 +273.84 +1142.5 +801.58 +2156.8 +928.56 +834.15 +251.38 +1995.9 +0.0414 +0.1812 +0.083538 +0.049005 +0.020769 +0.037798 +0.088131 +0.11301 +484 +287.66 +884.71 +751.57 +661.48 +659.77 +887.06 +49.447 +41.445 +43.865 +90.55 +189.94 +189.66 +340.72 +485.29 +172.36 +376.19 +761.83 +5097.5 +1003.5 +652.8 +812.82 +920.85 +1189.6 +4819.4 +6391 +0.16031 +578.67 +96.86 +209.33 +141.24 +79.787 +254.55 +173.46 +0.1296 +0.13914 +0.067583 +305.9 +145.44 +168.87 +1369.7 +2647.2 +307.19 +105.53 +45.156 +1113.6 +707.42 +1885.1 +444.49 +508.44 +338.09 +762.05 +0.052344 +0.21712 +0.19312 +0.067138 +0.079995 +0.20295 +0.45774 +0.22191 +0.078884 +269.33 +1023.1 +1164.5 +1257.6 +660.13 +967.61 +47.455 +73.362 +25.471 +136 +288.71 +177.45 +287.67 +678.17 +280.27 +676.46 +2562.5 +5777.9 +858.92 +1096.5 +1223.6 +1513.9 +1692.3 +5694.7 +2247.1 +3084.9 +2246.8 +155.06 +93.068 +248.55 +57.639 +353.78 +174.1 +244.1 +0.2585 +0.096308 +0.067533 +290.04 +243.93 +1592.3 +3479 +1057 +726.94 +1480.3 +716.51 +357.35 +980.22 +430.01 +382.69 +354.13 +439.31 +0.11339 +0.30329 +0.094161 +0.15305 +0.092782 +0.95161 +0.29201 +0.12462 +1.1793 +116.13 +949.25 +1969.5 +1249.3 +2114.1 +1140.5 +58.849 +118.01 +21.139 +142.71 +196.98 +137.62 +259.94 +1482.5 +238.6 +462.89 +2906.3 +6953.8 +649.48 +178.38 +863.76 +1543.3 +1559.9 +2029.5 +1731.5 +1787.4 +2129 +795.17 +0.32004 +28.991 +50.484 +612.57 +141.55 +122.37 +134.45 +0.041731 +70.702 +51.923 +216.28 +993.01 +2016 +2013.5 +438.78 +1260.8 +746.74 +444.52 +351.23 +325.06 +543.78 +0.16315 +0.28269 +1.9011 +0.20684 +0.11267 +0.13311 +0.29577 +0.21237 +0.14125 +0.20694 +1143.2 +287.82 +1023.5 +1540.8 +1572.5 +1975.2 +1300.3 +46.896 +223.61 +110.88 +119.06 +144.77 +230.61 +362.28 +1128.7 +377.61 +743.6 +850.51 +499.9 +79.682 +81.761 +473.11 +1312.9 +1521.3 +1697.9 +1057.8 +1481.2 +138.08 +234.67 +482.04 +41.854 +70.885 +852.37 +208.12 +102.56 +431.75 +800.76 +149.19 +1667.3 +366.58 +567.42 +1308.7 +2441.6 +427.12 +204.49 +373.9 +393.3 +677.59 +54.114 +105.66 +0.19516 +0.86463 +0.40842 +0.63739 +0.11629 +0.20011 +0.12786 +0.2272 +0.65623 +0.145 +293.95 +435.86 +1092.5 +2019.2 +2179.2 +2114.2 +958.5 +52.593 +257.85 +326.96 +131.97 +129.86 +236.59 +369.02 +633.38 +383 +617.52 +562.76 +264.44 +46.024 +78.95 +426.66 +341.95 +752.15 +2187.7 +1842.8 +1619.1 +0.17471 +0.028696 +0.069955 +0.10603 +66.076 +10.379 +3.3762 +180.07 +171.89 +530.07 +1285.9 +918.53 +609.83 +670.38 +1298.7 +1063.2 +302.36 +235.14 +518 +592.44 +845.55 +0.11983 +71.873 +36.694 +0.38875 +0.19726 +0.43545 +0.04583 +0.077717 +0.12011 +0.10777 +0.211 +0.0708 +402.34 +404.73 +1402 +1299.1 +1455.1 +1231.3 +842.34 +109.15 +852 +392.77 +195.78 +93.879 +420.81 +595.3 +957.1 +134.47 +523.36 +629.52 +369.6 +47.113 +165.11 +450.18 +918.71 +1559.8 +2983.5 +866.86 +0.2149 +0.23093 +0.025442 +0.05904 +0.060502 +0.42906 +5.5339 +2.0516 +25.895 +18.375 +1486 +1062.2 +870.07 +878.63 +523.94 +1583.7 +1303.7 +606.72 +315.82 +263.27 +720.26 +1001.4 +0.32825 +0.19151 +0.04952 +28.273 +25.594 +0.17304 +0.10358 +0.062688 +0.032039 +0.066776 +0.11724 +0.053414 +338.72 +356.68 +670.42 +651.9 +1206.8 +2563.6 +2207.4 +123.79 +1133.4 +227.94 +99.542 +251.43 +420.14 +675.36 +190.71 +142.36 +305.95 +529.74 +381.57 +34.02 +281.94 +408.38 +1053.2 +1533.1 +85.86 +54.615 +0.045374 +0.018717 +0.052816 +0.15296 +0.10399 +0.26042 +2.0728 +10.824 +26.506 +33.959 +26.444 +1596.8 +715.5 +647.18 +437.92 +1536.1 +1037.4 +151.9 +143.99 +0.23796 +0.26085 +440.9 +987.14 +1110.2 +0.04756 +42.925 +31.724 +0.063343 +0.11335 +0.11661 +0.33646 +0.081637 +0.044376 +0.033464 +399.57 +634.47 +378.25 +251.18 +2234 +3176.5 +5028.2 +119.39 +191.37 +432.28 +1214.4 +259.53 +402.38 +399.25 +135.9 +120.39 +288.26 +1529.4 +715.89 +64.168 +235.29 +296.25 +67.732 +89.798 +80.856 +47.942 +84.504 +0.016953 +217.84 +25.735 +116.31 +42.733 +4.3546 +8.2096 +3.1987 +29.043 +87.264 +2195.9 +1737.5 +271.35 +907.2 +90.34 +154.6 +1210 +499.89 +365.24 +0.088524 +0.035878 +738.84 +339.29 +1786.6 +73.325 +41.285 +0.062174 +0.31851 +0.31385 +0.069932 +0.029129 +0.010351 +1044.1 +132.81 +151.32 +199.84 +217.41 +1888.5 +1323.9 +11074 +87.675 +162.49 +616.44 +1663.6 +379.04 +439.35 +378.99 +218.68 +161.71 +383.25 +1563.3 +639.04 +0.10046 +85.418 +114.94 +211 +97.754 +48.24 +55.1 +395.76 +303.97 +87.969 +18.556 +33.902 +9.5661 +2.7022 +4.9639 +10.163 +10.762 +193.61 +240.11 +1197.4 +390.26 +1074.4 +88.767 +0.12781 +964.92 +465.55 +250.53 +188.62 +0.062791 +0.1782 +0.058732 +3739 +108.34 +50.934 +41.785 +0.34159 +0.13706 +0.15684 +0.061521 +895.89 +356.27 +1748.3 +138.95 +107.55 +402.15 +1097.2 +956.96 +2323.6 +108.27 +287.88 +738.59 +1166.4 +486.63 +1031.1 +549.68 +1884.8 +131.24 +1201.6 +539.86 +90.43 +271.83 +40.584 +109.68 +190.63 +40.99 +49.597 +45.415 +333.59 +154.69 +138.68 +44.657 +36.135 +19.532 +4.7297 +7.7976 +8.9658 +5.7267 +56.34 +158.58 +681.4 +501.84 +3357.1 +4292.1 +104.53 +0.1353 +0.051941 +207.97 +375.6 +166.84 +457.15 +0.13671 +0.058822 +149.74 +110.95 +105.9 +114.77 +25.11 +0.05079 +2001.1 +652.04 +560.69 +2134.2 +692.44 +887.08 +217.61 +591.85 +1140.4 +2569.6 +577.13 +498.42 +318.15 +841 +1848.2 +36.32 +574.8 +917.55 +1476.8 +786.21 +265.55 +116.76 +258.44 +59.16 +104.83 +144.92 +69.731 +24.484 +129.36 +159.51 +214.09 +14.247 +32.715 +38.476 +20.739 +8.9799 +7.2342 +16.101 +16.781 +488.44 +538.64 +398.34 +828.09 +106.67 +41.871 +126.78 +0.086474 +0.10149 +0.069468 +1189.7 +189.32 +639.72 +1187.5 +113.05 +132.44 +292.97 +146.56 +64.735 +38.816 +18.292 +21.443 +669.52 +600.39 +123.62 +157.3 +571.08 +1317.9 +523.64 +1525.3 +0.11599 +756.27 +282.38 +699.47 +625.81 +159.69 +53.169 +1012.5 +593.44 +700.98 +433.49 +486.72 +42.075 +151.78 +65.416 +92.607 +102.08 +80.555 +63.733 +130.89 +112.36 +40.615 +16.801 +18.013 +33.207 +17.977 +7.4554 +7.0424 +0.035235 +502.52 +440.23 +178.9 +140.41 +418.76 +178.72 +153.36 +144.63 +0.034636 +0.01696 +0.066269 +37.02 +7.4215 +3.465 +49.714 +384.99 +0.2156 +0.97349 +0.53516 +96.312 +75.404 +50.96 +51.966 +24.959 +465.32 +130.91 +71.074 +89.912 +208.03 +54.671 +25.457 +25.383 +1533.3 +644.72 +280.6 +148.63 +205.22 +1.6084 +0.17917 +470.91 +798.8 +30.033 +116.39 +21.94 +163.12 +188.65 +78.267 +82.16 +87.656 +130.2 +78.487 +64.52 +63.097 +23.338 +41.577 +22.427 +0.26698 +0.07227 +2772.6 +1398.9 +643.92 +225.64 +217.87 +371.62 +340.65 +12.813 +54.096 +103.33 +29.891 +54.058 +57.133 +119.67 +18.702 +273.22 +804.63 +355.27 +255.94 +502.37 +320.26 +310.2 +153.4 +114.34 +24.718 +15.925 +112.02 +217.94 +7.3534 +39.109 +44.272 +22.159 +38.782 +52.373 +30.385 +426.14 +424.47 +718.53 +1029.4 +0.19847 +0.20153 +215.77 +376.5 +44.385 +73.167 +18.186 +297.67 +212.72 +199.79 +166.16 +89.559 +96.9 +153.11 +65.36 +35.015 +32.336 +69.954 +89.352 +143.53 +2648.3 +2124.5 +2055.1 +778.89 +283.17 +221.32 +300.02 +38.698 +15.083 +46.053 +10.561 +71.144 +91.034 +82.09 +0.12253 +0.89744 +0.076039 +477.82 +501.41 +400.27 +441.93 +193.22 +339.72 +257.01 +72.82 +28.552 +43.439 +52.568 +19.558 +46.297 +24.858 +121.14 +17.47 +37.452 +0.072465 +48.038 +581.68 +1130.3 +626.42 +360.05 +0.062185 +197.74 +365.28 +180.19 +68.968 +67.71 +41.945 +277.72 +402.31 +154.34 +143.06 +338.26 +158.11 +62.766 +20.549 +41.364 +33.542 +106.77 +82.653 +200.85 +2148.6 +1275 +1298.1 +265.27 +323.46 +379.42 +0.32796 +47.903 +41.26 +58.991 +31.091 +173.39 +0.1605 +0.12609 +0.17936 +0.64501 +0.17449 +0.074845 +113.57 +260.54 +464.95 +494.73 +31.947 +234.32 +68.536 +63.576 +47.772 +25.674 +18.393 +142.49 +0.024056 +0.097862 +0.073398 +0.21122 +0.41314 +451.36 +1749.5 +589.68 +442.76 +721.83 +3023.2 +220.99 +703.55 +231.9 +106.1 +47.596 +72.048 +107.79 +357.36 +195.69 +185 +37.987 +42.876 +36.504 +134.01 +139.19 +24.233 +109.73 +126.86 +198.37 +759.91 +530.42 +310.9 +180.98 +0.1226 +36.767 +77.535 +64.672 +48.156 +52.085 +31.238 +0.10014 +0.15015 +0.10824 +0.1616 +0.1384 +0.12659 +0.098371 +69.073 +103.85 +276.22 +386.44 +63.309 +24.329 +56.721 +46.97 +26.884 +23.512 +998.77 +34.931 +87.25 +0.067415 +0.86133 +0.076759 +0.18656 +48.34 +27.538 +736.54 +381.83 +246.49 +3545.6 +1.2773 +923.19 +247.82 +293.97 +146.83 +129.83 +71.032 +143.47 +157.1 +70.291 +57.068 +18.112 +256.04 +95.5 +150.79 +19.047 +106.18 +142.36 +627.8 +854.45 +482.76 +0.041095 +482.13 +479.89 +34.668 +32.237 +11.149 +21.67 +36.577 +0.055264 +0.030211 +0.18916 +0.041197 +0.23012 +0.25767 +0.18535 +68.385 +34.255 +114.24 +558.09 +375.53 +67.427 +124.55 +66.604 +131.56 +26.305 +1926.7 +785.01 +0.44827 +0.04744 +59.846 +0.77496 +2.5935 +0.54714 +29.221 +17.378 +5.937 +209.38 +259.79 +868.79 +1739.2 +1014.6 +299.42 +205.64 +153.05 +85.944 +126.24 +188.37 +648.38 +172.7 +138.04 +66.191 +181.49 +95.369 +199.56 +22.052 +47.261 +74.439 +1052.5 +1013.8 +0.021778 +0.03919 +337.48 +1055.3 +50.16 +0.021448 +0.063402 +17.59 +12.243 +0.039517 +0.038394 +0.025718 +0.10192 +0.36288 +0.32193 +0.54223 +30.582 +16.386 +92.145 +304.81 +383.42 +138.95 +179.72 +16.896 +92.312 +860.9 +628.1 +657.3 +290.21 +0.07433 +0.073695 +0.48336 +0.87667 +0.71858 +15.273 +10.698 +8.2003 +12.525 +168.34 +1166.4 +844.42 +586.8 +232.44 +608.06 +115.58 +94.907 +161.09 +231.07 +520.7 +1039 +0.13615 +0.18525 +171.62 +1927.5 +104.85 +39.486 +30.53 +114.67 +594.84 +178.76 +0.071796 +0.11671 +755.1 +1745.4 +186.86 +0.024138 +19.824 +27.499 +18.195 +197.23 +0.30233 +0.083009 +0.5889 +0.79994 +0.21453 +0.28394 +0.090087 +29.891 +24.294 +145.38 +179.98 +147.61 +210.05 +92.321 +41.721 +619.25 +295.13 +556.6 +379.09 +596.95 +0.12375 +0.40087 +0.88514 +0.32101 +13.412 +7.8664 +2.9874 +11.833 +11.58 +18.667 +681.14 +311.61 +316.88 +342.53 +179.22 +157.69 +266.2 +252.09 +525.57 +348.8 +0.070855 +0.11907 +117.89 +1087.3 +1101.7 +49.618 +31.649 +45.615 +221.72 +138.91 +226.83 +1036.4 +875.82 +2119.6 +211.48 +0.018352 +0.028232 +13.519 +36.264 +169.34 +0.066552 +0.13617 +0.6378 +4542.5 +726.64 +30.05 +51.642 +25.493 +30.622 +157.78 +67.765 +139.04 +177.89 +37.449 +44.514 +0.14375 +487.75 +558 +265.24 +443.11 +1384.5 +0.80981 +0.38665 +0.33736 +4.7574 +26.617 +4.7194 +14.607 +14.744 +147.59 +90.592 +456.43 +408.08 +81.184 +67.094 +31.248 +27.379 +281.48 +324.56 +176.9 +0.13061 +71.589 +181.24 +254.15 +573.5 +466.88 +20.069 +55.479 +70.557 +139.58 +127.47 +1490.6 +788.72 +1028 +0.038751 +0.015453 +37.693 +20.275 +32.217 +167.26 +125.91 +4867.5 +8877.5 +4744 +817.33 +35.749 +59.325 +958.25 +195.81 +258.71 +63.075 +156.37 +150.81 +431.78 +1187.2 +0.028357 +375.99 +838.73 +222.5 +394.75 +1870.8 +0.30641 +0.14258 +0.42786 +20.021 +11.69 +5.4684 +19.84 +652.16 +492.08 +174.88 +328.01 +51.1 +97.463 +65.539 +55.23 +7.7214 +14.614 +37.193 +102.32 +2533.2 +585.09 +185.49 +216.1 +651.95 +520.27 +300.72 +58.958 +81.609 +97.312 +75.948 +1433.3 +907.35 +1241.7 +0.05995 +0.070423 +0.44508 +20.826 +59.671 +697.72 +274.65 +346.65 +169.15 +241.8 +290.14 +71.349 +0.47021 +793.28 +224.12 +273.63 +146.82 +148.06 +179.88 +232.27 +613.69 +9.4024 +0.096808 +760.82 +345.81 +430.79 +2224 +459.39 +0.19736 +0.1455 +62.836 +18.177 +204.45 +121.54 +632.85 +862.34 +70.088 +138.22 +129.8 +47.968 +29.455 +66.806 +13.889 +14.37 +43.484 +36.818 +854.44 +1062 +255.67 +201.24 +550.02 +5286.2 +296.44 +155.38 +99.316 +40.106 +169.44 +740.98 +1306.1 +1103.8 +0.25605 +0.35843 +2106 +484.96 +2220.6 +834.45 +330.34 +509.35 +2414.1 +2819.7 +635.36 +0.07977 +0.32448 +520.02 +222.09 +241.45 +226.28 +125.64 +340.08 +299.6 +435.55 +9.7728 +0.1244 +0.05853 +206.18 +827.09 +2866.4 +1257.7 +0.45667 +0.36313 +83.731 +167.17 +190.1 +97.632 +296.33 +335.35 +85.532 +310.68 +219.25 +155.37 +31.289 +61.146 +27.941 +13.055 +46.185 +183.23 +1213.5 +784.46 +318.82 +195.94 +110.56 +3865.2 +3891.2 +85.209 +224.04 +34.712 +115.14 +518.04 +876.01 +1716.3 +428.32 +315.64 +846.44 +372.49 +1481.4 +1189.4 +261.56 +580.89 +3189 +2509.4 +0.10297 +0.046378 +0.074906 +0.31122 +145.46 +334.43 +538.64 +393.19 +74.503 +114.16 +135.53 +5.8721 +11.169 +0.13823 +124.64 +418.85 +1429.5 +710.15 +335.69 +0.52072 +88.318 +59.52 +152.28 +128.36 +459 +248.28 +117.47 +450.69 +0.17389 +288.08 +27.099 +112.61 +40.598 +28.644 +49.515 +394.32 +3566.4 +1099.1 +335.89 +1098.3 +0.011366 +3284.4 +2602.6 +4333 +127.79 +51.8 +264.84 +499.72 +373.39 +557.13 +436.43 +493.29 +660.56 +479.86 +276.32 +203 +210.16 +391.62 +0.20188 +0.070393 +0.049973 +0.08111 +0.073274 +0.095156 +681.82 +942.6 +465.85 +217.13 +103.9 +65.016 +96.499 +13.8 +9.1091 +37.956 +79.985 +234.87 +999.19 +610.2 +454.25 +0.091811 +85.753 +61.127 +121.42 +96.061 +446.39 +237.38 +101.94 +1025.5 +489.33 +242.65 +325.84 +156.06 +40.599 +67.447 +148.68 +1049.7 +2957.5 +1510.6 +630.23 +1094.6 +113.4 +1730.1 +1956.6 +2528 +1088.7 +129.32 +634.36 +369.34 +410.17 +476 +469.77 +14.374 +17.996 +126.14 +289.74 +605.85 +210.27 +391 +0.042449 +0.16027 +0.016946 +0.015409 +0.068875 +43.138 +290.34 +818.35 +641.98 +482.93 +136.26 +77.203 +2.7069 +4.0845 +5.8779 +15.019 +44.188 +414.64 +1083.9 +921.65 +251.23 +0.13003 +90.357 +42.585 +86.969 +64.45 +876.14 +234.04 +56.997 +607.64 +490.28 +44.936 +354.53 +80.268 +27.515 +89.532 +155.06 +906.25 +904.35 +1330.4 +535.8 +1563.8 +3740.5 +1248.5 +2045.5 +1590.2 +2510.2 +52.266 +111.12 +459.63 +683.51 +685.6 +15.426 +12.24 +19.932 +150.57 +189.68 +286.29 +189.83 +0.08544 +0.18577 +0.023424 +0.08264 +0.052771 +55.624 +134.85 +504.88 +1489.3 +827.4 +517.05 +122.22 +8.8171 +1.9658 +2.0627 +7.633 +16.331 +23.068 +960.95 +2077 +774.08 +132.74 +0.36926 +82.21 +110.38 +54.136 +184.39 +196.02 +205.28 +125.46 +452.06 +313.96 +58.049 +14.138 +53.612 +25.246 +81.582 +266.45 +1284.3 +1107.6 +1339.7 +1063.3 +1211 +24.905 +1164.2 +1491.3 +1946.3 +0.085308 +0.019249 +48.907 +759.51 +1457.7 +64.646 +14.602 +18.561 +35.899 +60.252 +611.88 +506.13 +753.37 +0.097946 +0.025892 +0.035392 +0.045721 +0.15179 +172.56 +350.25 +776.41 +765.26 +720.35 +453.6 +16.471 +13.518 +34.595 +0.026014 +10.297 +7.36 +19.813 +39.628 +2455 +1968.5 +172.31 +0.52791 +85.927 +79.914 +106.9 +181.64 +348.37 +271.77 +180.58 +339.07 +240.03 +81.512 +15.008 +58.916 +45.367 +70.907 +126.54 +1357.8 +734.45 +844.5 +1266 +1131.1 +22.526 +0.17569 +539.77 +577.78 +267.14 +310.94 +375.76 +181.61 +875 +74.623 +284.96 +293.64 +2150.2 +803.33 +530.64 +825.42 +470.08 +0.017569 +0.055829 +0.045731 +0.063918 +220.91 +345.71 +335.74 +768 +1187.2 +0.1844 +10.574 +24.056 +11.499 +20.784 +18.517 +0.049389 +7.2861 +9.3063 +31.541 +46.434 +4960 +111.13 +0.28127 +132.79 +88.241 +178.62 +197.21 +640.15 +541.34 +522.28 +294.69 +405.12 +273.26 +38.131 +420.76 +45.479 +91.787 +0.85474 +1272.7 +679.76 +582.39 +567.89 +955.26 +32.407 +889.39 +1324.6 +355.64 +295.44 +221.51 +557.73 +42.52 +72.62 +102.29 +150.01 +133.33 +143.63 +212.3 +370.14 +309.8 +558.49 +0.023853 +0.12282 +0.24652 +172.19 +208.16 +204.22 +383.75 +327.65 +2180.6 +0.32733 +10.5 +8.8149 +20.456 +25.376 +13.497 +150.37 +45.274 +11.425 +18.958 +46.069 +19.463 +0.30165 +0.16494 +129.46 +71.32 +1351.9 +214.33 +1241.8 +455.46 +1405.8 +186.4 +301.11 +422.31 +77.404 +161.28 +235.82 +0.70436 +0.50665 +10294 +578.6 +205.7 +378.31 +247.09 +1722.7 +1064.5 +860.58 +59.366 +125.87 +251.88 +142.26 +50.057 +4358.2 +123.92 +233.85 +317.28 +230.24 +323.35 +237.27 +685.12 +401.23 +466.28 +0.11989 +394.21 +218.89 +144.43 +225.62 +236.91 +0.030465 +0.11116 +0.095551 +0.55263 +9.072 +18.694 +17.052 +13.882 +71.084 +31.57 +128.3 +20.847 +42.064 +17.91 +7.5684 +0.40808 +130.04 +147.14 +590.84 +1294.9 +967.55 +851.26 +475.61 +141.3 +411.69 +802.86 +162.96 +134.36 +230.06 +117.62 +0.36558 +6324.8 +169.88 +296.16 +473.38 +336.53 +1806.5 +2030.7 +173.86 +62.638 +100.26 +440.71 +114.14 +0.40009 +0.30926 +117.54 +110.41 +152.75 +119.06 +193.18 +212.46 +369.12 +0.1836 +508.84 +728.21 +938.31 +292.01 +231.21 +293.95 +304.89 +0.033314 +0.10135 +0.15282 +0.6723 +7.3363 +237.48 +66.958 +12.629 +61.721 +42.823 +253.66 +73.954 +24.763 +18.83 +8.2548 +30.659 +75.263 +970.26 +541.67 +799.48 +1033.2 +581.86 +502.57 +940.34 +420.19 +800.28 +209.65 +101.09 +41.289 +142.82 +62.857 +59.003 +176.32 +115.49 +300.26 +303.52 +3794.6 +87.911 +60.359 +65.53 +112.22 +173.64 +106.76 +34.379 +126.42 +137.34 +91.491 +101.56 +62.362 +173.72 +145.94 +232.28 +9.5405 +0.1921 +0.16813 +664.93 +610.52 +130.54 +192.13 +313.85 +0.15819 +0.1108 +0.052321 +252.69 +93.038 +123.49 +34.536 +19.187 +13.554 +40.676 +133.78 +0.012091 +40.135 +28.928 +20.715 +35.891 +1993.6 +571.15 +581.84 +466.08 +877.04 +470.9 +65.902 +1482.9 +2285.2 +635.27 +305.04 +130.16 +38.112 +97.83 +127.99 +46.226 +96.815 +74.322 +52.556 +149.49 +25.225 +72.068 +72.47 +143.92 +157.84 +0.16203 +37.039 +39.236 +75.323 +232.44 +1630.5 +2434 +121.68 +456.96 +227.48 +130.49 +29.916 +0.58132 +0.067805 +57.089 +239.3 +1148 +136.89 +112.34 +79.663 +0.13417 +0.19175 +0.12631 +260.86 +194.99 +63.405 +9.054 +15.465 +40.581 +0.023232 +0.021142 +0.0293 +21.144 +22.945 +87.37 +1917.5 +915.26 +612.26 +668.67 +735.86 +141.87 +736.14 +560.49 +3120 +354.12 +556.35 +73.302 +59.177 +126.23 +101.26 +32.884 +73.783 +39.784 +42.599 +46.013 +55.69 +63.69 +127.89 +361.11 +44.252 +48.617 +76.659 +47.136 +36.383 +0.086091 +0.13785 +1529.2 +83.681 +918.35 +329.61 +238.79 +34.485 +384.83 +0.40877 +0.11751 +184.83 +853.47 +937.13 +625.27 +30.09 +98.193 +66.893 +0.16512 +712.46 +250.24 +239.78 +16.532 +0.022769 +97.087 +0.082615 +0.030556 +0.039495 +0.076921 +0.03297 +0.13081 +1880.1 +790.72 +571.21 +130.62 +97.113 +83.986 +188.47 +3240.8 +2285.4 +424.58 +533.96 +822.4 +790.61 +190.68 +530.97 +1025.2 +517.29 +57.51 +46.469 +32.37 +68.906 +35.758 +46.614 +37.095 +22.332 +41.674 +128.95 +33.061 +59.754 +0.061617 +0.16163 +0.085615 +61.675 +2246.1 +529.12 +196.44 +70.135 +506.35 +1803.9 +321.68 +842.86 +568.03 +722.48 +340.02 +0.11562 +0.42642 +0.78126 +52.659 +60.41 +115.34 +138.52 +18.54 +0.013211 +0.0147 +0.067439 +0.055727 +0.094388 +0.17427 +0.029811 +0.090882 +2428 +830.66 +617.91 +78.124 +109.96 +48.02 +205.06 +157.11 +116.5 +147.26 +622.43 +677.23 +447.27 +366.81 +599.54 +999.03 +1350.8 +430.52 +54.272 +48.573 +115.9 +84.68 +86.391 +9.7096 +6.48 +30.083 +60.887 +0.055544 +0.11493 +0.29547 +0.10904 +0.046772 +164.55 +848.45 +770.61 +155.78 +219.23 +620.98 +668.22 +1321.1 +659.43 +823.87 +295.02 +227.58 +0.33073 +0.21478 +0.21812 +0.88187 +87.352 +94.317 +79.113 +55.839 +25.99 +0.11826 +0.0463 +0.20368 +0.15934 +0.20266 +0.078118 +0.17133 +1269.2 +694.96 +898.92 +130.92 +98.952 +19.79 +274.99 +67.228 +61.322 +407.21 +242.26 +738.27 +357.11 +250.49 +633.53 +1035.8 +1193.8 +66.531 +119.53 +8.9408 +65.479 +131.95 +109.4 +20.582 +17.322 +19.266 +0.25694 +0.30751 +0.21913 +0.1033 +0.032373 +0.1699 +370.56 +1102.2 +899.91 +310.19 +116.45 +471.68 +2196 +0.2517 +539.89 +367.52 +279.07 +248.3 +120.78 +1.4623 +0.56745 +0.12788 +0.16452 +0.2811 +69.861 +120.9 +24.2 +0.057783 +0.053848 +0.34549 +0.30368 +0.11393 +0.13671 +0.049957 +4577.6 +1355.6 +1169.1 +1865.3 +1300.1 +22.046 +276.4 +38.201 +112.11 +141.8 +121.27 +812.69 +339.75 +340.72 +1749.8 +1232.2 +790.75 +119.01 +35.604 +19.792 +55.792 +91.544 +83.599 +39.487 +14.554 +28.944 +0.095537 +0.34267 +0.12202 +0.072427 +0.092746 +0.10909 +0.055135 +1129.7 +1053 +659.98 +118.1 +280.91 +1990.4 +0.10124 +0.095934 +186.43 +173.01 +231.54 +162.3 +160.33 +170 +0.19699 +0.084227 +0.12183 +50.555 +115.97 +239.76 +202.39 +565.23 +0.050472 +0.13295 +0.15889 +0.00915 +0.064198 +0.16449 +2256.4 +936.02 +795.29 +1198 +346.32 +722.52 +22.909 +74.286 +417.16 +113.5 +453.31 +206.37 +727.65 +1359.7 +2645 +266.94 +111.19 +46.713 +35.39 +33.117 +92.538 +93.318 +40.804 +22.519 +73.753 +202.11 +0.18169 +0.10232 +0.088391 +0.24022 +392.76 +1537.5 +3303.2 +1546.3 +473.38 +327.6 +569.55 +506.92 +181.99 +504.2 +0.20371 +108.06 +205.52 +163.71 +209.54 +235.48 +308.7 +615.5 +0.025609 +0.10415 +15.16 +18.585 +206.75 +614.82 +1118.3 +0.061337 +0.079986 +0.060736 +0.079614 +0.2289 +144.87 +46.092 +68.88 +1366.4 +380.28 +200.68 +315.58 +111.99 +209.48 +163.25 +277.06 +295.44 +219.27 +2084.6 +3052.7 +132.12 +176.53 +92.845 +66.584 +54.093 +46.612 +78.561 +34.317 +146.96 +86.729 +205.64 +55.682 +0.079042 +0.14217 +0.1425 +739.8 +1316.8 +2588 +4526.7 +2313.3 +380.75 +135.57 +379.73 +367.82 +560.19 +970.25 +71.486 +79.599 +97.699 +82.987 +105.01 +882.96 +489.95 +599.38 +698.06 +453.94 +22.206 +75.62 +335.74 +587.02 +282.35 +0.040447 +0.088218 +0.16329 +77.803 +77.391 +119.72 +12.219 +5.9061 +156.03 +278.35 +376.06 +437.36 +190.64 +122.54 +565.25 +682.91 +359.68 +2707.6 +0.072793 +95.906 +114.09 +75.068 +34.858 +60.153 +26.578 +47.649 +282.6 +130.3 +84.802 +140.3 +67.09 +30.589 +0.059206 +742.48 +875.83 +639.03 +1406.1 +4081.3 +929.86 +1336.9 +323.74 +254.24 +241.76 +661.21 +1313.4 +43.589 +42.922 +66.418 +49.554 +134.98 +60.055 +1197.3 +761.6 +986.42 +399.33 +482.13 +162.2 +407.89 +1052.3 +304.01 +0.063463 +0.047209 +0.024671 +63.195 +66.695 +51.83 +53.94 +113.37 +140.95 +114.71 +229.29 +1029.4 +1612.3 +5387.4 +5003.9 +243.19 +9380.7 +923.37 +50.165 +186.82 +277.69 +113.39 +67.843 +59.106 +15.583 +25.626 +20.198 +222.9 +23.408 +83.357 +48.15 +48.912 +0.16764 +656.39 +509.97 +250.51 +527.53 +822.98 +763.49 +1325.4 +441.61 +384.69 +252.12 +0.62489 +0.050631 +41.746 +43.172 +74.317 +60.967 +55.314 +5334.2 +3800 +2996.8 +1119.5 +260.93 +231.5 +307.88 +213.3 +443.96 +392.29 +0.22197 +0.08749 +0.030671 +727.22 +124.38 +84.005 +81.797 +292.63 +247.03 +115.11 +291.74 +881.73 +2682.8 +4328 +5540.3 +5323.4 +86.462 +281.39 +81.598 +179.21 +151.75 +65.767 +112.55 +32.61 +10.206 +19.956 +117.73 +109.03 +57.502 +53.756 +37.745 +80.822 +385.81 +659.12 +674.45 +468.03 +562.78 +1135.6 +460.75 +1074.8 +499.6 +283.92 +395.5 +1236.5 +1638.2 +53.248 +112.71 +69.911 +128.9 +60.747 +4309.6 +2865.6 +2328.2 +624.18 +185.71 +353.75 +239.71 +253.09 +286.23 +0.1082 +0.13238 +0.064563 +0.03965 +334.88 +505.95 +86.81 +178.3 +663.96 +1075.5 +818.29 +577.13 +1774.9 +632.49 +164.9 +5470.9 +8943.5 +3742.9 +1345 +115.24 +144.01 +112.14 +107.65 +89.546 +41.104 +7.1019 +20.637 +43.597 +89.798 +75.311 +74.725 +116.86 +259.26 +455.68 +498.77 +502.82 +704.79 +523.69 +0.41684 +1301.5 +941.47 +1015.1 +251.64 +1433 +1582 +1398.3 +40.127 +198.85 +76.973 +120.06 +7388.2 +3835.5 +251.31 +244.94 +615.07 +301.95 +535.92 +374.12 +0.20206 +0.050042 +0.056924 +0.26609 +0.087839 +0.022109 +368.45 +438.24 +111.09 +132.05 +921.37 +808.9 +1019.5 +531.18 +2149.3 +435.63 +144.87 +230.64 +10643 +5898.3 +2026.1 +40.111 +188.47 +138.91 +168.82 +203.81 +42.116 +5.2948 +22.695 +35.925 +121.14 +612.33 +188.1 +57.532 +293 +570.36 +540.93 +408.08 +579.63 +0.15926 +0.81058 +0.04284 +803.55 +555.01 +437.07 +896.91 +1378.6 +159.61 +68.162 +254.39 +88.432 +14250 +2836.4 +31.255 +285.21 +323.57 +214.99 +90.656 +0.0804 +0.14419 +0.14268 +0.13 +0.053223 +0.15144 +0.29863 +0.035042 +492.88 +210.98 +94.369 +305.37 +662.38 +721.62 +1181.4 +489.78 +438.51 +1218.3 +97.78 +75.163 +4984.5 +4091.3 +60.795 +31.678 +124.76 +198.52 +176.61 +206.67 +37.318 +3.6301 +9.1312 +18.701 +134.01 +231.5 +97.791 +70.328 +279.16 +551.86 +816.88 +349.68 +563.94 +0.85929 +0.42366 +0.18717 +1002.1 +315.58 +666.87 +1031.4 +124.97 +86.975 +97.122 +217.14 +89.2 +872.74 +126.94 +53.245 +546.53 +572.12 +229.6 +0.059899 +0.017263 +0.16697 +0.16621 +0.3571 +0.18074 +0.022769 +0.047176 +0.23812 +434.36 +151.43 +38.136 +218.13 +882.65 +782.61 +1342.9 +1696 +1006.5 +357.73 +634.14 +49.816 +5397.2 +5469.8 +46.838 +33.119 +66.15 +185.11 +105.78 +225.73 +35.267 +14.78 +20.735 +27.536 +24.715 +121.73 +113.63 +55.759 +323.64 +206.89 +763.23 +0.42954 +0.12588 +0.38625 +0.29449 +0.043779 +0.27847 +543.34 +460.2 +1147.8 +238.92 +61.311 +181.05 +208.56 +508.39 +339.02 +175.28 +125 +164.62 +0.043501 +0.02866 +0.062457 +0.040213 +0.11443 +0.21913 +0.11669 +0.04374 +0.016654 +0.17227 +0.062289 +247.2 +218.31 +67.361 +200.25 +612.29 +242.55 +647.37 +2424.1 +1143.5 +952.74 +137.37 +53.519 +7754.5 +79.312 +94.58 +32.569 +77.014 +105.6 +98.382 +187.66 +23.153 +16.673 +23.345 +33.799 +50.45 +64.834 +157.59 +42.568 +261.19 +185.93 +614.25 +0.33103 +0.28102 +0.13799 +0.15294 +0.073055 +0.8494 +127.22 +462.39 +582.03 +179.22 +129.21 +983.13 +763.44 +137.08 +345.52 +88.9 +165.44 +27.223 +0.1583 +0.096839 +0.071621 +0.043791 +0.050473 +0.061135 +0.022685 +0.083898 +0.038899 +0.7427 +0.6071 +267.54 +198.31 +69.754 +84.708 +390.57 +708.21 +2934.1 +1721.4 +1116.8 +1230.7 +174.38 +9386.7 +108.48 +139.66 +75.38 +26.515 +120.66 +108.66 +89.76 +344.93 +74.355 +68.365 +34.298 +28.465 +48.124 +70.851 +96.992 +61.976 +371.84 +1575.1 +1094.2 +342.1 +0.077362 +0.076971 +0.05553 +0.12666 +295.68 +252.99 +382.44 +483.03 +458.97 +85.039 +498.06 +810.13 +103.07 +208.19 +161.99 +125.81 +0.1919 +0.12191 +0.037021 +0.29284 +0.052602 +0.32042 +0.046684 +0.1262 +0.44467 +0.64395 +0.06337 +0.2208 +223.39 +273.76 +67.621 +70.992 +506.43 +851.67 +2396.2 +1877.6 +62.199 +28.433 +732.63 +765.14 +220.15 +235.48 +61.016 +26.896 +87.236 +70.419 +203.86 +357.74 +58.619 +70.907 +334.52 +60.353 +98.742 +99.331 +142.46 +37.093 +187.75 +1227.5 +1563.1 +300.69 +0.064358 +0.18656 +81.927 +46.866 +250.13 +291.85 +794.61 +735.84 +667.5 +206.08 +413.8 +139.57 +101.27 +34.505 +106.77 +0.10019 +0.11337 +0.081098 +0.13903 +0.17152 +0.057469 +0.27896 +0.089418 +0.73589 +0.32431 +0.64672 +0.34203 +0.065661 +160.32 +80.67 +123.31 +179.51 +350.25 +5073 +3533.3 +115.99 +157.95 +8106.2 +1879.3 +648.6 +84.411 +303.74 +100.71 +38.849 +86.472 +161.51 +263.09 +195.46 +89.781 +39.924 +225.73 +42.995 +78.674 +53.808 +94.261 +88.364 +373.94 +996.86 +1341.8 +464.36 +0.039879 +65.058 +91.046 +81.726 +381.79 +1495.5 +683.13 +1123.8 +517.43 +163.17 +24.442 +40.156 +38.388 +25.15 +94.066 +0.024743 +0.068258 +0.19848 +0.93696 +1.4281 +0.11725 +0.15148 +0.1642 +0.23464 +0.22145 +0.19224 +2.505 +0.70668 +201.05 +90.126 +126.88 +1190 +777.07 +4899.7 +678.77 +1130.2 +6.7953 +10596 +3770.2 +779.21 +176.74 +157.91 +168.41 +66.738 +76.78 +96.715 +182.56 +18.197 +54.624 +44.979 +83.368 +60.242 +73.634 +65.679 +70.81 +537.25 +451.41 +719.55 +1099.7 +340.66 +322.84 +40.488 +616.53 +3816.4 +1162.9 +1224.5 +416.71 +1044.3 +9063.2 +70.761 +17.786 +76.351 +27.221 +10.547 +16.9 +0.021039 +0.045338 +0.095938 +0.13353 +0.31105 +0.055649 +0.083421 +0.044455 +0.016204 +0.14049 +0.34422 +0.09559 +0.34635 +140.15 +1944.3 +836.85 +359.34 +380.13 +902.41 +896.1 +916.53 +260.12 +5520.8 +1990 +487.75 +384.89 +111.42 +189.71 +50.02 +137.73 +165.61 +67.841 +17.14 +69.179 +42.488 +52.427 +84.819 +103.17 +44.679 +83.167 +342.59 +1181.8 +378.38 +1105.3 +410.63 +8129.5 +2901.9 +627.33 +1594.8 +725.26 +1002.6 +0.09602 +0.063524 +6443.4 +103.58 +26.237 +86.196 +51.087 +25.939 +31.543 +0.014291 +0.004506 +0.030525 +0.15593 +0.18315 +0.043413 +0.24672 +0.046868 +0.14889 +0.18599 +1.9303 +0.37693 +0.41698 +630.52 +944.82 +97.564 +296.6 +185.71 +986.83 +1218 +1653.2 +469.28 +3312.5 +1509.8 +443.92 +330.44 +123.85 +136.11 +39.228 +159.79 +0.73861 +30.21 +40.968 +27.758 +59.848 +46.37 +1098.8 +43.889 +98.104 +40.548 +235.48 +669.96 +348.12 +370.51 +243.04 +4807.6 +3606.9 +576.44 +1256.6 +0.30355 +0.17953 +0.29701 +0.053853 +5896.5 +50.044 +46.258 +47.816 +42.806 +69.952 +106.56 +0.34318 +0.025863 +0.1704 +0.13901 +0.095444 +0.092367 +0.12837 +0.018696 +0.016011 +0.044065 +0.1034 +0.068349 +0.1808 +619.98 +312.02 +129.54 +279.42 +216.25 +123.29 +983.97 +3944.9 +543.57 +3465.9 +1794.2 +315.24 +364.92 +128.76 +316.27 +40.732 +118.16 +1.2723 +46.693 +17.538 +73.975 +108.89 +99.22 +125.81 +113.48 +227.24 +75.975 +202.5 +902.64 +434.51 +241.82 +7366.6 +5050.8 +5326 +98.017 +69.843 +0.16565 +0.25871 +0.077979 +0.077727 +202.77 +44.166 +74.829 +52.991 +37.051 +79.419 +245.29 +188.46 +0.022691 +0.013789 +0.14137 +0.053556 +0.10356 +0.11882 +0.10259 +0.019621 +0.043758 +0.20601 +0.11421 +0.42741 +1109.6 +2030.4 +2451.1 +313.58 +596.71 +125.66 +135.84 +442.03 +778.45 +810.21 +738.1 +315.35 +382.64 +106.18 +173.69 +84.679 +92.843 +17.735 +65.789 +39.076 +56.094 +163.55 +164.85 +495.57 +125.21 +269.44 +118.81 +242.01 +929.05 +716.76 +4381 +4876.5 +4573 +148.31 +96.322 +59.475 +0.042397 +0.076226 +0.13975 +456.51 +118.43 +34.431 +67.079 +45.391 +34.866 +59.594 +104.74 +147.49 +0.10363 +0.056511 +0.14809 +0.098921 +0.031666 +0.025205 +0.11921 +0.045407 +0.094984 +0.23079 +0.096631 +0.10193 +1.6416 +4695.7 +294.95 +3856.5 +302.47 +31.979 +65.641 +462.15 +704.75 +917.91 +575.57 +175.31 +231.62 +176.22 +98.136 +80.741 +111.14 +19.508 +34.909 +14.136 +30.208 +186.59 +73.34 +291.55 +276.49 +240.13 +418.12 +234.08 +607.79 +2757.4 +4920 +2799.4 +4729.3 +2626.9 +128.68 +46.913 +0.0726 +0.072401 +841.44 +646.64 +224.38 +45.655 +60.483 +67.441 +355.93 +571.9 +179.15 +58.79 +197.9 +0.13627 +0.30573 +0.11765 +0.067013 +0.018219 +0.016733 +0.057497 +0.064122 +0.13514 +0.090312 +0.066371 +4.7209 +2.5143 +943.4 +322.96 +0.23517 +30.915 +100.11 +376.11 +337.24 +723 +1056.2 +761.33 +176.87 +55.933 +104.28 +81.898 +96.379 +71.783 +21.72 +10.677 +22.403 +153.35 +63.851 +97.804 +165.95 +296.34 +496.23 +184.7 +412.73 +43.664 +5602.1 +4002.9 +1860.3 +2679.2 +59.8 +50.525 +38.697 +775.63 +572.89 +1475.9 +336.99 +115.05 +649.9 +2193 +245.61 +744.1 +191.27 +84.952 +170.41 +0.026531 +0.1137 +0.027563 +0.028579 +0.017583 +0.017441 +0.005683 +0.024632 +0.040253 +0.13334 +0.18874 +4.8316 +5.5234 +535.21 +98.258 +998.54 +653.23 +20.796 +9.0748 +360.11 +1302.8 +1828.5 +1244 +933.62 +55.069 +69.321 +40.333 +36.342 +121.36 +10.116 +15.08 +36.442 +168.15 +122.2 +124.15 +278.44 +425.85 +468.23 +154.97 +126.34 +23.184 +50.346 +3712.7 +1466 +1793.8 +1386.8 +72.252 +51.122 +178.73 +551.67 +1585.6 +331.67 +348.35 +353.49 +1277.2 +635.25 +392.83 +91.123 +96.079 +227.47 +0.006421 +0.049285 +0.044429 +0.008224 +0.047792 +0.068893 +0.017327 +0.039469 +0.08043 +0.13022 +0.082486 +5.1338 +4.1562 +16.882 +141.76 +734.8 +2930.1 +323.75 +0.52506 +21.982 +1693.4 +1727.6 +1895.2 +957.11 +1074.9 +70.258 +52.68 +45.589 +210.09 +42.13 +10.354 +19.661 +79.071 +222.31 +67.117 +218.7 +193.49 +238.43 +296.85 +85.012 +40.904 +59.337 +3410.2 +1700.5 +1296.7 +2115.4 +2930.4 +20.937 +123.49 +62.511 +141.19 +327.3 +221.18 +240.25 +612.72 +330.89 +233.97 +80.032 +61.025 +116.47 +281.4 +0.35713 +0.029346 +0.027064 +0.035857 +0.045525 +0.006328 +0.048262 +0.072376 +0.089183 +0.25604 +3.9534 +6 +84.076 +112.48 +471.24 +1950 +230.46 +226.41 +233.52 +152.13 +1310.9 +1663.7 +779.52 +758.12 +405.68 +66.272 +65.105 +85.09 +58.834 +60.204 +18.779 +234.33 +104.95 +30.056 +12.884 +330.23 +366.01 +526.89 +130.22 +41.978 +39.877 +83.094 +672.33 +1758.8 +1338.8 +2849.5 +73.871 +95.442 +131.27 +78.909 +294.33 +273.98 +396.63 +483.5 +493.7 +244.6 +137.36 +84.581 +165.83 +181.96 +0.24078 +0.047571 +0.042202 +0.11999 +0.03037 +0.009228 +0.021816 +0.030977 +0.17975 +0.24829 +7.4315 +7.293 +52.933 +6.5971 +293.88 +4863.8 +928.3 +112.59 +183.04 +21.641 +15.022 +717.13 +1614.8 +629.28 +542.28 +142.76 +73.015 +66.367 +18.333 +61.114 +41.806 +59.816 +43.447 +37.07 +16.375 +455.18 +601.62 +1983.8 +127.05 +63.564 +9.1131 +81.932 +65.859 +145.19 +665.97 +3082.9 +4975.3 +277.61 +181.54 +86.337 +81.146 +293.29 +327.72 +1073.8 +512.55 +347.1 +134.98 +157.76 +265.3 +0.054571 +0.18742 +0.082125 +0.033194 +0.081653 +0.049311 +0.058793 +0.020303 +0.067323 +0.13689 +0.20344 +13.834 +9.772 +48.885 +12.516 +16.256 +4965.6 +1659.5 +141.05 +193.06 +35.968 +34.877 +52.472 +1344.1 +493.89 +612.7 +188.02 +52.916 +39.841 +20.352 +33.753 +15.054 +41.654 +106.28 +51.689 +14.346 +536.01 +672.32 +1050.8 +98.978 +107.55 +15.315 +67.565 +25.825 +90.562 +551.62 +3907.9 +2211.4 +297.49 +141.52 +74.294 +84.463 +497.94 +321.86 +798.51 +997.35 +245.92 +207.91 +289.35 +0.067189 +0.12025 +0.11858 +0.3864 +0.10523 +0.3428 +0.18746 +0.034576 +0.089765 +0.059297 +0.10473 +0.15225 +13.86 +12.321 +31.326 +8.9195 +323.04 +134.71 +145.97 +451.24 +59.115 +55.685 +85.474 +88.555 +15.423 +555.67 +479.14 +128.05 +150.63 +41.16 +23.577 +29.607 +19.572 +39.653 +43.109 +160.17 +80.801 +224.67 +1174.8 +861.35 +152.29 +315.12 +194.56 +111.59 +30.172 +65.475 +134.45 +87.755 +1186.3 +223.71 +353.59 +128.69 +151.5 +268.89 +968.96 +1414 +744.6 +320.58 +282.53 +249.62 +0.24849 +0.29093 +0.25982 +0.99116 +0.3283 +0.11002 +0.048244 +0.043303 +0.072392 +0.17545 +0.15748 +0.36863 +23.905 +11.748 +21.218 +14.339 +882.83 +0.18589 +229.16 +67.704 +51.019 +60.503 +77.169 +186.56 +51.586 +226.58 +404.33 +171.54 +152.9 +60.561 +24.917 +57.242 +9.1754 +32.435 +40.515 +80.929 +348.09 +111.32 +215.36 +47.265 +134.04 +321.31 +58.288 +80.063 +73.861 +51.005 +122.88 +61.66 +84.99 +103.96 +163.11 +97.962 +366.93 +65.736 +1681.3 +891.47 +1001.1 +361.26 +0.066279 +1.296 +0.32493 +0.25601 +0.095479 +0.46714 +0.24702 +0.89324 +0.098013 +0.035136 +0.018783 +0.17505 +0.072354 +0.055295 +33.351 +16.96 +8.6701 +8.6353 +1357.9 +17071 +40.055 +73.379 +11.504 +60.006 +75.506 +97.137 +81.796 +176.72 +449.69 +284.16 +284.44 +64.221 +22.822 +42.988 +6.3771 +31.072 +155.39 +84.027 +343.38 +102.21 +129.57 +151.28 +89.326 +0.3188 +71.084 +105.42 +165.84 +125.81 +80.866 +98.395 +400.75 +125.72 +136.44 +81.719 +165.66 +63.942 +32.455 +527.23 +0.2479 +0.61274 +0.17505 +0.083339 +0.040549 +0.11917 +0.023824 +0.012139 +0.084957 +0.17797 +0.031481 +0.033224 +0.097474 +0.072072 +0.25574 +0.021377 +81.456 +41.589 +17.169 +15.404 +18.925 +137.16 +71.361 +64.516 +24.209 +43.195 +48.634 +196.69 +93.569 +225.12 +269.47 +95.372 +97.168 +79.84 +43.41 +64.213 +22.325 +161.14 +161.91 +112.26 +381.76 +61.769 +42.907 +56.459 +53.078 +28.73 +21.702 +67.963 +330.26 +135.12 +75.358 +329.75 +213.26 +188.26 +198.99 +64.303 +75.372 +47.043 +56.7 +0.032864 +0.29714 +1.2298 +0.13757 +0.43475 +0.17595 +0.20137 +0.32128 +0.013389 +0.067862 +0.076756 +0.0317 +0.008228 +0.026471 +0.065689 +0.084098 +0.020856 +108.99 +86.414 +21.645 +10.701 +114.78 +275.89 +59.646 +39.61 +30.829 +74.772 +1519 +233.41 +523.44 +182.64 +333.42 +103.08 +112.67 +156.47 +93.292 +161.39 +46.35 +53.415 +141.95 +93.537 +384.86 +79.639 +28.888 +48.559 +25.837 +23.973 +30.127 +25.532 +187.03 +189.41 +289.04 +406.55 +210.14 +606.31 +187.78 +47.317 +82.751 +0.23591 +0.1827 +0.036279 +0.14376 +0.18934 +0.13446 +0.16527 +0.4125 +0.46207 +0.34286 +0.021036 +0.032588 +0.12984 +0.038536 +0.014503 +0.013669 +0.071847 +0.14763 +0.14067 +90.213 +65.786 +15.323 +7.8638 +65.005 +306.02 +47.255 +681.07 +1381.9 +351.98 +609.14 +100.44 +312.94 +193.92 +265.78 +138.72 +154.29 +101.86 +70.404 +457.99 +81.21 +172.72 +137.15 +127.15 +260.87 +49.476 +44.337 +79.109 +98.754 +24.538 +17.166 +293.03 +160.9 +458.07 +274.75 +165.74 +188.53 +320.87 +140.04 +51.183 +1.2868 +0.49845 +0.069229 +0.068235 +0.023328 +0.14641 +0.55429 +0.32456 +0.11474 +0.18441 +0.037657 +0.033751 +0.046685 +0.052535 +0.43469 +0.091557 +0.053914 +0.12411 +0.26058 +0.044777 +57.603 +39.499 +18.982 +23.733 +427.31 +876.15 +463.67 +1407.7 +853.21 +730.83 +330.03 +72.821 +112.34 +173.86 +193.12 +8.4912 +8.216 +11.125 +183.18 +505.43 +13.04 +75.922 +145.12 +70.374 +165.03 +85.525 +0.03948 +0.063966 +51.063 +33.086 +16.826 +817.65 +290.85 +646.82 +213.6 +303.6 +161.68 +255.62 +0.6356 +0.17687 +0.94067 +0.55357 +0.16547 +0.062933 +0.061666 +0.011768 +0.049334 +0.10235 +0.032313 +0.18103 +0.056532 +0.17429 +0.091581 +0.16587 +0.11756 +1.0874 +0.31652 +0.22127 +0.070532 +0.033851 +57.026 +23.962 +1257.1 +1294.5 +626.19 +498.79 +287.61 +1541.1 +794.01 +508.54 +268.58 +147.68 +230.31 +75.688 +49.627 +6.2095 +217.31 +1197.9 +321.83 +191.44 +14.379 +79.972 +97.126 +136.82 +0.021514 +0.007827 +20.047 +0.053468 +41.131 +51.024 +1131.7 +902.49 +339.53 +1130.6 +302.85 +378.92 +145.17 +0.057038 +0.19252 +0.48657 +0.90054 +0.38425 +0.38058 +0.12796 +0.16751 +0.031015 +0.063999 +0.082118 +0.1279 +0.01472 +0.22981 +0.40355 +0.62896 +0.10493 +0.22375 +0.41069 +0.15286 +0.053713 +0.43361 +0.060175 +104.99 +14.189 +1179.7 +1157.6 +622.49 +753.82 +221.04 +1166.6 +955.65 +193.41 +287.64 +994.52 +114.24 +87.471 +35.783 +186.41 +359.33 +511.98 +160.38 +104.18 +32.682 +117.91 +270.65 +0.03439 +0.00761 +0.036021 +0.054414 +0.055327 +1908.1 +733.07 +902.34 +1231.9 +862.63 +832.6 +193.6 +281.07 +216.62 +0.055577 +0.055177 +0.1469 +0.11132 +0.62654 +0.35621 +0.084066 +0.12204 +0.54041 +0.026394 +0.063307 +0.01806 +0.069225 +0.21656 +0.38735 +0.16511 +0.044637 +0.14374 +0.44954 +0.40793 +0.022452 +0.022494 +0.017912 +204.88 +192.87 +219.84 +1139.2 +799.04 +585.47 +169.12 +944.73 +1292 +648 +2201.8 +532.67 +157.91 +60.103 +765.2 +288.78 +37.104 +41.414 +214.75 +68.606 +36.105 +1728.9 +0.087427 +0.091913 +0.14966 +0.24793 +0.097395 +0.15154 +1643.4 +1339 +507.75 +988.36 +14.16 +6.465 +67.495 +278.63 +608.36 +20000 +0.29726 +0.081376 +0.13631 +0.15145 +0.24469 +0.078288 +0.21849 +0.25451 +0.10246 +0.042455 +0.009998 +0.43855 +0.1858 +0.23549 +0.28397 +0.034734 +0.56939 +0.065779 +0.2423 +0.022365 +0.037905 +0.064475 +152.41 +183.65 +179.18 +484.45 +976.5 +598.33 +368.57 +687.21 +2370.9 +358.39 +1192.2 +397.32 +240.24 +136.75 +114.15 +27.8 +50.863 +42.337 +302.4 +381.22 +292.89 +3380.7 +0.4495 +0.37642 +0.47346 +0.40705 +38.559 +24.115 +7.0979 +20.524 +8.2543 +579.13 +441 +7.0297 +463.65 +149.05 +914.35 +11424 +5306.7 +0.065776 +0.083743 +0.17129 +0.12881 +0.098865 +0.099205 +0.36675 +0.076694 +0.050893 +0.10022 +0.22813 +0.19426 +0.054389 +0.052722 +0.052901 +0.15553 +0.10725 +0.16306 +0.36958 +0.23806 +0.23328 +128.38 +271.95 +268.3 +460.67 +926.67 +609.86 +576.22 +777.15 +2205.7 +845.24 +186.52 +343.57 +70.418 +87.967 +64.561 +16.164 +30.278 +3450.5 +254.44 +515.36 +466.31 +1601.7 +0.062995 +198.11 +63.856 +8.2241 +28.476 +37.953 +67.873 +38.098 +15.502 +14.066 +390.38 +9.3938 +14.959 +264.15 +330.88 +4883.9 +6483.2 +0.027342 +0.080711 +0.26539 +0.14223 +0.036764 +0.068373 +0.086826 +0.061436 +0.09274 +0.11073 +0.034654 +0.053774 +0.058785 +0.04813 +0.068237 +0.045184 +0.05324 +0.15088 +0.45824 +0.064929 +0.56958 +153.19 +474.61 +285.46 +548.46 +429.69 +752.81 +222.22 +1052.4 +1125.2 +1019.4 +301.31 +318.53 +40.414 +61.805 +47.064 +19.572 +2912 +2965.7 +1285 +1100 +368.53 +1106.3 +1524.8 +3244.8 +18.927 +11.331 +11.707 +40.729 +108.74 +25.58 +35.538 +15.585 +403.6 +79.298 +10.801 +26.854 +1.0501 +2549.3 +9614.1 +1000.4 +0.014624 +0.12442 +0.046415 +0.11215 +0.061612 +0.045251 +0.003685 +0.050648 +0.08627 +0.27103 +0.12599 +0.033378 +0.14017 +0.069181 +0.03481 +0.072204 +0.032787 +0.28272 +0.34053 +1.5226 +204.37 +3370 +959.85 +695.88 +580.35 +361.46 +701.47 +240.6 +353.84 +84.332 +196.92 +434.97 +23.003 +33.641 +27.741 +17.255 +5490.5 +5361.9 +5047.3 +1393.5 +957.77 +2251 +2576.6 +8013.5 +18.239 +16.713 +23.37 +35.998 +93.786 +47.002 +45.523 +449.01 +501.89 +17.411 +13.378 +23.224 +8.6063 +0.36344 +7010.9 +768 +1165.5 +0.20792 +0.14701 +0.096241 +0.22517 +0.070283 +0.016705 +0.040251 +0.017631 +0.13341 +0.049896 +0.25569 +0.23034 +0.12899 +0.064062 +0.034764 +0.028653 +0.25073 +0.31567 +1.0596 +345.68 +592.28 +2134.2 +1202.9 +539.47 +330.7 +409.63 +1199.2 +668.86 +124.53 +101.03 +15.569 +146.77 +32.936 +52.947 +13.684 +38.817 +5523.1 +5910.9 +558.18 +781.59 +5226 +5629.1 +7637.8 +7.106 +13.787 +34.437 +19.076 +35.607 +43.835 +56.498 +306.37 +372.91 +41.495 +21.882 +11.719 +9.6909 +0.40136 +0.1059 +841.57 +938.07 +487.94 +0.010238 +0.10553 +0.046506 +0.11898 +0.062395 +0.074887 +0.037402 +0.041439 +0.085629 +0.12357 +0.48259 +0.05641 +0.02809 +0.008891 +0.078475 +0.35253 +0.59843 +0.30841 +146.21 +95.998 +674.8 +1106.9 +441.7 +156.68 +447.74 +203.49 +320.22 +42.279 +114.12 +17.376 +116.68 +25.078 +60.922 +36.217 +45.414 +88.563 +6366.7 +491.95 +1182.1 +6178.2 +4796.2 +4481.3 +0.20407 +11.856 +21.926 +16.243 +23.729 +0.093971 +61.36 +361.93 +277.8 +46.069 +13.812 +16.442 +18.608 +4.5053 +0.034962 +0.063652 +1385.7 +386.44 +246.84 +0.14137 +0.45911 +0.34995 +0.26907 +0.36218 +0.19126 +0.1741 +0.022072 +0.16994 +0.038305 +0.050812 +0.069623 +0.006206 +0.021296 +0.292 +0.34715 +1.0713 +112.36 +43.416 +190.52 +686.82 +413.38 +220.37 +834.74 +748.82 +253.5 +57.745 +150.11 +21.212 +125.76 +36.243 +80.544 +84.903 +47.81 +51.836 +4049.5 +490.62 +194.32 +170.38 +5763.9 +4597.6 +0.90267 +0.86948 +0.81293 +0.25663 +0.2 +0.26418 +79.064 +141.85 +153.54 +35.027 +9.3936 +9.1993 +7.5821 +5.5996 +20.028 +0.044108 +0.11056 +240.89 +200.69 +123 +3.858 +3.0067 +0.40047 +0.25624 +0.61325 +0.57434 +0.35709 +0.11586 +0.034646 +0.02964 +0.068849 +0.014857 +0.005365 +0.35297 +0.50582 +1.1016 +113.23 +42.231 +111.29 +474.44 +468.83 +138.11 +277.49 +864.62 +201.23 +42.901 +62.746 +12.645 +115.77 +56.018 +53.807 +98.567 +70.706 +51.033 +24.592 +24.543 +210.43 +311.09 +80.96 +1853.7 +1440.3 +0.54587 +0.83071 +0.06988 +0.051265 +0.082991 +112.97 +320.2 +941.72 +2241.3 +19.074 +6.5456 +4.8211 +14.334 +6.48 +0.065746 +0.1132 +161.3 +61.142 +35.962 +13.512 +0.32989 +0.2049 +0.17805 +0.56547 +0.4957 +0.37138 +0.053374 +0.063802 +0.2806 +0.061452 +0.33847 +0.034291 +0.23814 +0.39771 +0.21901 +202.85 +43.508 +169.32 +52.427 +532.14 +1187.8 +233.47 +1208.8 +1634.6 +27.691 +38.937 +14.39 +7.947 +108.84 +68 +180.3 +106.66 +98.757 +25.396 +26.562 +52.594 +446.93 +75.141 +1957.7 +1161.5 +0.23214 +0.07412 +0.024165 +0.26018 +534.5 +116.63 +253.85 +190.13 +1612.9 +2283.9 +4.503 +4.6024 +10.57 +7.8631 +0.036369 +0.096908 +170.91 +53.093 +24.879 +27.583 +0.9919 +0.32218 +0.13575 +0.76685 +0.55023 +0.15789 +0.1557 +0.19741 +0.27046 +0.17342 +0.32438 +0.41117 +0.53851 +0.18219 +0.12775 +258.79 +76.91 +70.134 +83.549 +435.83 +103.45 +227.57 +1113.3 +1388 +655.59 +2554.8 +8.1038 +84.266 +232.55 +67.19 +153.73 +125.53 +431.86 +421.9 +23.984 +82.514 +49.544 +64.313 +83.672 +0.14088 +0.18529 +0.31038 +0.10529 +0.046473 +105.35 +76.261 +176.49 +137.31 +906.64 +1079.8 +287.75 +5.4632 +8.6178 +8.0025 +0.057809 +0.26716 +185.3 +35.779 +29.912 +51.068 +3.3967 +0.2249 +0.13473 +0.48103 +2.0001 +0.40828 +0.50174 +0.20536 +1.2002 +0.54592 +0.073546 +0.13058 +0.087965 +0.17538 +0.051666 +11951 +571.83 +65.441 +83.139 +100.29 +254.07 +481.44 +423.91 +313.72 +1852.2 +1201.8 +2723 +149.5 +281.99 +109.16 +119.64 +178.39 +32.871 +133.76 +202.18 +142.37 +91.291 +49.243 +67.492 +0.23922 +0.072452 +0.059104 +53.378 +81.514 +62.733 +69.171 +178.6 +78.902 +881.99 +789.59 +229.26 +345.68 +0.33845 +0.169 +0.65015 +653.95 +115.03 +40.762 +28.143 +18.116 +0.056281 +0.074211 +0.063786 +0.22665 +1.1135 +1.8627 +1.0306 +0.46698 +0.32024 +0.36744 +0.30865 +0.68378 +0.054778 +0.022752 +0.098575 +695.26 +314.55 +48.36 +116.48 +120.29 +758.04 +492.65 +387.25 +802.26 +364.69 +362.89 +2585 +1731.8 +813.71 +164.31 +118.89 +270.48 +47.187 +138.89 +257.83 +334.57 +185.02 +35.568 +65.29 +91.223 +74.021 +58.67 +89.157 +42.217 +144.56 +116.89 +382.92 +178.73 +1253.8 +413.14 +328.28 +191.12 +124.56 +66.652 +221.72 +485.79 +142.67 +22.968 +50.586 +0.065482 +0.096258 +0.07727 +0.45136 +0.7232 +0.50779 +0.35879 +1.3405 +0.9348 +0.25919 +0.31328 +0.30467 +0.11207 +0.078028 +0.092702 +0.044516 +3911.3 +117.63 +47.884 +44.938 +153.72 +631.03 +409.18 +363.28 +406.72 +1529.7 +1943.4 +752.7 +2317.6 +1037.6 +205.51 +175.65 +215.92 +410.92 +136.63 +40.846 +10.936 +0.035188 +0.037047 +94.905 +79.32 +76.547 +28.58 +97.661 +90.744 +341.78 +915.11 +463.13 +203.47 +1214.2 +187.42 +93.426 +102.97 +247.47 +122.24 +379.72 +949.23 +184.88 +34.48 +0.14067 +0.16036 +0.32147 +0.55511 +1.6732 +1.485 +0.30166 +0.35656 +0.87711 +1.5999 +1.2133 +0.071639 +0.097078 +0.062833 +0.078319 +0.11189 +0.052087 +75.47 +327.33 +810.94 +48.94 +112.36 +135.99 +564.03 +428.81 +325.42 +943.08 +1018.4 +446.23 +115.62 +1086.5 +84.748 +333.55 +335.2 +170.43 +90.889 +30.856 +18.218 +0.08446 +289.18 +35.908 +116.06 +150.16 +50.736 +87.845 +84.283 +686.2 +1359.7 +1156.3 +5158.4 +0.03407 +0.012671 +33.992 +0.16328 +0.23849 +0.10527 +0.19088 +0.14316 +0.049323 +0.25146 +0.13173 +0.05233 +0.29288 +3.2381 +1.7772 +1.2188 +0.30211 +0.45187 +0.81733 +0.95902 +0.82853 +0.13628 +0.24409 +0.073842 +0.071618 +0.091826 +0.007311 +56.215 +191.47 +864.48 +130.37 +81.244 +94.073 +450.03 +246.6 +80.84 +431.87 +546.67 +590.07 +120.21 +112.54 +123.52 +283.8 +398.25 +75.39 +81.79 +55.74 +0.080217 +0.18078 +72.451 +16.982 +90.54 +162.77 +33.063 +488.43 +174.03 +1234.7 +1039.1 +42.749 +274.46 +0.019462 +0.12007 +0.19701 +0.27779 +0.19921 +0.31658 +0.19006 +0.20798 +0.14864 +0.30309 +0.18967 +0.12345 +0.19997 +0.16787 +0.24989 +0.099583 +0.51502 +0.28993 +0.28413 +0.60542 +0.1241 +0.11731 +0.16837 +0.093039 +0.056192 +0.078605 +0.18962 +55.558 +30.342 +1549.3 +189.7 +89.231 +140.53 +480.34 +598.94 +109.5 +266.7 +378.21 +548.59 +412.09 +145.58 +94.823 +363.46 +287.54 +64.579 +48.83 +79.264 +54.063 +29.332 +41.572 +14.703 +134.29 +177.88 +41.869 +419.71 +197.37 +385.14 +1603.4 +16.175 +0.23558 +0.047942 +0.057576 +0.54416 +0.48425 +0.30715 +0.70684 +0.27651 +0.29715 +0.20019 +0.1284 +0.43112 +0.1543 +0.10444 +0.086 +0.78884 +0.31419 +0.38494 +0.57546 +5.5527 +0.67306 +0.28949 +0.032038 +0.25226 +0.12284 +0.093856 +0.12448 +0.37224 +132.87 +61.206 +1156.4 +232.62 +124.87 +109.49 +347.17 +358.27 +209.4 +177.35 +436.02 +421.17 +378.35 +402.46 +346.72 +180.53 +83.654 +64.524 +78.777 +229.11 +72.587 +29.299 +38.82 +179.89 +221.37 +407.22 +3216.7 +3847.9 +73.903 +30.069 +69.121 +20.66 +0.31024 +2.3437 +0.28557 +0.2806 +0.52248 +0.55234 +1.6657 +0.10042 +0.20653 +0.44536 +0.2626 +0.12362 +0.021098 +0.009823 +0.066443 +0.15849 +0.035409 +0.020897 +0.38456 +1.5403 +1.7864 +0.92947 +0.1211 +0.18169 +0.03437 +0.068512 +0.0726 +0.063071 +127.7 +102.22 +41.982 +143.75 +132.75 +75.615 +202.33 +306.12 +238.7 +208.67 +423.31 +827.72 +818.41 +633.15 +892.4 +165.11 +94.909 +106.2 +179.32 +471.13 +53.886 +104.46 +30.052 +303.97 +175.25 +384.58 +83.087 +3380.1 +62.574 +46.787 +130.47 +1.6314 +1.4338 +0.68098 +0.23397 +0.28988 +0.36032 +0.12572 +0.55654 +0.33438 +0.086464 +0.14357 +0.088183 +0.030601 +0.01347 +0.030183 +0.068391 +0.06299 +0.16731 +0.11754 +0.19204 +0.10179 +0.48884 +0.83021 +0.15179 +0.11309 +0.15335 +0.051284 +0.11109 +0.26902 +130.47 +111.1 +39.982 +324.16 +212.63 +80.125 +92.203 +198.71 +146.07 +139.22 +61.682 +2072.5 +1101.5 +1160.8 +2828.3 +2712.6 +144.74 +197.01 +317.23 +254.66 +614.69 +46.991 +276.81 +240.28 +421.74 +174.91 +123.19 +47.067 +30.73 +27.222 +0.79767 +0.93031 +0.6527 +0.18686 +0.57061 +0.16706 +0.39984 +0.35152 +0.18556 +0.26583 +0.35237 +0.091806 +0.032438 +0.030631 +0.025176 +0.026231 +0.24591 +1.3939 +0.51838 +0.32738 +0.16568 +0.097878 +0.25571 +0.86376 +0.17641 +0.033889 +0.014991 +0.026878 +0.087333 +0.16469 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/layer84_permz.geos b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/layer84_permz.geos new file mode 100644 index 00000000000..fb4bb7c6d70 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/layer84_permz.geos @@ -0,0 +1,13200 @@ +6.4542e-06 +3.4083e-06 +3.3865e-06 +0.0012584 +0.0025506 +0.0049557 +0.011005 +0.94973 +0.18647 +0.055489 +0.077892 +0.016698 +0.11529 +0.043023 +0.094006 +0.034537 +0.022937 +117.11 +223.44 +33.238 +56.975 +0.0061175 +0.0045341 +0.02993 +0.026893 +0.0051619 +0.0025665 +0.011614 +1.0857e-05 +3.0584e-05 +1.1793e-05 +9.7815e-06 +1.8215e-05 +1.3971e-05 +9.1116e-06 +4.6364e-06 +1.0297e-05 +7.9578e-06 +1.3536e-06 +3.645e-06 +1.0576e-05 +4.5575e-05 +1.9143e-05 +8.1675e-06 +0.052147 +0.058883 +0.042518 +0.0060599 +0.0071636 +0.028538 +0.036131 +0.0017056 +0.0047555 +0.014849 +0.0065429 +0.0034798 +0.011185 +0.013638 +0.0098327 +50.995 +1.1286e-05 +1.0634e-05 +8.1667e-06 +5.2393e-06 +0.0032541 +0.0036477 +0.016646 +0.22377 +0.067813 +0.049244 +0.079361 +0.028587 +490.01 +202.93 +0.037146 +0.042683 +0.037978 +110.97 +86.644 +20.79 +20.101 +0.0025327 +0.0039998 +0.037997 +0.025787 +0.0065124 +0.0028595 +0.0098913 +2.8881e-05 +3.3028e-05 +2.5872e-05 +1.233e-05 +4.8856e-06 +2.2513e-05 +3.7565e-05 +2.6637e-06 +5.9152e-06 +3.4875e-06 +1.443e-06 +1.9086e-06 +1.1767e-05 +9.9196e-06 +7.389e-06 +3.4775e-06 +0.043254 +0.0324 +0.0052078 +0.014262 +0.019534 +0.023121 +0.024673 +0.03173 +0.0061988 +19.557 +0.025883 +0.0034476 +0.013853 +0.027658 +0.016655 +87.986 +6.5883e-06 +9.7745e-06 +2.0938e-05 +7.9875e-05 +4.9302e-05 +2.3443e-05 +0.0044765 +0.020005 +0.060883 +0.019016 +0.056679 +0.023007 +0.09989 +0.064859 +0.01452 +0.061766 +0.057448 +102.28 +41.87 +21.954 +25.789 +0.0022285 +0.0047058 +0.012034 +0.023596 +0.0027214 +0.0024529 +0.0070773 +6.3261e-05 +1.8382e-05 +1.9455e-05 +1.2733e-05 +8.6306e-06 +1.5792e-05 +2.3827e-05 +3.8131e-05 +1.5722e-05 +2.4469e-05 +4.3473e-06 +1.2284e-05 +2.5926e-05 +8.7617e-06 +3.6858e-06 +5.5697e-06 +0.02466 +0.037672 +0.0087035 +0.025294 +0.033894 +0.014143 +0.03082 +0.023784 +0.004703 +27.017 +0.014126 +0.0038305 +0.04231 +0.02316 +0.014491 +58.056 +1.9582e-05 +2.9963e-06 +1.6623e-05 +1.8874e-05 +6.3653e-05 +1.3589e-05 +4.6928e-05 +6.9859e-06 +0.0084093 +0.029766 +0.070997 +0.033223 +353.8 +288.01 +0.0099835 +0.067955 +0.069079 +0.023029 +19.435 +22.489 +19.191 +0.0029326 +0.0031055 +0.0062858 +0.0078211 +0.0049509 +0.0027538 +0.00523 +1.4683e-05 +7.3425e-06 +7.9791e-06 +2.3118e-05 +1.5686e-05 +3.7766e-05 +2.3192e-05 +1.8254e-05 +1.3246e-05 +3.6985e-05 +2.8115e-05 +4.5961e-05 +2.039e-05 +1.4442e-05 +1.2089e-05 +3.5193e-06 +0.0051816 +0.027909 +0.009852 +0.016548 +0.020567 +0.0084122 +0.012641 +0.014461 +0.014112 +25.336 +29.621 +0.0029542 +0.0030702 +0.0032005 +0.0064901 +57.245 +2.4328e-05 +4.5128e-06 +2.7136e-05 +1.7964e-05 +2.8686e-05 +3.1372e-05 +1.0345e-05 +2.7707e-06 +0.0065548 +0.019202 +0.10566 +0.045114 +170.57 +0.088424 +43.184 +65.588 +0.035426 +0.022368 +0.018213 +22.095 +3.7483 +0.002324 +0.0024469 +0.012055 +0.008703 +0.0059859 +0.0063365 +0.0057563 +0.020547 +1.0258e-05 +3.6084e-06 +2.2701e-05 +3.4276e-05 +1.5466e-05 +3.7823e-06 +4.2638e-06 +4.1338e-05 +3.1336e-05 +0.00010557 +7.4098e-06 +1.2464e-05 +6.3393e-06 +1.5805e-05 +7.1952e-06 +1.078e-05 +0.016137 +0.010825 +0.028925 +0.012291 +0.020505 +0.048329 +0.008651 +11.551 +14.808 +10.408 +0.002144 +66.711 +102.15 +10.64 +114.82 +1.7405e-05 +2.4344e-05 +2.1956e-05 +1.1204e-05 +5.0225e-05 +4.0387e-05 +1.3347e-05 +0.0044621 +0.0049595 +0.020514 +0.011097 +0.023158 +179.42 +0.024189 +0.012755 +77.305 +90.436 +79.243 +0.020578 +283.76 +0.040689 +0.0033532 +0.0088773 +0.013935 +0.0043266 +0.0031504 +0.0050983 +0.0070095 +0.011672 +1.2884e-06 +2.1406e-06 +1.1139e-05 +1.3991e-05 +2.3014e-05 +8.3808e-06 +1.4631e-05 +4.154e-05 +3.9946e-05 +5.8834e-05 +1.0903e-05 +2.3152e-06 +6.2313e-06 +4.4326e-05 +4.2737e-06 +1.1187e-05 +2.0606e-05 +250.02 +0.02002 +0.018546 +0.013976 +0.043392 +0.011596 +13.198 +17.546 +0.003838 +0.0015999 +42.677 +81.733 +37.719 +112.2 +3.6356e-05 +2.3023e-05 +3.4597e-05 +5.7646e-05 +6.9528e-05 +1.8271e-05 +0.0012786 +0.002228 +0.0072075 +0.029326 +0.0069144 +0.014489 +0.018507 +0.0065641 +0.022753 +20.905 +33.669 +49.178 +0.011052 +167.23 +124.32 +0.0044922 +0.0090015 +0.02186 +0.0032666 +0.0031722 +0.0028023 +0.0082649 +0.0082842 +2.781e-05 +1.5826e-05 +2.424e-05 +2.6436e-05 +7.9702e-06 +6.8927e-06 +1.803e-05 +2.2496e-05 +3.0583e-05 +9.2788e-05 +1.3457e-05 +1.1549e-06 +7.2593e-06 +2.6906e-05 +1.108e-05 +0.10054 +121.09 +107.26 +53.744 +0.022794 +0.016922 +0.024856 +76.964 +40.729 +0.0046386 +26.186 +24.197 +80.474 +33.168 +21.156 +106.42 +1.7062e-05 +1.9122e-05 +0.00014683 +2.8591e-05 +0.00011344 +6.1433e-05 +0.001497 +0.0031062 +0.0070954 +0.023254 +0.017912 +0.012054 +40.081 +0.0089496 +15.844 +113.94 +60.247 +30.255 +0.0075243 +47.301 +0.034774 +0.02061 +68.797 +0.011401 +0.0020654 +0.0033827 +0.0040613 +0.0076305 +0.0022376 +0.0063505 +1.1355e-05 +1.4114e-05 +1.1373e-06 +5.7265e-06 +2.0587e-05 +2.1325e-05 +5.5662e-06 +9.3884e-06 +1.4534e-05 +4.8081e-06 +4.1314e-06 +4.6246e-06 +3.562e-06 +0.076017 +365.09 +223.78 +238.75 +29.974 +0.020406 +0.012377 +75.929 +0.020419 +0.015204 +0.013802 +25.463 +24.786 +31.447 +23.069 +17.862 +45.732 +2.9373e-05 +1.3717e-05 +2.9431e-05 +0.00043611 +3.2076e-05 +8.3081e-05 +0.0027533 +0.0064722 +0.0031243 +0.01778 +0.021194 +0.015824 +20.78 +17.021 +92.294 +101.81 +77.178 +18.17 +0.0076742 +50.767 +0.044462 +0.020819 +0.037292 +26.721 +10.382 +0.0036319 +0.0027375 +0.010642 +0.0024527 +0.0075613 +0.23629 +7.2295e-06 +3.3354e-06 +1.8601e-06 +8.9319e-06 +8.6002e-06 +6.6354e-06 +1.7864e-05 +3.2434e-05 +6.6334e-06 +6.1923e-06 +1.465e-05 +2.0517e-05 +0.045933 +133.23 +210 +230.58 +29.976 +0.017093 +0.023383 +0.13894 +113.35 +0.023573 +0.025135 +31.244 +19.437 +23.043 +1.625e-05 +2.4275e-05 +3.0701e-06 +4.5119e-05 +2.0232e-05 +5.466e-05 +6.5022e-05 +5.5413e-05 +1.0716e-05 +0.004639 +0.008323 +0.0037374 +0.021388 +15.566 +6.8933 +22.36 +50.617 +56.32 +70.494 +69.684 +9.2923 +0.029442 +170.07 +0.052952 +73.596 +0.031332 +0.025705 +0.038516 +0.015747 +0.012916 +0.013572 +0.0027896 +0.0078059 +0.32422 +0.097566 +7.2112e-06 +2.9737e-06 +6.779e-06 +3.5362e-06 +8.3346e-06 +2.2955e-05 +7.1457e-06 +1.2459e-05 +1.1444e-05 +0.31724 +83.695 +0.058988 +175.36 +120.98 +225.27 +0.021759 +0.019454 +0.016441 +0.046793 +0.13608 +0.029077 +75.922 +0.035559 +0.01964 +0.032685 +1.4956e-05 +1.1366e-05 +1.5315e-05 +3.7969e-05 +2.3949e-05 +1.0672e-05 +7.9027e-06 +8.0941e-06 +6.4121e-06 +0.0072658 +0.0043561 +15.245 +0.013724 +7.6659 +0.0016117 +15.91 +104.18 +60.491 +89.769 +52.963 +10.163 +0.046213 +0.013641 +0.011291 +0.013866 +0.022194 +0.018874 +0.080349 +0.011676 +0.091263 +0.012761 +0.012575 +0.016611 +0.010156 +0.091179 +0.018647 +8.453e-06 +3.9313e-06 +4.9767e-06 +4.0395e-05 +1.0691e-05 +1.6847e-06 +0.016196 +0.057741 +0.20997 +0.024199 +95.735 +0.22616 +0.24421 +0.020918 +0.014651 +0.015946 +0.034849 +0.026367 +138.87 +0.01299 +32.123 +39.926 +0.07113 +0.02754 +5.5833e-06 +1.4019e-05 +6.268e-06 +2.0509e-05 +2.143e-05 +2.5294e-05 +5.2994e-05 +7.9145e-06 +9.0655e-06 +0.0047828 +8.0254 +9.5821 +0.0055881 +51.814 +9.3075 +0.008353 +141.74 +142.06 +54.175 +20.407 +5.4557 +0.05138 +0.0087376 +0.0062507 +0.017249 +0.02682 +0.021104 +0.037153 +0.004153 +0.0079049 +0.053362 +0.021818 +0.0033722 +0.014907 +0.0076799 +0.050542 +2.8038e-06 +1.2757e-05 +9.8478e-06 +4.0759e-05 +2.3775e-05 +0.03523 +0.036197 +0.050775 +0.1063 +0.046321 +0.09346 +0.18002 +0.24415 +0.016196 +0.0071926 +0.012974 +83.038 +225.78 +111.97 +16.769 +66.728 +80.289 +0.0855 +0.054759 +0.075428 +1.2624e-05 +5.6341e-06 +9.1799e-06 +1.8029e-05 +5.4194e-05 +1.7822e-05 +2.4298e-05 +2.2995e-05 +0.011558 +16.729 +0.0051966 +0.006055 +25.165 +12.289 +33.44 +0.043703 +187.61 +18.258 +33.113 +10.529 +0.034429 +0.022848 +0.023204 +0.028452 +136.07 +0.022313 +0.045408 +0.0079732 +0.0078156 +0.032748 +0.026976 +0.092872 +0.03735 +0.0051307 +0.010701 +2.7685e-06 +4.9666e-06 +1.022e-05 +2.1973e-05 +0.0060967 +0.029113 +0.048285 +0.088998 +0.19865 +0.027988 +0.29715 +0.18875 +505.82 +0.017706 +73.799 +0.023977 +0.013389 +142.78 +149.43 +21.919 +45.145 +59.213 +0.1038 +0.082851 +5.4693e-06 +2.7247e-06 +4.2157e-06 +3.4732e-06 +1.816e-06 +1.158e-05 +2.2036e-05 +2.3251e-06 +4.1459e-06 +0.022457 +0.0076117 +0.0070432 +69.168 +17.18 +17.202 +79.183 +89.411 +160.71 +13.218 +71.401 +0.033579 +0.011585 +0.10133 +0.054753 +0.049085 +224.53 +0.019651 +0.023521 +0.0038992 +0.017413 +0.061447 +0.050834 +0.10931 +0.020776 +0.0076966 +0.23035 +0.64683 +1013.4 +1070.5 +0.023279 +0.010271 +0.015452 +0.029664 +0.066662 +4.4901e-06 +3.3646e-06 +7.4568e-06 +0.10408 +436.79 +145.35 +111.82 +0.016515 +0.011714 +0.0069967 +98.402 +123.38 +81.446 +0.29091 +0.13385 +1.0492e-05 +9.618e-06 +1.7501e-05 +4.2574e-06 +4.5451e-06 +3.2037e-06 +6.4184e-06 +1.3178e-05 +4.5783e-06 +1.872e-05 +0.038062 +0.011271 +0.0086495 +75.031 +23.711 +27.097 +66.173 +98.692 +43.807 +10.053 +0.042875 +38.815 +0.013141 +0.014174 +0.051804 +195.65 +247.32 +0.022494 +0.04559 +0.090334 +0.036835 +0.074147 +0.039417 +0.082535 +0.071921 +0.012673 +0.0053909 +0.16822 +1176.2 +1601.3 +2168.1 +0.0063056 +0.01963 +0.020731 +1.8731e-06 +8.1244e-06 +3.119e-06 +3.4039e-06 +0.1053 +376.91 +137.27 +214.24 +63.241 +0.043648 +0.0071696 +54.988 +0.030312 +207.34 +140.36 +4.3608e-06 +5.7146e-06 +3.4246e-05 +1.3845e-05 +5.0325e-06 +1.0604e-05 +2.2569e-06 +1.0474e-05 +1.7147e-05 +2.6691e-05 +6.6749e-05 +0.037588 +0.0096477 +0.018603 +76.707 +27.976 +16.733 +32.809 +38.861 +35.252 +9.0337 +0.070212 +46.084 +0.021721 +0.24003 +0.039082 +0.052863 +203.63 +50.927 +0.090257 +0.078616 +0.058342 +0.15554 +0.027307 +0.079645 +0.069255 +0.015724 +0.0064409 +0.06938 +0.19535 +1303.5 +1472.7 +2058.5 +0.011513 +0.019653 +1.0065e-06 +5.226e-07 +1.5142e-06 +4.4592e-06 +252.5 +210.45 +0.056997 +421.24 +126 +283.51 +0.0091569 +0.03727 +143.87 +260.36 +1.4671e-05 +2.2754e-06 +5.8072e-06 +2.5578e-05 +3.73e-05 +1.2615e-05 +1.0488e-05 +4.0757e-06 +3.8922e-06 +1.141e-05 +0.00015126 +0.00052666 +5.0732e-05 +0.0001732 +0.0057488 +0.016249 +33.586 +32.845 +44.006 +60.994 +18.201 +7.2348 +24.933 +81.304 +0.0083895 +0.11658 +0.050666 +0.070471 +161.13 +67.914 +0.048678 +0.085098 +0.07925 +66.559 +0.0097752 +86.34 +0.05064 +0.02597 +0.0063292 +0.025946 +0.028167 +1378.3 +893.24 +1778.9 +0.015472 +1.8093e-05 +2.3153e-06 +1.3063e-06 +6.2635e-06 +440.52 +28.2 +296.51 +0.11462 +0.10075 +189.31 +469.06 +0.055579 +0.037358 +269.34 +153.04 +0.00015394 +7.1805e-06 +4.1543e-05 +2.2775e-05 +1.6103e-05 +1.4905e-05 +3.836e-05 +5.9474e-06 +6.8608e-06 +3.7691e-05 +5.6713e-05 +0.00044797 +2.1819e-05 +6.5353e-06 +0.0045733 +0.0083197 +0.015454 +0.0098953 +13.37 +30.152 +10.922 +11.6 +32.204 +8.0292 +11.075 +0.069139 +0.042364 +0.050346 +63.38 +119.44 +32.779 +0.093374 +0.066461 +0.024523 +0.00971 +273.41 +0.079412 +0.023475 +0.010176 +0.0094315 +0.029258 +0.082585 +677.19 +542.9 +0.0065881 +0.00012157 +2.0488e-05 +4.1237e-06 +5.5386e-06 +2.2325e-05 +75.708 +0.012301 +0.30591 +115.12 +65.876 +138.28 +0.10394 +0.03523 +0.01279 +5.7797e-06 +6.0867e-05 +1.5544e-05 +2.1043e-05 +2.5787e-05 +2.688e-05 +2.0647e-05 +5.459e-05 +7.2486e-06 +4.1144e-06 +6.1576e-06 +3.7612e-05 +2.2198e-05 +6.1339e-06 +1.8407e-06 +0.0077257 +0.013734 +0.019979 +0.0093143 +20.944 +29.224 +12.565 +9.1943 +12.516 +0.0051445 +201.06 +0.042182 +0.032757 +0.076136 +75.101 +81.426 +38.514 +0.02309 +0.0086811 +0.01777 +4.6207e-06 +425.13 +0.044781 +0.035922 +0.022509 +0.0085249 +0.039868 +0.14506 +472.06 +0.32035 +0.23039 +8.5812e-06 +1.2855e-05 +5.8119e-06 +5.8183e-06 +24.848 +101.44 +7.3316 +105.57 +180.17 +0.037171 +86.407 +233.22 +0.012696 +0.013574 +224.51 +2.8827e-05 +9.2401e-05 +9.9892e-06 +6.3414e-06 +4.7237e-06 +2.3694e-05 +1.953e-05 +1.6815e-06 +6.2956e-06 +1.0603e-05 +2.0299e-05 +6.8023e-06 +1.5586e-06 +7.9782e-06 +6.9472e-06 +0.00709 +0.01688 +24.901 +19.869 +26.817 +11.72 +3.5711 +10.036 +44.565 +0.068931 +153.12 +0.025516 +0.03969 +69.904 +70.409 +44.468 +0.019256 +0.013209 +0.037794 +2 +192.33 +0.053518 +0.042213 +0.02037 +0.010314 +0.016408 +0.038422 +0.35952 +0.33266 +4.3644e-05 +8.7682e-05 +2.1329e-05 +0.021608 +20.36 +26.468 +99.75 +12.097 +22.776 +0.057144 +0.068147 +0.070388 +225.58 +0.0096307 +16.51 +245.1 +257.36 +0.00018641 +3.0399e-05 +2.3181e-06 +9.5362e-06 +8.5263e-06 +2.839e-06 +6.9068e-06 +4.5199e-06 +7.7594e-06 +1.4852e-05 +8.044e-06 +4.5626e-06 +2.9042e-06 +6.2378e-06 +0.003899 +29.115 +37.701 +38.926 +54.623 +13.707 +17.429 +0.047137 +0.0087832 +0.040789 +155.82 +0.027096 +0.049063 +113.93 +78.173 +70.763 +1367.7 +0.010119 +66.044 +2 +54.928 +147.53 +0.07849 +0.019265 +0.026635 +0.032163 +0.026047 +1184.3 +1.5472e-05 +1.247e-05 +8.6955e-06 +1.5395e-05 +0.0017211 +59.305 +27.725 +130.27 +0.0030135 +56.696 +114.44 +945.33 +344.19 +66.637 +0.017138 +2.386 +167.71 +182.61 +0.028197 +2.2344e-05 +8.2356e-06 +5.2349e-06 +4.474e-06 +6.468e-07 +8.5523e-06 +5.5831e-06 +1.6622e-05 +7.1888e-06 +5.1486e-06 +1.0634e-06 +1.0723e-05 +28.46 +0.00341 +33.79 +24.51 +37.722 +30.677 +9.173 +0.032797 +0.034143 +0.0087525 +0.026253 +0.043291 +0.0077231 +117.46 +93.641 +73.856 +1195.9 +958.97 +0.039199 +75 +65.327 +59.849 +339.4 +0.032268 +0.029015 +0.02575 +0.037657 +3.2552e-05 +2.0756e-05 +4.1813e-05 +4.6419e-05 +4.2621e-05 +3.1134 +0.0015666 +0.0043303 +278.27 +220.71 +31.054 +44.953 +0.038174 +619.58 +0.01087 +0.015515 +0.0074238 +2.9237 +0.056477 +221.92 +95.667 +0.025418 +5.016e-06 +1.5938e-05 +4.4953e-05 +6.4601e-05 +2.1304e-06 +4.6599e-06 +3.7551e-06 +5.0755e-06 +4.9153e-06 +0.067011 +0.031338 +60.833 +0.0025987 +41.405 +0.0074498 +50.206 +0.089658 +0.047779 +0.06176 +0.018795 +0.0076598 +0.038653 +0.070547 +51.639 +0.044419 +152.64 +418.32 +747.55 +42.242 +109.09 +339.58 +0.040283 +37.687 +0.098979 +0.076808 +0.021783 +0.0093863 +7.3146e-06 +1.392e-05 +6.6525e-06 +6.4315e-06 +8.6e-06 +6.2137e-06 +3.304 +0.0011121 +0.0089623 +151.6 +68.108 +17.999 +53.958 +0.062313 +0.016734 +0.014528 +0.01063 +0.018374 +0.0023414 +0.035303 +0.034634 +35.5 +3.8989e-05 +4.8508e-06 +1.4228e-05 +5.9671e-06 +5.8192e-06 +1.5036e-05 +4.2229e-05 +2.2523e-05 +1.0655e-05 +1.7156e-05 +0.062991 +0.050561 +0.022795 +0.0055159 +0.014797 +0.0085203 +0.15981 +0.12437 +0.10363 +0.016831 +0.01419 +0.018092 +0.058224 +0.044222 +78.358 +92.785 +1615.3 +2.9577e-05 +0.014873 +0.0099551 +63.952 +220.75 +0.076704 +47.138 +0.0049371 +299.84 +140.21 +1.5842e-05 +3.1487e-06 +4.0931e-06 +2.0878e-05 +1.5259e-05 +3.3171e-05 +0.0011363 +2.4674 +0.00069178 +62.554 +71.536 +73.956 +37.487 +0.0057279 +0.010368 +0.013334 +0.015473 +0.019842 +0.060644 +14.998 +0.054356 +0.031061 +76.342 +9.4992e-06 +8.6519e-06 +1.2653e-05 +6.8546e-06 +9.167e-06 +4.7976e-06 +8.0055e-06 +1.8503e-05 +6.5935e-06 +0.043644 +0.038365 +0.017741 +0.018957 +0.0089964 +0.028968 +0.09752 +0.034099 +0.010923 +0.0051145 +0.016532 +0.00795 +0.022037 +0.11444 +0.056487 +1870 +0.032603 +0.025897 +0.0080484 +0.010437 +0.0070665 +0.017214 +182.22 +0.13154 +610.7 +0.041198 +0.095381 +3.7991e-06 +5.6282e-06 +3.9962e-06 +5.9559e-06 +1.805e-05 +2.7062e-05 +0.00014387 +1.3982 +41.638 +34.124 +0.0010047 +0.0015914 +18.261 +17.027 +0.0023284 +0.01449 +0.013317 +0.0242 +0.0076539 +0.036693 +0.006701 +0.043908 +0.060139 +87.829 +0.16792 +2.0646e-05 +9.0226e-06 +5.1762e-06 +1.6651e-05 +6.3797e-06 +3.858e-06 +5.3665e-06 +5.3837e-06 +0.034242 +0.035726 +1.4388e-05 +0.020749 +0.036489 +0.02439 +0.067755 +0.01779 +0.017202 +0.0039464 +0.014403 +0.016396 +0.010644 +2803.3 +2201.7 +0.013406 +0.028362 +0.069786 +0.010766 +0.011239 +0.017522 +187.96 +1.3755e-05 +297.84 +420.31 +0.04115 +0.084772 +0.18328 +2.6055e-05 +3.7582e-05 +8.1309e-06 +1.7563e-05 +1.2407e-05 +0.062501 +372.48 +0.0080451 +0.0017904 +0.0018647 +0.00068496 +0.00026433 +0.0084082 +0.0046953 +0.014448 +0.014576 +0.022934 +0.011221 +0.017566 +0.01334 +0.049373 +0.077702 +0.043879 +0.22234 +2.4289e-05 +9.0909e-06 +5.4286e-06 +3.5886e-06 +4.2054e-06 +1.7021e-06 +3.6003e-06 +3.3485e-06 +5.6762e-06 +0.071437 +0.011205 +0.030228 +0.082707 +0.029239 +0.045893 +0.036344 +0.017285 +0.010884 +0.025263 +0.023415 +3607.1 +0.010283 +0.013489 +0.025497 +0.05073 +0.069386 +0.023478 +67.256 +2.1142e-05 +1.5445e-05 +6.9956e-06 +148.44 +183.24 +186.76 +0.10291 +0.17721 +0.030151 +1.8088e-05 +1.2615e-05 +8.3816e-06 +0.03322 +4.5379e-06 +1.8357e-06 +2.4315e-06 +0.0014364 +4.4147 +2.246 +0.0058744 +0.0077545 +0.007997 +0.02235 +0.017129 +0.023606 +0.016315 +0.025584 +0.051673 +1.1899e-06 +0.071716 +0.029642 +0.21017 +0.073389 +1.2212e-06 +2.4235e-06 +2.7301e-06 +2.557e-06 +1.0744e-06 +2.4276e-06 +4.748e-06 +0.0094542 +0.0080874 +0.0099301 +0.030732 +0.086822 +0.068278 +0.043797 +0.048238 +0.037226 +0.030769 +0.003634 +0.015575 +0.0081583 +0.012778 +0.010665 +0.010124 +0.042424 +0.043357 +0.020287 +1.3553e-05 +2.0352e-06 +5.4023e-06 +3.7423e-06 +2.3142e-06 +111.86 +155.7 +0.052658 +0.083426 +0.029872 +0.009051 +179.33 +326.26 +2.6311e-06 +3.2221e-06 +6.7858e-06 +3.7855e-06 +6.7948e-06 +5.9987e-06 +0.010408 +0.0095129 +0.01477 +0.014352 +0.032302 +0.014859 +0.048715 +0.05964 +0.086381 +0.093784 +0.035545 +0.019874 +0.017955 +0.20365 +1.7805e-06 +2.7843e-06 +3.7913e-06 +3.9088e-06 +2.631e-06 +2.2821e-06 +0.023555 +0.011799 +0.004388 +0.0090053 +0.012931 +0.024962 +0.10788 +0.1344 +0.04969 +0.043009 +0.037478 +0.0029099 +0.0094298 +0.014363 +0.016217 +0.014208 +0.0071208 +0.0092798 +0.022248 +0.29873 +4.223e-06 +2.3116e-06 +1.6845e-05 +2.9541e-06 +4.3063e-06 +296.54 +83.087 +200.65 +0.03064 +0.072162 +0.038179 +0.081732 +630.01 +0.00078004 +2.9002e-06 +6.3596e-06 +3.2126e-06 +0.016494 +0.016656 +0.016223 +0.014435 +0.0091474 +0.010339 +0.0087628 +0.024426 +0.031917 +0.055378 +0.065483 +0.04618 +0.051182 +0.020813 +0.034031 +0.0392 +0.078686 +3.6235e-06 +8.0712e-06 +8.9838e-06 +1.6975e-05 +5.1504e-06 +0.022724 +0.014728 +0.0082719 +0.0023627 +0.0046817 +39.68 +0.018831 +0.086068 +0.057589 +0.028871 +0.07631 +22.124 +0.011637 +0.0096039 +0.016491 +0.0073634 +0.014424 +0.0070428 +0.0070998 +0.38152 +0.20414 +1.3388e-05 +1.3954e-05 +1.3916e-05 +2.3716e-06 +1.9203e-06 +276.38 +86.274 +237.21 +0.1085 +0.099812 +0.037165 +163.73 +410.32 +0.0011845 +1.1215e-06 +0.57478 +1.0258 +0.084105 +0.011753 +0.015313 +0.016942 +0.012066 +0.014486 +0.02851 +0.028917 +0.013082 +0.021767 +0.02058 +0.028847 +0.043223 +0.018183 +0.025183 +0.10772 +0.073678 +3.2814e-05 +6.4353e-06 +1.8512e-05 +4.1463e-06 +0.012027 +0.019009 +0.010656 +0.0093094 +0.0025747 +23.856 +0.019222 +0.023007 +0.11617 +0.055042 +0.034185 +53.223 +40.283 +0.017731 +0.01055 +0.016413 +0.012076 +0.0059415 +0.0040681 +0.0045245 +0.25685 +0.30293 +0.4473 +2562.6 +2.2298e-06 +3.5673e-06 +3.5346e-06 +293.25 +118.39 +274.16 +0.064609 +0.23714 +0.029766 +0.027983 +293.15 +0.012468 +3.1991e-06 +0.4585 +0.96695 +0.097054 +0.017193 +0.0084455 +0.021119 +489.01 +837.9 +0.046526 +0.014491 +0.014896 +0.014798 +0.013303 +0.041629 +0.032425 +0.011846 +0.02361 +0.10855 +0.079089 +3.8909e-05 +1.3582e-05 +8.3521e-06 +4.4139e-06 +0.010048 +0.008916 +0.012024 +0.0087716 +21.915 +20.664 +0.014498 +0.038736 +281.41 +0.052841 +0.116 +0.045876 +52.592 +0.014855 +0.0059324 +0.017046 +0.017892 +0.0048419 +0.0070679 +0.40907 +0.53403 +0.31196 +0.62015 +2472.8 +5024.7 +3740.6 +0.01028 +198.18 +65.313 +263.91 +0.064942 +0.20045 +0.021234 +0.028894 +0.022595 +0.030823 +0.056239 +0.57844 +0.52126 +0.0351 +0.012582 +0.007504 +0.047605 +5.4004e-06 +185.81 +0.022783 +0.019105 +0.0071829 +0.020496 +0.016122 +0.017801 +0.019332 +0.016302 +0.043327 +0.14546 +0.075413 +0.027106 +1.9848e-06 +1.1036e-05 +4.7296e-06 +0.010688 +0.0095277 +0.0095915 +33.536 +15.096 +45.921 +0.020004 +0.036517 +0.11012 +0.072967 +0.18371 +2.878e-06 +58.71 +0.020286 +0.0072614 +0.021257 +0.018985 +0.0051696 +0.017623 +0.015016 +0.60937 +0.37463 +0.41049 +5458.1 +10.158 +0.0083221 +18.792 +81.858 +91.937 +273.24 +0.062476 +0.16939 +0.017595 +0.029147 +0.015622 +0.051446 +0.069638 +0.034506 +0.49247 +0.07305 +0.021128 +0.021053 +0.089553 +1.0021e-05 +0.0018802 +0.018356 +0.02366 +0.0065828 +0.016185 +0.0079685 +0.031864 +0.045392 +0.084164 +0.08056 +0.17302 +0.075139 +0.019002 +4.8484e-06 +5.0683e-06 +3.8711e-06 +0.024493 +0.018015 +27.077 +31.855 +15.511 +177.54 +54.009 +0.047985 +0.049626 +0.11321 +0.1525 +0.0046547 +46.805 +0.022487 +0.012904 +0.039141 +0.026058 +0.0053318 +0.0082291 +5.8325 +0.0066122 +0.45067 +81.448 +31.549 +18 +0.01557 +27.598 +73.446 +289.89 +154.36 +0.033886 +386.26 +0.010438 +0.027178 +84.459 +0.089433 +0.075746 +0.033409 +0.5967 +0.10829 +0.025695 +0.01571 +0.19303 +1.6706e-05 +2.3357e-05 +0.0020546 +0.013589 +0.0057231 +0.0071034 +0.0063959 +0.026883 +0.053806 +0.036428 +0.13273 +173.3 +0.045341 +0.047146 +3.2577e-06 +9.6693e-06 +3.0402e-06 +9.4e-06 +7.4792e-06 +23.587 +19.799 +11.784 +91.995 +103.45 +0.051079 +0.077237 +0.069405 +3.337e-06 +0.0069284 +81.191 +87.019 +0.014275 +0.026181 +0.014463 +0.0035737 +0.0083141 +8.3283 +362.27 +161.48 +59.501 +66.852 +0.016179 +100.81 +35.772 +67.885 +224.26 +394.06 +0.033985 +0.083174 +30.817 +1.8271e-05 +8.8591e-06 +0.036918 +0.076411 +0.030249 +0.0030472 +0.24021 +0.043265 +0.031617 +0.24183 +3.5435e-05 +0.0033611 +0.0032474 +0.0098578 +0.011795 +0.0091226 +0.010223 +0.023326 +0.027937 +0.027932 +0.028064 +111.29 +0.073111 +0.059538 +0.088963 +3.6594e-05 +1.9786e-06 +1.0423e-05 +4.0005e-06 +9.8633 +35.141 +0.0073209 +69.693 +75.741 +0.0651 +0.018384 +1.0801e-05 +0.0027506 +0.018861 +152.74 +80.01 +0.016845 +51.767 +0.010956 +0.0055617 +75.829 +182.11 +259.56 +141.83 +80.538 +189.88 +0.032874 +0.033195 +25.118 +78.557 +198.31 +482.36 +0.032939 +3.9644e-05 +4.3631e-05 +3.9884e-05 +3.7352e-05 +13.391 +0.026062 +0.024654 +0.054103 +0.012829 +0.33624 +0.060247 +0.2247 +0.20841 +0.001981 +0.0032902 +0.011082 +0.028974 +0.027199 +0.037051 +0.015657 +0.014843 +0.02718 +0.024604 +92.502 +0.051393 +0.043725 +0.072229 +5.5349e-06 +6.4215e-06 +6.0211e-06 +10.56 +13.005 +24.696 +0.011622 +77.727 +90.043 +274.34 +5.1738e-06 +4.402e-06 +0.084558 +34.373 +260.12 +0.017151 +30.02 +13.539 +0.0049633 +180.24 +120.29 +356.77 +131.44 +100.02 +100.27 +151.9 +0.10094 +0.032967 +0.019395 +0.065063 +2 +0.97862 +1.4168 +3.8846e-05 +2.6615e-05 +1.5357e-05 +1.6432e-05 +2.2051e-05 +0.028496 +0.050352 +0.022677 +0.017201 +6.4423 +0.028529 +871.52 +0.23621 +0.19424 +0.0083699 +0.0073349 +0.022287 +0.020962 +0.037026 +0.026928 +0.10467 +0.018919 +0.015117 +120.04 +0.028485 +0.10561 +0.035395 +5.5006e-06 +3.7158e-06 +5.8991e-06 +15.972 +0.0074838 +18.524 +0.013569 +0.013602 +0.076878 +0.065357 +394.02 +554.14 +0.095828 +13.306 +82.093 +0.0080772 +20.073 +0.0066443 +0.0015835 +93.103 +249.37 +262.44 +78.234 +60.569 +154.39 +107.2 +0.092111 +6000 +6000 +2 +2 +100.04 +120.43 +121.41 +0.025502 +8.0324e-06 +1.3233e-05 +1.3573e-05 +6.8013e-06 +42.166 +0.011524 +0.018685 +7.5898 +6.2225 +1286.6 +801.18 +0.14317 +0.25396 +0.19942 +0.016374 +38.021 +0.039995 +0.099557 +0.089665 +0.044685 +0.010879 +71.768 +0.028456 +0.05115 +0.054392 +4.5725e-05 +9.2232e-06 +69.235 +0.014268 +0.0065559 +0.01852 +0.015898 +91.916 +0.14131 +7.376e-06 +9.0521e-06 +1.6032e-05 +519.05 +11.263 +53.404 +42.377 +34.791 +15.582 +0.0015798 +162.89 +192.05 +317.99 +73.708 +3.2582e-05 +3.2508e-05 +1.5372e-05 +6000 +4149.6 +4984.7 +2 +2 +1.7596 +534.99 +168.93 +0.018011 +208.91 +5.9353e-06 +0.015976 +0.0075456 +0.011869 +0.025825 +0.1071 +0.012954 +0.010061 +2.7963 +583.01 +0.21794 +0.262 +0.17877 +46.455 +0.010489 +13.561 +0.02776 +0.088544 +0.03838 +0.0079739 +28.335 +0.090437 +0.06516 +6.7856e-06 +0.00017106 +4.1091e-06 +51.025 +0.0053609 +0.0083895 +0.02286 +47.102 +133.71 +496.9 +64.618 +64.36 +96.972 +79.076 +216.63 +311.95 +38.415 +51.812 +10.783 +3.5018 +115.4 +5.4976e-06 +5.6484e-06 +5.4125e-05 +3.867e-05 +4.0171e-05 +2.9226e-05 +6000 +6000 +0.89211 +2 +2 +1.266 +0.64667 +418.62 +0.014794 +0.035631 +5.831e-06 +2.4296e-05 +0.0086243 +0.015372 +0.03313 +0.067456 +0.055137 +0.013256 +3.9672 +0.00092287 +0.1452 +0.14805 +0.18563 +0.27367 +0.092497 +12.731 +18.466 +34.214 +26.857 +47.027 +0.0059733 +0.058463 +0.038405 +9.2109e-06 +2.2831e-05 +2.9556e-05 +32.799 +0.010795 +0.012346 +0.011261 +0.012059 +0.042251 +0.24421 +929.72 +92.366 +0.053893 +138.1 +122.64 +621.42 +0.46128 +67.771 +8.4229 +5.361 +3.5068 +2.7726 +2.5543e-05 +2.6083e-05 +1.8224e-05 +5.6139e-05 +4542.5 +6000 +2 +1.0371 +2 +2 +14.843 +11.086 +319.12 +0.020247 +59.069 +2.1012e-05 +9.7823e-06 +0.0064417 +0.017478 +0.053315 +0.041396 +0.0011479 +0.0068185 +0.0043638 +0.0013485 +3.0873 +0.16564 +0.11651 +0.20489 +0.010233 +0.0068549 +21.593 +71.552 +30.994 +0.010199 +0.0048875 +0.0043378 +1.3187e-05 +4.6404e-06 +1.6419e-05 +6.4174e-05 +2.9613e-05 +0.0049225 +0.019535 +0.028827 +53.38 +0.020791 +498.84 +795.44 +0.021976 +0.04988 +178.26 +158.2 +712.31 +0.34344 +78.871 +0.0049239 +0.0015312 +2.8033 +0.0005436 +7.6231e-06 +1.7327e-06 +3.6808e-05 +6000 +4092.2 +2 +2 +0.93872 +2 +19.408 +10.848 +7.1272 +231.42 +8.1627e-06 +3.3605e-06 +3.1971e-06 +0.0089904 +0.0079553 +0.012775 +0.039549 +0.0011296 +0.0043573 +0.0091118 +0.00471 +0.0077163 +5.2384 +0.0063621 +0.018077 +0.20076 +0.01815 +0.014537 +0.0035083 +51.063 +28.662 +0.0060156 +0.0041244 +0.0023391 +0.006986 +3.07e-05 +7.7237e-06 +5.3307e-05 +5.8566e-05 +2.3657e-05 +0.0077484 +0.011225 +0.09302 +0.014383 +305.88 +697.33 +0.036298 +0.024342 +125.93 +412.19 +1556.3 +0.31941 +119.58 +0.0047299 +0.00090425 +3.9539 +0.00049446 +1.1462e-05 +7.608e-06 +1.1186e-05 +6000 +6000 +2 +1.3096 +0.42928 +2 +6.0208 +7.745 +13.817 +11.547 +4.7873e-06 +3.8792e-06 +2.0183e-05 +6.0446e-05 +6.7169e-06 +1.8499e-05 +8.4948e-06 +0.0012808 +0.0060674 +0.0079399 +0.0053937 +6.0922 +6.2203 +27.862 +54.121 +0.098075 +0.029944 +0.011378 +0.0025021 +0.0041784 +19.664 +19.362 +0.0055268 +0.0032824 +0.0059059 +0.0075303 +2.0485e-05 +3.0454e-05 +8.0804e-05 +3.0306e-05 +2.1426e-05 +0.027283 +0.048885 +0.063985 +375.29 +414.55 +0.075677 +67.37 +162.83 +0.23106 +1330.8 +0.02519 +0.0057621 +1.2822e-05 +0.0022411 +1.2755 +0.0006105 +10.453 +2.0933 +6.0394e-05 +6000 +5839.4 +5236.5 +1272 +0.41726 +1.6587 +19.621 +9.8083 +19.571 +23.521 +3.6713e-06 +1.9119e-05 +3.1752e-05 +5.6851e-05 +3.9968e-06 +2.9245e-06 +0.0030799 +0.0026298 +0.022798 +0.012925 +0.0061616 +8.0566 +10.098 +28.156 +0.011668 +0.070072 +0.021395 +0.012649 +0.0025579 +0.0084178 +0.0049549 +0.00085375 +0.0028304 +0.0026286 +0.010617 +0.0045605 +4.9351e-06 +1.7173e-05 +6.9811e-05 +5.2192e-06 +3.5938e-05 +0.024335 +0.031511 +0.16048 +998.27 +456.75 +991.91 +206.28 +123.71 +593.94 +0.057166 +0.089101 +0.00959 +0.077936 +0.087137 +1.0541 +2.973 +9.8521 +4.6754 +7.609 +6000 +2458.9 +2468 +1080.4 +0.77322 +0.55087 +0.58741 +6.9197 +15.548 +18.1 +46.231 +7.1506e-05 +5.6885e-06 +1.1326e-05 +1.5941e-06 +0.019796 +0.0062482 +0.0023728 +0.021373 +0.024499 +7.8985 +2.7384 +13.623 +36.068 +28.971 +0.090768 +0.054016 +0.0068777 +0.0094686 +0.0065724 +0.0046961 +0.0012289 +0.0027698 +0.0029001 +0.010836 +0.0049029 +14.294 +2.7776e-05 +8.2964e-05 +6.854e-06 +0.0099124 +0.0077718 +0.014085 +0.10048 +0.79601 +700.27 +1394.8 +420.83 +389.6 +491.64 +7.2125e-06 +0.06885 +623.92 +175.46 +0.3649 +1.3051 +3.1052 +12.954 +6.5447 +3.3335 +5839.4 +2726.5 +2585.2 +969.86 +0.35624 +0.26205 +0.29837 +1.0192e-05 +5.0717e-06 +1.1496e-05 +9.2781 +9.3613 +23.256 +5.5553e-06 +0.047138 +0.017976 +0.010076 +0.0047416 +0.041541 +8.7209 +5.8648 +3.6775 +15.88 +24.375 +31.199 +0.10438 +0.031465 +0.013876 +0.025309 +0.010164 +16.958 +2.8234 +0.0012099 +0.0086919 +0.014569 +0.0084334 +17.86 +0.00035592 +0.00014952 +2.0445e-05 +0.012668 +0.011203 +0.011911 +0.035173 +0.12892 +426.33 +513.43 +709.46 +603.71 +754.59 +0.11199 +2.8167e-06 +0.11733 +365.85 +0.30307 +1.933 +7.3606 +12.184 +6.1023 +3.0081 +10.036 +1521 +1446 +0.42782 +0.54209 +0.14735 +5.7922e-06 +2.2536e-05 +1.0497e-05 +1.6221e-05 +1.0651e-05 +2.1999e-06 +0.043308 +0.07008 +0.085604 +0.036187 +0.024395 +0.011559 +16.506 +8.8251 +2.8509 +2.9803 +13.55 +49.954 +14.044 +0.087939 +0.019378 +0.012807 +0.017934 +0.010869 +0.013575 +1.6657 +0.0020318 +0.0049264 +0.0085334 +0.016548 +19.1 +8.4262e-05 +5.9375e-05 +3.0898e-05 +4.2635e-06 +0.0072153 +0.020403 +0.013092 +0.063733 +0.023095 +706.97 +414.73 +561.81 +583.08 +0.0020261 +211.7 +262.07 +421.31 +0.0015366 +0.88418 +18.062 +0.0045805 +7.8957 +0.0010562 +5.7128 +8.9081 +780.01 +802.15 +8.1876e-06 +4.3923e-06 +2.819e-05 +1.1478e-05 +2.8511e-06 +8.4036e-06 +0.00027731 +0.01344 +0.018552 +0.011287 +0.051091 +0.052047 +0.034535 +6.3346e-06 +0.0073226 +11.444 +2.9458 +3.5658 +11.447 +0.13536 +0.19877 +0.027293 +0.02031 +0.011625 +0.013602 +0.010543 +0.015547 +0.00054723 +5.564 +9.62 +54.679 +0.0090351 +0.010949 +8.1705e-05 +3.4805e-05 +3.8671e-06 +6.2894e-06 +0.012842 +0.021559 +0.017889 +0.091523 +0.019308 +266.02 +615.17 +555.65 +255.66 +48.91 +0.13518 +166.1 +0.0032529 +0.0015394 +2.2295 +10.092 +0.002694 +14.312 +0.0016751 +6.4326 +6.7649 +352.36 +0.29161 +5.5861e-06 +2.1274e-06 +3.5199e-06 +1.2111e-05 +3.0879e-06 +6.5266e-06 +0.00075117 +0.0074467 +0.017732 +0.028132 +0.028142 +0.057749 +5.0091e-06 +1.8737e-05 +1.568e-05 +8.5588 +8.2889 +0.2517 +0.07381 +0.093311 +0.087179 +0.03202 +0.015703 +0.013477 +0.016869 +0.043501 +0.065292 +0.18598 +0.092577 +0.14861 +0.16614 +0.44119 +0.0046269 +2.0478e-05 +3.9581e-05 +1.4735e-05 +2.5938e-06 +7.892e-07 +0.016987 +0.019828 +0.078471 +0.27178 +0.13774 +971.57 +1517.3 +208.57 +58.711 +0.1475 +0.00019986 +0.0013711 +0.0016673 +10.781 +4.5664 +0.0020127 +19.575 +6.2006 +0.0039491 +15.561 +442.02 +2.4469e-06 +4.9945e-06 +4.7797e-05 +5.4648e-06 +3.2764e-06 +8.1617e-06 +1.2342e-06 +0.0010976 +0.011337 +0.046865 +0.044229 +0.027133 +0.12677 +2.819e-06 +5.3603e-06 +5.4862e-06 +12.911 +0.035007 +0.1881 +0.15001 +0.095093 +0.051564 +0.047951 +0.1144 +0.1023 +0.05922 +0.03292 +0.094742 +0.097381 +0.14476 +0.26779 +0.42137 +0.14448 +1.1079 +3.0241e-06 +6.9073e-06 +3.6347e-06 +3.097e-06 +5.8345e-06 +6.6494e-06 +0.017542 +0.30261 +346.86 +654.89 +880.85 +654.55 +249.66 +45.907 +211.96 +0.00032145 +0.00092865 +0.0011159 +5.3687 +0.0017044 +0.0023973 +25.589 +10.345 +0.0088593 +11.903 +2.1368e-05 +3.2631e-06 +5.0632e-06 +0.000104 +0.00011297 +5.9103e-06 +7.7958e-06 +1.1299e-05 +0.0023192 +0.0035882 +0.043807 +0.022529 +0.041125 +0.079182 +3.9732e-06 +6.9966e-06 +7.1924e-06 +0.024733 +0.063464 +0.21558 +0.08722 +0.086118 +0.011231 +29.685 +129.33 +532.58 +465.92 +208.45 +564.91 +0.15818 +0.091039 +0.20784 +850.86 +0.35057 +0.055337 +6.8438e-06 +4.74e-06 +8.1545e-06 +7.7128e-06 +1.4198e-05 +9.065e-06 +1.5977e-05 +851.21 +424.45 +433.74 +1911.8 +1300.2 +335.69 +0.0015122 +3.4667 +0.00024852 +0.0020439 +0.0021996 +0.0028635 +0.0027434 +0.002446 +41.455 +18.885 +25.53 +42.964 +5.8604e-06 +2.2878e-06 +1.9812e-06 +1.9787e-05 +4.8935e-05 +3.0584e-06 +2.2982e-06 +5.0755e-06 +0.0021166 +0.0040382 +0.015958 +0.019545 +0.053941 +0.019307 +0.0032902 +0.0018827 +0.007382 +0.025764 +0.033634 +0.20659 +0.0058382 +0.0027374 +0.0091346 +0.017889 +221.45 +249.89 +0.21625 +70.395 +617.52 +0.076253 +0.1245 +0.054475 +0.064757 +0.028573 +0.042348 +1.3564e-05 +1.5352e-05 +2.3669e-05 +2.1923e-05 +4.0201e-06 +5.2e-06 +1.5072e-05 +15.373 +306.34 +603.09 +1057.6 +1921.5 +304.07 +0.0014065 +0.0010346 +0.00031605 +0.0015167 +0.0013149 +0.0025728 +0.0022907 +0.0035685 +44.381 +0.0023242 +0.66494 +9.0554e-06 +1.1954e-06 +2.3624e-06 +7.1026e-06 +4.9531e-06 +4.5962e-06 +1.1707e-05 +4.4904e-06 +3.453e-07 +0.0022756 +0.007747 +0.020408 +0.012737 +0.040103 +0.02912 +4.518e-05 +0.0013075 +0.015126 +0.0097186 +0.0047583 +0.012412 +0.0075046 +0.0041142 +0.009146 +0.018245 +293.09 +201.65 +0.068745 +134.09 +215.21 +155.37 +0.093871 +0.063623 +0.10179 +0.051514 +8.6557 +2.1398e-05 +2.4414e-05 +1.7823e-05 +5.5816e-05 +8.5047e-06 +3.1459e-05 +9.849e-06 +7.9809e-06 +16.366 +1073.3 +0.25156 +0.19081 +402.82 +0.00085413 +0.0005534 +0.00044049 +0.0011797 +0.0017816 +0.0020836 +0.0049496 +0.0043551 +0.010172 +10.549 +0.0020077 +1.6516e-05 +1.7769e-06 +8.0451e-06 +9.4329e-06 +3.0378e-06 +6.3156e-06 +1.3578e-06 +2.2231e-06 +1.3782e-06 +1.5439e-06 +0.012772 +0.017731 +0.015885 +0.054111 +0.066776 +0.0021918 +0.011712 +0.0094865 +0.0093768 +0.002875 +0.0094018 +0.018767 +0.011114 +0.02677 +0.036441 +353.63 +0.1002 +0.035612 +0.098239 +0.022403 +0.098379 +46.251 +55.825 +86.094 +26.556 +14.846 +1.7155e-05 +2.1736e-06 +2.9292e-05 +1.2531e-05 +4.2716e-05 +9.1892e-05 +2.0216e-05 +3.8024e-05 +5.2909e-05 +0.041089 +0.18415 +591.7 +0.0027504 +0.0014306 +0.0004465 +0.0011739 +0.0023305 +0.0023479 +5.2192 +0.013909 +20.599 +24.836 +0.0020509 +2 +2.774e-06 +1.3818e-06 +7.1988e-06 +3.9631e-06 +5.4121e-06 +5.9862e-06 +2.0456e-06 +2.1124e-06 +5.9129e-06 +9.583e-06 +0.0099545 +0.020683 +0.012191 +0.0060056 +0.0020178 +0.0063626 +0.0081151 +0.0077169 +0.0063101 +0.003057 +0.0069759 +0.0092996 +0.013447 +0.019173 +0.017007 +0.0085207 +0.096741 +0.0010064 +0.046578 +0.085699 +162.94 +38.577 +31.32 +152.73 +42.696 +9.052 +1.8056e-06 +6.9506e-06 +2.1218e-05 +2.5674e-05 +2.9171e-05 +4.1781e-06 +8.2685e-06 +1.2274e-05 +2.8577e-05 +0.051454 +394.52 +340.32 +108.65 +0.0036529 +0.00057158 +0.0013332 +0.0022623 +0.0042637 +8.3173 +0.0269 +0.0060291 +41.883 +2 +0.0013809 +9.5444e-06 +2.2126e-06 +2.8104e-06 +7.7474e-06 +1.055e-05 +1.0579e-05 +5.5851e-06 +1.5427e-06 +3.8735e-06 +3.1868e-05 +3.1549e-05 +0.032385 +0.001654 +0.006347 +0.003331 +0.0075162 +0.0030931 +0.0049124 +0.010416 +0.0028062 +0.0064962 +0.012233 +548.21 +0.011114 +0.012546 +0.01753 +0.030613 +0.062204 +0.03321 +0.075665 +99.688 +29.877 +29.342 +185.15 +71.372 +7.5459e-06 +9.817e-06 +3.6888e-06 +5.0964e-06 +7.9193e-06 +1.3119e-05 +1.3243e-05 +1.4494e-05 +3.1957e-06 +1.7187e-05 +176.86 +362.46 +189.34 +196.62 +0.0028047 +0.0001964 +0.00088037 +0.00099004 +0.0054197 +0.010886 +0.029279 +0.012763 +0.0080943 +2 +0.0023485 +2.9382e-05 +2.9789e-05 +1.9878e-05 +3.3961e-05 +6.8099e-06 +7.9467e-06 +7.288e-07 +3.7506e-06 +2.8082e-05 +2.4958e-05 +5.342e-05 +0.013892 +0.004391 +0.0080864 +0.0075525 +0.0033456 +0.0043745 +0.0035243 +0.0068509 +72.891 +0.011128 +0.066575 +0.11731 +0.029392 +0.0063573 +0.011711 +0.0065458 +0.043787 +0.24015 +0.032246 +74.637 +2.2628e-05 +3.1325e-05 +2.9867e-06 +5.5075e-06 +3.3352e-05 +1.0808e-05 +9.7961e-06 +5.0965e-06 +9.7559e-06 +2.6001e-05 +1.0609e-05 +2.2272e-05 +1.9604e-05 +4.478e-05 +4.884e-06 +806.56 +155.19 +584.12 +0.29984 +0.30505 +0.0019024 +0.0012228 +0.0036285 +0.011183 +0.093351 +0.03849 +0.00095006 +0.00069376 +0.0032749 +1.4588e-05 +6.3414e-05 +2.3036e-05 +1.9989e-05 +9.6949e-06 +1.3617e-05 +1.7872e-05 +2.2419e-05 +4.9506e-05 +1.051e-05 +2.3654e-05 +0.0084426 +0.0069478 +0.0044515 +0.0066773 +0.0022462 +0.0024596 +0.0025031 +0.0051575 +26.002 +0.0089458 +82.43 +0.17482 +0.034716 +0.0086336 +0.016091 +0.034079 +0.090596 +0.091858 +0.089508 +0.064269 +6.1904e-05 +2.6566e-05 +2.2074e-06 +9.777e-07 +3.8808e-06 +4.6555e-06 +4.9495e-06 +7.2805e-06 +3.9843e-06 +0.041294 +0.052609 +0.012776 +0.068157 +0.10189 +662.15 +966.91 +138.22 +413.12 +0.27223 +0.11386 +0.064642 +0.0008875 +0.0019774 +0.016 +0.12864 +0.0791 +0.05336 +0.00065705 +9.3492e-06 +2.2165e-05 +1.5121e-05 +1.0654e-05 +3.1967e-06 +9.6837e-06 +1.8621e-05 +3.3583e-05 +5.8797e-05 +6.1404e-05 +0.095181 +0.075049 +0.010487 +14.433 +0.0032955 +16.189 +0.0046786 +0.0015958 +0.0044103 +0.48356 +0.00032856 +32.852 +0.05573 +0.043974 +0.034632 +0.011983 +0.073011 +0.042269 +10.293 +0.054707 +0.096138 +0.15934 +0.065775 +0.058154 +8.6168e-06 +1.6832e-06 +1.4373e-05 +3.6174e-06 +1.2091e-05 +0.071886 +111.41 +0.052368 +0.045424 +0.039561 +40.868 +22.273 +59.956 +800.1 +101.76 +296.28 +0.15203 +0.13798 +0.069936 +0.013748 +0.0065923 +0.012129 +0.1393 +0.053065 +0.047579 +0.026341 +0.0048472 +1.4855e-05 +7.0753e-06 +1.673e-05 +4.6154e-05 +4.6442e-05 +6.0423e-05 +7.0573e-05 +6.2273e-05 +5.9138e-05 +0.21108 +0.064445 +0.0096967 +0.0024153 +0.0046223 +24.194 +0.01005 +0.0022023 +0.0098255 +0.00027744 +0.00033778 +0.00014647 +0.040765 +143.39 +0.010945 +0.007238 +1.8237e-05 +0.070403 +10.48 +13.648 +21.027 +0.15576 +0.15275 +0.094592 +0.035364 +9.963e-07 +7.8112e-06 +1.5346e-06 +0.15431 +0.081447 +0.020555 +0.073418 +0.058654 +2.2841e-05 +58.627 +7.5757 +1292.6 +894.76 +114.38 +273.37 +367.09 +553.6 +0.080402 +0.025627 +0.011424 +0.0449 +0.079084 +0.037147 +0.035803 +0.007274 +0.011162 +0.011486 +9.2551e-06 +3.3198e-05 +2.4754e-05 +0.0002024 +2.5662e-05 +4.5082e-05 +7.3556e-05 +1091 +0.13323 +0.073646 +0.0038128 +0.0014932 +0.0075837 +43.609 +0.00495 +0.0030549 +0.01066 +0.00041381 +0.00038719 +1.3212 +16.713 +0.014015 +0.011351 +0.011097 +82.576 +0.0053031 +0.0027742 +0.0028972 +0.079103 +0.14552 +0.080303 +0.085 +0.018782 +0.010759 +2.7439e-06 +0.040667 +0.12811 +0.070442 +0.039219 +0.04722 +3.6087e-05 +1.3702e-05 +32.646 +14.646 +747.02 +421.06 +179.62 +361.91 +211.13 +0.28065 +0.090482 +0.033944 +0.02668 +0.064484 +0.14006 +0.021352 +0.01414 +0.0064925 +0.0059615 +0.021805 +0.014368 +0.015646 +4.8526e-05 +1.0011e-05 +1.1582e-05 +7.3422e-05 +0.00012026 +0.10778 +0.28338 +0.0016095 +0.0053049 +39.745 +0.0081803 +0.0069067 +0.0023986 +0.0049768 +0.00091437 +0.00057868 +0.00057691 +0.00047154 +0.002575 +20.39 +0.0096853 +0.024267 +89.832 +0.0051551 +0.087016 +0.15611 +0.054265 +0.14311 +0.11508 +0.057367 +0.019528 +0.012062 +2.3145e-06 +0.087082 +0.11111 +0.16237 +0.068916 +3.522e-05 +2.7709e-05 +1.833e-05 +25.372 +0.94169 +589.3 +367.15 +295.54 +0.11891 +0.046323 +716.59 +0.03391 +0.059941 +0.0042318 +0.0024308 +0.16902 +0.045407 +0.024287 +0.009249 +0.0073505 +0.026017 +0.010993 +0.008711 +0.010857 +2.5691e-05 +1.0643e-05 +5.489e-05 +2.9398e-05 +0.00010334 +7.6915e-05 +0.0023035 +0.0050295 +0.01121 +0.0042311 +0.0058278 +0.0032937 +0.0056575 +0.0020429 +0.0017221 +0.00048275 +0.0003405 +0.0026037 +0.010989 +78.734 +0.030871 +138.01 +127.21 +0.075979 +0.16718 +0.033606 +0.049413 +0.071763 +0.068186 +0.028917 +0.019057 +1.8026e-05 +0.071193 +0.10832 +0.18275 +0.11711 +0.052414 +6.1159e-06 +3.1658e-06 +0.060527 +0.33475 +510.32 +0.084435 +137.1 +0.025233 +0.031651 +0.10335 +0.028916 +0.0070727 +0.013595 +0.058236 +0.3156 +0.043638 +0.024856 +0.043439 +0.0052032 +0.025251 +0.012967 +0.0064451 +0.0071064 +0.0043197 +2.9187e-06 +7.2202e-06 +3.8776e-05 +0.00024376 +0.018132 +0.0026303 +0.0042276 +38.93 +0.0032753 +0.0029461 +0.0099841 +0.0057437 +0.0028765 +0.0016319 +0.00083125 +0.00073447 +0.0023654 +2.0924e-05 +102.5 +0.042203 +266.56 +160.23 +5.2916e-06 +0.21804 +0.055426 +0.021829 +0.066352 +0.11427 +0.081744 +0.018183 +8.9715e-06 +3.2828e-06 +0.094758 +0.077061 +0.11045 +0.13725 +203.47 +3.667e-06 +0.26593 +0.48562 +0.010841 +36.91 +0.038533 +113.88 +0.028976 +0.025033 +0.0044122 +0.026079 +121.96 +0.10782 +0.31638 +82.107 +0.014351 +0.01687 +0.016171 +0.01712 +0.0083715 +0.0082244 +0.0082581 +0.0057142 +0.0084223 +5.8064e-06 +1.8525e-06 +3.9208e-05 +1.5717e-05 +0.0016971 +0.0026239 +15.653 +0.0014793 +0.011826 +0.0087222 +0.0061228 +0.0019653 +0.0030895 +4.8117 +0.0013371 +7.6717e-06 +4.2508e-06 +1.4079e-05 +110.58 +199.87 +117.23 +0.050148 +0.17177 +0.022722 +0.024115 +0.13412 +0.27001 +0.18067 +1.9326e-05 +6.2515e-05 +8.3615e-06 +6.8975e-06 +0.11319 +0.16152 +0.15457 +0.20758 +0.2324 +1.476e-05 +0.68783 +0.0090707 +93.717 +62.625 +72.696 +0.023334 +0.015102 +150.22 +116.53 +81.836 +0.12543 +1475.2 +29.695 +0.018057 +0.01984 +0.0057886 +0.025946 +78.304 +0.006735 +0.0039523 +0.0042377 +0.0068401 +0.015725 +1.787e-06 +9.3927e-06 +54.224 +0.003016 +0.0022478 +0.0030127 +0.0017203 +0.013604 +0.0033182 +0.0039505 +0.003061 +0.0043289 +8.4944 +0.0012101 +5.1425e-06 +1.1961e-05 +6.2837e-06 +121.42 +154.18 +152.15 +259.3 +0.054576 +0.02116 +0.032155 +0.13831 +8.3571e-06 +1.4291e-05 +5.4787e-06 +6.0374e-06 +7.8012e-06 +1.3783e-05 +1.8706e-05 +3.3564e-06 +471.96 +0.18138 +0.1907 +0.016569 +0.0081013 +0.0034524 +49.054 +0.011698 +0.0094782 +0.022114 +361.11 +238.2 +59.962 +98.418 +0.0084876 +0.013485 +0.030753 +0.011717 +0.0091555 +44.793 +48.29 +76.825 +160.47 +0.0040635 +0.0052465 +0.0052969 +0.0097493 +1.6214e-06 +3.6701e-06 +70.241 +0.002463 +0.0058414 +0.0040832 +0.0018311 +0.012847 +0.0033194 +0.005225 +0.0012695 +0.0016668 +9.7894 +6.7626e-06 +7.0366e-06 +4.4752e-06 +3.4006e-06 +2.7681e-06 +197.42 +227.58 +117 +0.042688 +0.051017 +0.046474 +1.3617e-05 +6.1527e-06 +8.7851e-06 +2.0834e-06 +4.5807e-06 +4.487e-05 +8.4579e-06 +1.1244e-05 +1.5476e-05 +1.5494e-05 +125.88 +85.286 +0.011932 +0.0093848 +0.0084025 +0.022319 +0.017765 +1892.3 +0.050765 +935.6 +273.42 +117.36 +203.77 +0.010011 +0.012679 +0.028341 +0.01737 +0.011368 +67.715 +39.457 +67.791 +245.31 +104.45 +111.68 +0.005765 +0.0090304 +0.0020171 +154.83 +0.024733 +0.0063356 +0.0074041 +0.0024325 +0.00082242 +0.0058143 +0.0022833 +0.0078461 +0.0018696 +0.0040656 +8.6596 +0.0093915 +1.1003e-06 +7.3427e-06 +1357.8 +3100.9 +148.43 +91.361 +307.49 +0.023763 +2.272e-07 +5.741e-07 +6.0402e-06 +1.4137e-05 +2.0482e-05 +1.0709e-05 +8.3907e-06 +8.53e-06 +1.0609e-05 +3.7686e-06 +6.7858e-06 +95.63 +82.028 +120.17 +0.015008 +0.041198 +15.432 +0.040936 +0.056516 +0.14346 +0.029926 +0.21377 +0.073481 +97.298 +290.1 +0.01028 +0.012028 +0.018099 +8.6837e-06 +3.3348e-06 +8.534e-07 +29.045 +58.197 +94.114 +286.98 +215.47 +255.29 +0.017873 +1.603e-05 +0.091003 +0.018392 +0.0098902 +0.0080227 +0.0024142 +2.0188e-06 +0.0023907 +0.0014608 +0.0028496 +0.0029781 +0.0022497 +0.0077264 +0.015932 +0.15917 +667.3 +824.26 +2269.4 +123.87 +148.01 +150.74 +1.2131e-06 +8.558e-07 +2.6392e-06 +8.5925e-06 +1.077e-05 +7.1627e-06 +9.4142e-06 +4.6302e-06 +4.8062e-06 +3.4325e-06 +2.1603e-05 +90.213 +53.176 +63.43 +128.25 +0.014606 +132.72 +292.68 +0.033597 +0.096708 +0.29855 +0.006042 +0.0054068 +211.21 +2.306e-06 +310.59 +0.017646 +0.012729 +1.9727e-06 +2.9127e-05 +6.8753e-06 +2.7058e-06 +0.24876 +31.305 +87.73 +438.9 +77.87 +51.165 +1.5116e-05 +147.86 +0.053976 +137.33 +0.010231 +0.0055297 +0.0038527 +0.0006612 +0.0015844 +0.00077647 +0.0014473 +0.001046 +0.0017294 +2682.8 +0.41224 +0.059454 +0.08024 +0.34401 +44.057 +38.011 +153.52 +180.51 +5.7692e-06 +1.2538e-06 +1.099e-06 +3.8868e-06 +4.4684e-06 +1.3979e-05 +3.0668e-06 +2.1989e-05 +1.3407e-05 +1.1574e-05 +2.496e-05 +59.86 +0.011429 +82.481 +9.9403 +0.047909 +0.04504 +294.71 +91.442 +0.008805 +0.020988 +0.0055653 +0.003125 +0.011394 +133.51 +283.97 +0.015136 +0.017495 +4.9855e-06 +1.3605e-05 +0.02268 +0.0034862 +0.073882 +0.0050615 +572.19 +299.05 +139.56 +25.512 +0.027628 +0.018144 +0.065516 +275.83 +0.010943 +0.0037833 +0.0027835 +0.00067402 +0.0015372 +0.00082221 +0.00076279 +0.13801 +0.053343 +0.01949 +0.56351 +82.379 +0.023542 +18.883 +23.609 +20.748 +7.722e-07 +1.3023e-05 +4.9211e-06 +1.0245e-06 +2.0563e-06 +2.2641e-06 +9.1124e-06 +1.5535e-05 +1.9872e-05 +2.9305e-05 +3.3786e-05 +1.0192e-05 +4.2678e-06 +2.0192e-06 +0.0023556 +0.0014152 +0.0045576 +0.030751 +0.01365 +0.062489 +0.085812 +0.0099928 +0.015183 +0.0071425 +0.0025967 +0.0056879 +141.64 +153.2 +105.62 +0.0079415 +1.7203e-05 +0.021826 +0.007595 +0.0056997 +0.049752 +0.0027933 +0.02704 +200.87 +91.155 +0.01052 +0.022822 +0.012279 +0.063757 +0.030392 +0.037463 +0.024507 +0.050221 +0.068014 +0.16232 +0.00084623 +0.00089577 +0.062967 +6.1892e-06 +0.89098 +0.015949 +0.067737 +46.189 +25.643 +13.568 +18.101 +1.0648e-05 +1.8655e-05 +2.2092e-05 +1.2167e-06 +3.0462e-06 +1.5229e-06 +2.8981e-06 +4.8712e-06 +4.3826e-05 +2.52e-05 +0.00010217 +1.8653e-06 +3.6854e-06 +0.0073349 +0.0016855 +0.0011295 +0.0026129 +0.034736 +96.728 +0.05526 +0.089092 +0.0032549 +0.0043508 +0.0073622 +0.0024926 +0.010928 +0.023814 +125.09 +0.018804 +134.99 +0.039866 +0.017041 +0.0079815 +0.0095673 +2.7222e-05 +1.8093e-05 +9.9412e-06 +218.59 +83.927 +0.010608 +0.010593 +0.011435 +0.05799 +0.014547 +0.035057 +0.032693 +0.032706 +0.040472 +0.24428 +0.002322 +1.3094e-05 +0.12723 +6.1405e-06 +284.59 +201.23 +37.567 +58.786 +10.43 +0.00047996 +0.00076113 +61.845 +2 +8.5704e-06 +2.4358e-06 +5.8225e-06 +2.6277e-06 +1.2056e-05 +1.2881e-05 +9.5422e-06 +2.0476e-05 +1.025e-05 +0.026133 +0.0028282 +0.0079353 +0.0011461 +0.0014806 +0.0046148 +0.038107 +0.13395 +0.26442 +0.2204 +5549.6 +0.0013498 +0.0049601 +0.0049291 +0.010411 +0.017035 +0.033054 +0.017927 +140.48 +74.659 +0.029403 +5.3086e-06 +1.5638e-05 +1.7896e-05 +5.7096e-06 +1.0409e-05 +116.94 +83.694 +41.427 +75.385 +0.0069998 +0.048799 +0.019342 +0.049854 +0.058357 +0.030476 +0.044169 +0.079582 +0.0028704 +0.44531 +92.918 +65.47 +179.55 +0.012607 +0.019118 +0.023811 +0.015122 +0.00042604 +5.0308 +0.00086945 +0.0046896 +6000 +5.8789e-06 +3.1753e-06 +2.9668e-06 +5.2241e-06 +6.0219e-06 +5.5602e-06 +4.2411e-06 +0.011659 +0.014178 +0.0033119 +0.004946 +0.0018537 +32.129 +0.010959 +0.045353 +0.085603 +0.19667 +0.47027 +3144.8 +0.0021285 +0.0036398 +0.0048881 +0.0057389 +0.17389 +0.054017 +0.022733 +0.063034 +0.018345 +0.022662 +3.6326e-06 +1.8053e-05 +2.6416e-05 +6.2086e-06 +0.016583 +0.054548 +109.02 +29.421 +0.023669 +0.011421 +0.079306 +0.047792 +0.044184 +0.026767 +0.024148 +141.62 +0.0022592 +3.5364e-05 +42.594 +68.697 +67.418 +217.64 +0.008294 +0.019402 +0.018935 +0.023311 +0.04894 +0.015665 +0.00086617 +0.013227 +0.027497 +0.01696 +5.0915e-06 +2.0541e-05 +1.5962e-05 +4.0473e-06 +7.5542e-06 +1.8255e-06 +0.0062153 +0.012302 +0.0046883 +0.0042171 +0.56312 +46.895 +0.0066638 +0.039824 +202.24 +0.10723 +0.35572 +5796.2 +0.0039996 +0.0028732 +0.136 +0.11068 +0.22108 +0.011059 +0.0066505 +0.0042229 +0.020082 +0.037387 +0.059505 +0.017214 +0.027986 +26.956 +41.943 +121.97 +66.163 +20.519 +0.011336 +0.0094087 +0.11113 +0.032434 +0.073192 +0.0095594 +0.02667 +0.0062053 +3.4574e-05 +2.113e-05 +63.065 +101.33 +50.024 +0.95452 +0.0062981 +0.027698 +0.034955 +0.039466 +0.063494 +32.538 +1.3416e-05 +0.010717 +0.015283 +0.033819 +0.036416 +155.83 +7.794e-06 +3.3883e-06 +2.838e-05 +1.9881e-05 +0.0069799 +0.0049651 +0.0025233 +0.0025888 +0.011423 +15.858 +0.012904 +0.042346 +0.047419 +0.14187 +0.2605 +4234 +0.68764 +0.063208 +9.2299e-06 +1.4075e-05 +0.0031368 +0.011051 +0.0051841 +0.0023413 +0.0070669 +0.05501 +0.046624 +0.011863 +78.545 +0.0077011 +73.49 +130.12 +96.941 +119.35 +0.0086997 +144.63 +0.073915 +0.014305 +0.033483 +1.0281e-05 +2.2904e-05 +1.5238e-05 +2.2898e-06 +9.7099e-06 +61.766 +169.86 +29.889 +54.972 +0.0074231 +0.048925 +0.053123 +0.039659 +0.1122 +0.052896 +5.1827e-06 +8.3037e-06 +68.974 +95.894 +0.053187 +0.043027 +0.073283 +0.00070731 +6.587e-06 +1.0876e-05 +0.0075451 +0.0058959 +0.0030712 +0.0016583 +15.14 +17.941 +46.243 +0.025182 +0.046808 +0.12763 +0.11228 +2574.7 +1.0319 +0.33007 +1.5433e-05 +2.0388e-05 +6.3893e-05 +1.8158e-05 +0.0052929 +0.0024673 +0.05454 +0.027418 +0.027855 +0.0075689 +34.899 +0.016269 +80.604 +165.34 +1.9238e-05 +1.1292e-05 +0.0060657 +130.35 +294 +0.0021284 +0.0019879 +9.9067e-06 +2.7608e-05 +1.163e-05 +3.0046e-05 +63.404 +60.774 +77.637 +13.579 +61.066 +0.015383 +0.061478 +0.093677 +0.09351 +0.097913 +4.2986e-05 +2.3606e-05 +2.249e-05 +4.0697e-05 +0.036944 +154.25 +59.293 +0.01806 +0.0021749 +0.0027008 +0.001792 +0.0057311 +0.0021804 +0.0023169 +0.0030378 +48.684 +0.01439 +0.031323 +0.037954 +0.071143 +0.17283 +0.12465 +1067.2 +1.4315 +0.43937 +4.5182e-06 +1.0496e-05 +42.535 +66.145 +0.0098791 +0.035279 +0.081381 +0.026183 +0.023361 +9.3252 +6.5815e-06 +1.6378e-05 +2.224e-05 +2.0522e-05 +2.3151e-05 +33.287 +22.505 +5.3733e-06 +0.0034637 +0.0034584 +0.0025741 +6.0038e-06 +4.7984e-05 +1.8324e-05 +1.7818e-05 +1.4935e-05 +132 +43.275 +27.03 +0.75919 +0.24202 +0.046907 +0.099425 +0.025692 +0.038632 +4.726e-05 +2.206e-05 +1.0404e-05 +2.5653e-05 +2.1994e-05 +147.31 +51.501 +0.044913 +0.017195 +0.0014905 +0.0015409 +0.0051897 +0.0018941 +0.00080037 +0.0046097 +65.739 +63.029 +136.79 +66.027 +3.2572e-06 +0.19911 +0.16307 +2336.1 +2 +1.0464 +2852 +142.9 +0.032328 +37.748 +32.748 +64.373 +0.052141 +0.015749 +0.028117 +2205.9 +2.8334e-06 +1.2307e-05 +4.9167e-06 +5.0323e-06 +6.0093e-06 +8.5251e-06 +1.0346e-05 +3.905e-06 +6.0784e-06 +0.006862 +0.0048841 +15.444 +16.694 +51.738 +0.043581 +0.056481 +71.542 +75.965 +16.752 +31.926 +63.979 +0.18926 +0.10619 +128.1 +0.027519 +0.023197 +6.6456e-05 +1.4827e-05 +2.6272e-05 +1.0371e-05 +2.377e-05 +0.016592 +47.038 +0.015446 +0.0016875 +0.0023637 +0.0077109 +0.0027485 +0.00066853 +0.0080203 +48.439 +102.89 +0.0045325 +0.0085354 +1.0149e-05 +0.06343 +0.19686 +2799 +1.0999 +0.28557 +3436.9 +120.23 +0.11282 +0.007043 +1.6392e-05 +173.03 +0.11251 +0.013597 +0.019164 +0.44974 +420.88 +1.3357e-05 +6.4486e-06 +6.5728e-06 +6.9227e-06 +2.709e-06 +7.7618e-06 +3.5601e-06 +2.6241e-06 +6.9374e-06 +15.732 +47.055 +0.0015385 +79.742 +212.31 +0.18968 +0.18766 +36.826 +14.529 +97.888 +49.083 +2.4287e-05 +4.8659e-05 +0.05366 +0.051708 +0.026923 +1.8578e-05 +1.6186e-05 +2.275e-05 +6.5137e-06 +3.6187e-05 +1.3932e-05 +107.63 +0.034027 +151.61 +24.525 +0.0082705 +0.0020117 +0.0019797 +0.015764 +0.027937 +0.014296 +13.242 +1.5828e-05 +0.092211 +0.075557 +0.092231 +4410.5 +1.3445 +0.1706 +3673.2 +1.5939 +7.3185e-06 +2.2957e-05 +0.004904 +134.26 +0.032007 +0.011687 +0.026178 +0.093864 +0.10813 +2.0777e-05 +1.2221e-05 +1.8277e-05 +1.0492e-05 +2.9754e-06 +9.3913e-06 +2.7934e-05 +8.0188e-06 +1.2469e-05 +11.285 +18.083 +0.0080551 +30.432 +0.0047278 +0.10581 +916.11 +36.35 +23.061 +58.527 +32.249 +36.834 +3.0328e-05 +6.8965e-05 +0.050164 +0.013437 +0.0053823 +9.565e-06 +1.8662e-06 +1.1248e-05 +6.3694e-06 +2.9031e-05 +126.41 +0.052567 +119.83 +48.057 +0.0045561 +0.0030058 +0.0020207 +0.018946 +0.025987 +0.015938 +0.033054 +0.012043 +0.11314 +0.053507 +0.099861 +5647.1 +1.1549 +702.86 +1.0327 +1.1622 +2 +0.010018 +41.537 +52.251 +59.27 +39.447 +0.0035636 +0.085909 +0.075513 +1.2208e-05 +6.326e-06 +1.7272e-05 +1.6701e-05 +7.4919e-06 +2.8059e-05 +9.7066e-06 +0.0078622 +0.0028389 +15.322 +10.51 +17.838 +5.7863 +0.010309 +26.43 +1303.4 +8.2997e-06 +14.397 +163.13 +54.651 +66.672 +2.0307e-05 +3.3123e-05 +0.00011954 +0.012588 +0.018731 +0.024527 +7.4553e-06 +8.0342e-06 +1.4937e-05 +6.0376e-06 +165.35 +0.034373 +165.64 +46.458 +24.486 +0.0028188 +0.0019149 +0.011479 +0.016795 +0.0055014 +0.01008 +0.0281 +0.057048 +0.024654 +0.091315 +0.090289 +2.8009e-05 +692.65 +0.8697 +1.8409 +1.9984 +1.6036 +66.756 +22.354 +27.799 +20.948 +13.759 +0.09675 +1.0053e-05 +4.7957e-06 +2.536e-05 +3.1526e-05 +4.8919e-05 +1.4268e-05 +6.1258e-05 +0.0029592 +0.017092 +17.547 +29.663 +0.0015002 +20.392 +0.027348 +0.010928 +21.778 +10.875 +2.0465e-05 +7.3255e-06 +124.95 +106.72 +99.002 +0.010841 +3.1262e-05 +2.4472e-05 +5.0086e-05 +0.028954 +0.030519 +0.039276 +4.6269e-06 +0.13645 +0.13278 +0.12375 +0.032825 +132.93 +59.456 +22.786 +9.0927 +0.0025599 +0.014179 +0.0096878 +0.0075471 +0.0046122 +0.0016209 +0.046237 +0.017134 +0.11031 +18.281 +1.8159e-05 +839.77 +0.57343 +2 +0.8483 +1.4129 +0.35105 +16.645 +0.011445 +41.303 +7.102 +1.4777e-05 +7.0849e-06 +1.263e-05 +1.6507e-05 +1.2828e-05 +1.0689e-05 +8.366e-06 +4.1969e-05 +0.0012148 +0.035006 +30.781 +0.013785 +7.672 +0.011632 +275.23 +0.047411 +26.205 +10.508 +2.4031e-06 +7.7738e-06 +125.96 +136.94 +0.037093 +0.01987 +2.0856e-05 +2.0605e-05 +3.7574e-05 +2.4119e-05 +1.2551e-05 +0.03044 +0.038006 +0.0066674 +0.0071871 +0.0080959 +0.015445 +0.01742 +36.044 +33.879 +9.0452 +0.084928 +0.08831 +0.0068032 +0.0039521 +0.0021946 +0.0016394 +0.0060955 +0.011405 +0.047419 +9.9047 +2.9128 +898.04 +0.32371 +1.1553 +0.81089 +0.67924 +0.61918 +11.737 +0.010154 +0.019304 +3.6409e-06 +2.4783e-05 +3.9837e-05 +5.0049e-06 +1.3898e-05 +7.1489e-06 +1.5832e-05 +1.2409e-05 +2.4948e-06 +2.717e-06 +135.77 +28.493 +0.012514 +0.018378 +0.021271 +137.95 +0.10837 +0.078308 +9.4877 +10.475 +331.43 +254.03 +176.13 +147.96 +106.04 +88.657 +98.97 +0.050104 +0.021875 +0.0063826 +0.023555 +0.0039531 +0.0076067 +0.010275 +2.5146e-06 +8.1144e-06 +3.3627e-06 +1.7223e-06 +54.305 +4.6527 +0.017378 +0.038962 +119 +184.18 +0.0028719 +0.0023036 +0.0046045 +0.0077145 +0.0085617 +12.679 +3.9873 +0.0029488 +0.26901 +3151.1 +1.0224 +0.64689 +0.78489 +0.57782 +0.011614 +0.025567 +4.6071e-06 +2.3661e-05 +2.3892e-05 +2.6159e-05 +3.6131e-05 +1.5283e-06 +1.8383e-05 +4.7899e-06 +3.856e-06 +3.2439e-06 +2.7664e-05 +32.938 +0.017277 +0.01684 +0.011313 +0.0024335 +0.017353 +0.0048975 +0.0048538 +694.71 +307.85 +252.25 +165.31 +93.909 +0.024976 +0.034458 +0.030728 +0.013596 +0.017799 +0.042803 +4.3837e-06 +4.1669e-05 +0.26241 +0.076269 +0.072796 +4.6257e-06 +1.4633e-05 +7.5508e-06 +54.768 +10.409 +0.0096186 +0.013153 +126.13 +440.09 +42.992 +0.00085592 +0.0050311 +0.0047216 +0.0043768 +0.02403 +0.010782 +0.0029467 +0.18138 +1188.6 +0.89947 +0.52688 +0.70047 +0.37798 +0.0078952 +73.912 +1.2059e-05 +7.5028e-06 +1.5795e-05 +1.5238e-05 +2.7144e-05 +9.8843e-06 +6.99e-06 +2.13e-05 +1.5767e-05 +3.81e-05 +6.0497e-05 +239.97 +0.010768 +0.0099013 +0.0071833 +0.0075325 +0.020653 +0.0037644 +0.0038616 +570.21 +182.97 +191.29 +0.091804 +0.0090394 +0.048177 +0.022192 +0.018756 +2.294e-05 +4.6302e-05 +6.562e-06 +3.1653e-06 +0.026783 +0.11868 +0.079553 +0.037082 +7.7734e-06 +3.083e-06 +4.3048e-06 +52.45 +16.445 +15.609 +0.0076192 +0.01883 +0.031968 +36.074 +71.404 +0.019126 +0.0038756 +0.015848 +0.013568 +0.018129 +0.040691 +0.02827 +993.43 +0.48146 +0.35859 +0.77617 +0.38812 +0.084631 +8.6949e-06 +1.0202e-05 +5.2249e-06 +2.8253e-05 +1.0332e-05 +1.8271e-05 +1.0702e-05 +1.7145e-05 +5.5987e-05 +1.5517e-05 +0.00020496 +22.14 +0.013371 +0.012626 +0.015591 +0.0094883 +0.0090031 +35.795 +0.0035375 +368.37 +681.38 +165.15 +0.0098403 +0.0085911 +0.0083981 +2.9934e-05 +1.3344e-05 +1.4333e-05 +7.7316e-06 +1.2509e-05 +6.4666e-06 +1.0513e-05 +0.027443 +0.12653 +0.098317 +5.1347e-06 +1.8314e-06 +9.1159e-06 +1.9621e-06 +9.9907e-06 +0.00010825 +0.0051357 +0.0086534 +0.010099 +0.031272 +0.053208 +0.039166 +68.638 +0.0034181 +0.012581 +0.029869 +0.0437 +0.068964 +0.035482 +1571.1 +1.1255 +0.36284 +0.97709 +0.58563 +0.17785 +1.3399e-05 +2.3454e-06 +8.7332e-06 +3.7313e-06 +1.5404e-05 +4.8491e-06 +5.2891e-06 +6.1447e-06 +2.2213e-05 +0.0043282 +0.0067874 +0.011676 +0.0072128 +16.255 +0.0063863 +0.012255 +48.662 +24.451 +0.002063 +0.003349 +0.47854 +0.18321 +1956.2 +0.016225 +0.0091154 +1.4583e-05 +1.5027e-05 +8.683e-06 +2.3238e-06 +2.0849e-06 +4.6043e-05 +0.02296 +0.037955 +0.081165 +0.16265 +3.9916e-06 +1.2936e-06 +1.3504e-05 +4.31e-06 +6.0974e-05 +4.6007e-05 +6.4702e-06 +0.0082252 +0.014308 +0.063233 +0.050152 +0.048827 +0.027064 +0.00076214 +0.0090725 +0.012528 +0.093631 +0.076332 +0.062463 +0.054946 +780.74 +0.14617 +0.94225 +1.1755 +0.30871 +0.40664 +8.2078e-06 +6.1463e-06 +3.5707e-06 +4.4105e-05 +5.3522e-06 +8.9714e-06 +3.9575e-06 +0.0055468 +0.0028521 +0.01171 +0.020369 +0.020294 +44.176 +0.015756 +114.16 +32.551 +0.0097104 +0.016315 +0.0092388 +0.44574 +0.53353 +0.65324 +0.5788 +3.3996e-05 +4.5049e-05 +4.9725e-05 +2.0038e-05 +4.2904e-05 +7.1308e-06 +0.026739 +0.016413 +0.0488 +0.070177 +8.5081e-06 +4.4189e-06 +2.6306e-06 +1.1488e-05 +2.0757e-05 +60.338 +1.0324e-05 +2.0678e-06 +2.0478e-05 +0.018435 +0.060583 +0.051996 +0.046074 +0.048589 +0.062206 +126.7 +0.015938 +994.02 +0.03529 +0.093527 +0.12799 +0.14734 +646.92 +390.16 +0.49678 +0.32526 +0.42467 +0.12524 +5.2149e-06 +3.079e-05 +0.0067434 +0.0075049 +0.032034 +0.0058434 +0.0099523 +0.0057999 +0.013792 +0.0065159 +0.015336 +0.054138 +62.816 +107.2 +33.28 +0.012927 +0.014269 +0.0093651 +0.031227 +1.0347 +3419.7 +0.96933 +0.25401 +1.9946e-05 +3.8728e-05 +0.0038135 +0.013972 +0.052738 +0.030519 +0.019473 +0.058286 +2.5537e-05 +4.5171e-05 +2.9298e-05 +1.3606e-05 +6.9507e-06 +9.6938e-06 +38.219 +6.7033e-06 +8.114e-06 +7.2745e-06 +70.393 +0.092134 +0.067136 +0.025989 +0.061315 +160.73 +97.778 +0.22108 +1111.3 +0.0064302 +0.33992 +0.19542 +0.1198 +0.12364 +231.36 +0.090798 +0.011877 +0.0060177 +0.0057668 +0.0057181 +0.016677 +0.013206 +0.012817 +0.043011 +0.0083075 +0.066471 +56.776 +28.075 +0.0033572 +0.0017382 +8.1415 +1.5643e-05 +0.0098319 +0.0058568 +0.013978 +0.014537 +0.021459 +60.877 +1.1568 +2762.9 +0.0056101 +0.0033927 +6.4032 +0.021671 +0.0084914 +45.423 +0.059112 +3.4204e-06 +4.2723e-06 +1.2519e-05 +2.6055e-05 +4.1349e-06 +6.2342e-05 +3.1893e-05 +1.7328e-06 +1.8152e-05 +26.312 +1.1709e-05 +1.2679e-05 +6.5251e-06 +128.11 +39.677 +0.065826 +0.04064 +0.060825 +71.179 +44.534 +0.06096 +0.012012 +0.005401 +0.70795 +0.68462 +0.10472 +0.12314 +155.69 +0.0017765 +0.0016125 +0.0071669 +0.0033905 +0.0038618 +0.011137 +0.0040705 +2.4985e-05 +158.41 +92.747 +0.03602 +99.305 +0.0077411 +0.0041965 +3.1075e-05 +3.1499e-05 +6.3556e-05 +0.004676 +0.0090775 +0.0071922 +0.016656 +0.02117 +0.064767 +47.572 +20.232 +0.0047 +0.0033179 +0.0054502 +0.013233 +0.021783 +3.3456e-05 +4.556e-05 +1.6832e-05 +3.9423e-06 +1.732e-06 +3.1499e-06 +1.4294e-05 +3.0992e-05 +8.2471e-06 +6.1064e-06 +8.6414e-06 +48.333 +2.4199e-05 +0.0094825 +0.00075736 +48.142 +14.053 +18.82 +0.024893 +0.025564 +43.529 +50.154 +0.14315 +0.0096352 +56.465 +0.015182 +0.70098 +0.095521 +0.0023798 +0.00058709 +0.0015955 +0.006727 +0.0061509 +0.017323 +0.34671 +0.33581 +0.034026 +1.087e-05 +52.681 +104.19 +0.040932 +54.515 +2.0412e-06 +4.3702e-05 +2.3997e-05 +1.9749e-05 +0.10876 +0.073929 +0.025893 +0.011474 +0.017514 +0.0024965 +0.059007 +57.359 +0.016037 +35.77 +0.005637 +0.0048726 +0.26949 +1.7876e-05 +2.9649e-05 +2.7615e-05 +1.1798e-05 +4.1392e-06 +2.9639e-06 +5.9356e-06 +4.3379e-05 +2.951e-05 +6.078e-06 +7.3678e-06 +9.094e-06 +33.041 +3.2875e-06 +0.0072236 +3.7497 +35.82 +12.906 +0.12124 +0.019709 +0.0091781 +19.982 +0.016516 +0.057138 +0.018941 +0.0087048 +1.2131 +0.89302 +0.054484 +0.001645 +0.00076139 +0.0010072 +0.038599 +0.041453 +0.033122 +0.27223 +0.37304 +0.07262 +6.6391e-06 +88.043 +95.822 +0.028656 +0.019893 +2.1952e-05 +3.0589e-05 +2.2702e-05 +3.5649e-05 +0.11282 +0.12701 +0.079565 +0.062167 +0.024536 +16.657 +0.0045343 +72.861 +0.010226 +0.013557 +28.551 +331.71 +0.32435 +0.24437 +1.2618e-05 +3.9646e-06 +9.2272e-06 +1.9015e-06 +4.9392e-06 +1.3788e-05 +2.9458e-05 +3.8693e-05 +1.1744e-05 +1.4648e-05 +1.0673e-05 +9.09e-06 +1.4405e-05 +5.2876e-06 +5.0944 +0.0029422 +0.0019697 +0.026675 +0.025186 +0.013532 +0.0039384 +0.02359 +117.31 +0.013008 +4.5109 +0.0017366 +0.54064 +0.066488 +270.1 +0.00030586 +0.00062398 +0.0037197 +0.045416 +0.038648 +0.37802 +0.31913 +6.4868e-06 +1.2711e-05 +94.32 +146.95 +0.075437 +0.049865 +3.6711e-06 +1.6258e-05 +1.7232e-05 +1.8831e-05 +668.93 +0.14128 +0.14105 +0.032431 +69.441 +10.258 +0.0013419 +0.00091415 +0.0012813 +58.737 +32.136 +39.977 +524.65 +0.090683 +1.9532e-05 +2.3695e-05 +3.14e-05 +1.709e-05 +1.4633e-05 +2.0825e-05 +1.5526e-05 +2.9746e-05 +3.2529e-05 +7.2272e-06 +8.9327e-06 +0.026009 +6.3145e-06 +0.0093052 +2.8966 +0.0025427 +0.0017852 +0.022139 +0.019489 +0.017249 +0.0030199 +74.805 +0.037956 +0.076334 +0.01862 +0.0026149 +0.30262 +0.069278 +216.96 +94.553 +0.00030772 +0.0021304 +0.039317 +0.024661 +0.42719 +6.0919e-06 +4.6626e-06 +2.9377e-06 +196.3 +100.07 +0.13384 +0.10984 +1.1303e-05 +9.0226e-05 +0.00013894 +0.33662 +723.4 +316.33 +0.10003 +0.027756 +45.96 +10.389 +0.0030943 +0.001462 +0.0013599 +0.0036955 +21.182 +26.619 +14.319 +0.090749 +0.16194 +6.9392e-06 +5.3491e-06 +2.081e-05 +8.2038e-06 +3.1546e-05 +1.6644e-05 +1.8894e-05 +9.7556e-05 +1.3254e-05 +4.3768e-06 +0.073347 +0.054799 +0.016123 +15.086 +0.00093552 +0.0053824 +0.015403 +0.0075496 +0.010225 +0.0055905 +0.043364 +0.093358 +0.085292 +0.0032672 +0.085294 +0.042181 +0.068535 +180.75 +94.454 +32.985 +0.002605 +0.00032997 +0.035736 +5.3596e-06 +5.3042e-06 +5.6365e-06 +7.1051e-06 +5.9369e-06 +87.142 +324.42 +0.11355 +3.802e-05 +0.020372 +0.029787 +644.61 +348.2 +591.87 +0.069874 +12.712 +15.811 +0.0018381 +0.0015619 +0.0012724 +0.0011885 +0.0025529 +0.0041156 +0.011199 +13.646 +0.13869 +0.11876 +8.5396e-06 +2.2767e-05 +7.9375e-06 +4.1602e-05 +4.5795e-05 +1.3486e-05 +2.3069e-05 +1.7412e-05 +7.3808e-06 +3.9912e-06 +0.095134 +0.018092 +0.0042837 +0.004492 +0.0013294 +0.0044696 +0.0074187 +0.0030373 +0.0092036 +0.0028542 +0.048642 +0.044717 +0.17464 +0.36107 +0.11972 +0.024498 +0.048004 +394.79 +131.56 +44.504 +38.375 +0.72079 +0.0004301 +0.00073373 +0.00051145 +1.194e-05 +2.3882e-05 +5.4546e-06 +156.21 +0.10991 +0.37554 +0.23606 +0.15449 +0.033444 +0.29402 +708.05 +514.7 +26.552 +29.52 +0.0069571 +0.0027698 +0.0021688 +0.0016703 +0.00113 +0.0013157 +0.006059 +12.438 +0.005917 +0.25444 +0.084238 +0.10499 +3.1323e-05 +5.5603e-05 +1.0551e-05 +2.9991e-05 +2.4167e-06 +1.6651e-06 +5.2495e-06 +9.4912e-06 +1.8037e-05 +0.019182 +0.015857 +0.012234 +0.0066923 +0.0021741 +0.0068479 +0.011296 +0.087682 +0.058208 +0.098202 +0.05385 +0.52037 +0.29594 +0.39142 +0.050139 +0.029379 +0.087055 +666.7 +0.06194 +0.11478 +0.032787 +0.025882 +0.00047098 +0.54314 +2.4859 +0.00033241 +1.5997e-05 +3.3156e-05 +2.0342e-05 +0.14629 +0.49445 +0.5239 +0.12755 +0.021471 +0.16388 +0.50507 +484.27 +25.238 +28.367 +0.0044072 +0.0015984 +0.0036715 +0.0027435 +0.00065032 +0.0010267 +0.0091466 +0.0059405 +0.096865 +0.22169 +0.083226 +0.10545 +0.065158 +1.9969e-05 +1.8527e-05 +5.4305e-06 +1.0823e-05 +3.7332e-06 +2.7316e-06 +8.2641e-06 +1.3353e-05 +0.029028 +0.041781 +0.0091493 +27.908 +0.0023152 +0.0073085 +0.11715 +174.94 +0.055453 +0.59634 +0.42005 +0.25153 +0.6321 +0.44492 +0.10475 +138.19 +0.19662 +0.068361 +0.055577 +0.10284 +0.028078 +0.024474 +0.051085 +0.97618 +1.2974 +2.3623 +0.00056469 +56.051 +0.06788 +0.13663 +0.33883 +0.24377 +0.12171 +0.11384 +0.19475 +1661.5 +33.358 +23.436 +19.538 +0.0036123 +0.0014116 +0.001335 +0.001148 +0.00046086 +0.0012245 +0.0024563 +0.14345 +0.040744 +0.07622 +0.046999 +0.061619 +0.04886 +1.7245e-05 +1.3277e-05 +6.8116e-06 +5.3689e-05 +8.0141e-06 +2.1701e-05 +6.4639e-06 +4.3209e-05 +0.02055 +0.029256 +0.014174 +43.394 +0.0052802 +0.014763 +0.22862 +337.16 +0.11036 +0.16044 +0.50231 +0.26177 +0.34095 +0.77417 +0.081884 +397.02 +0.31328 +0.073103 +0.039411 +0.061952 +0.055256 +0.045554 +0.063172 +3.9564e-05 +2.6183e-05 +4.8154 +5.7365 +35.133 +60.048 +0.094309 +0.47209 +0.19364 +0.1225 +0.063351 +3.4282 +5.4778 +0.0099629 +8.4436 +14.089 +0.0028572 +0.00089142 +0.0015233 +0.00053705 +0.00031412 +0.00068421 +3.7312e-06 +0.40698 +0.06972 +138.25 +0.034769 +0.063937 +0.030468 +1.0546e-05 +2.7055e-05 +1.1715e-05 +0.0052078 +4.1982e-06 +2.702e-05 +5.9777e-06 +1.3009e-05 +0.040822 +0.055012 +0.029614 +86.82 +0.011523 +0.017951 +263.01 +230.14 +0.22022 +0.20104 +0.50828 +0.3432 +0.2299 +0.2044 +0.057366 +0.033586 +0.10159 +0.044493 +0.044293 +0.051913 +0.020092 +0.023486 +0.11664 +1.0979e-05 +0.013456 +0.011802 +10.04 +3.1369 +0.0016116 +27.932 +63.484 +272.45 +0.1614 +0.054283 +5.6607 +5.6308 +18.573 +7.6786 +0.0033321 +0.0032171 +0.00073741 +0.00049261 +0.00037732 +0.00077995 +1.5224e-05 +4.9007e-06 +2.1298e-05 +223.09 +0.071626 +0.023454 +0.028105 +0.032082 +7.9058e-06 +4.9581e-06 +5.6477e-06 +5.8339e-06 +0.012173 +0.0088976 +0.014279 +8.4129e-06 +0.035896 +0.071444 +142.12 +148.62 +33.582 +0.021481 +444.75 +482.47 +0.15605 +0.099676 +0.54666 +0.74663 +0.086015 +0.003431 +0.0076165 +0.037609 +0.094098 +0.06481 +0.025902 +0.034305 +0.023733 +0.042958 +0.12842 +3.5656e-05 +0.020306 +0.0092914 +0.003874 +0.19528 +17.25 +0.0016034 +0.0015171 +43.47 +43.98 +115.99 +4.0655 +7.6013 +14.923 +2.801 +0.0032106 +0.0021814 +0.0010057 +0.00083833 +0.00034628 +3.1986e-05 +4.4443e-05 +3.1781e-06 +2.4833e-05 +144.96 +0.070132 +0.035428 +0.019243 +0.02097 +0.023715 +3.6185e-06 +1.0056e-05 +7.1706e-06 +0.026671 +0.008415 +0.0090284 +0.032555 +0.073094 +0.06631 +0.056157 +117.54 +27.132 +1.5546e-06 +0.32611 +497.18 +0.1785 +0.1281 +0.49265 +0.7388 +0.018966 +0.0047789 +0.01116 +0.038584 +248.06 +0.073314 +0.077004 +0.13896 +0.072064 +0.094237 +9.4865e-06 +3.4804e-05 +0.036138 +0.0044217 +0.0052052 +0.0055382 +0.0055762 +40.511 +0.0011165 +0.0046845 +46.554 +25.386 +4.2317 +0.0027621 +9.2628 +9.7267 +7.0141 +0.00065055 +0.00055295 +3.2178e-06 +6.7851e-06 +9.2011e-05 +1.0991e-05 +3.5937e-05 +3.6764e-05 +0.025372 +0.020432 +0.026134 +0.013296 +0.012103 +0.016439 +6.3615e-06 +3.0102e-05 +3.9288e-06 +6.0661e-06 +0.028773 +0.013021 +0.031586 +0.10125 +0.040659 +290.14 +139.88 +20.315 +124.68 +750.1 +0.19521 +0.15144 +0.1331 +0.61879 +0.003746 +0.01228 +0.0065286 +0.0064479 +0.057295 +0.052535 +0.058739 +0.097417 +0.38238 +0.045861 +0.0083664 +1.3177e-05 +0.007158 +0.027096 +0.0048323 +0.0097772 +0.0060059 +0.0043288 +0.017048 +0.068802 +0.016621 +0.02344 +30.982 +0.0029945 +0.01152 +16.257 +6.3172 +3.463 +2.0917 +5.4221e-06 +3.6881e-06 +2.0741e-05 +1.2757e-05 +8.2005e-06 +2.0037e-05 +1.9051e-05 +0.026527 +0.034757 +0.047871 +0.014593 +0.010695 +0.012597 +0.018021 +3.7074e-05 +3.512e-05 +1.1881e-05 +0.078251 +0.011894 +0.019029 +0.22463 +0.14463 +393.03 +192.94 +117.83 +142.09 +619.7 +927.86 +0.084806 +0.1078 +0.30443 +0.0039578 +0.008987 +0.010337 +0.011357 +0.078241 +286.09 +0.014316 +0.071119 +0.010285 +0.0089746 +0.0094361 +2.0802e-06 +0.0083937 +0.010924 +21.351 +0.0089005 +0.0068735 +25.756 +0.0093225 +0.03385 +0.021985 +0.011901 +0.015115 +0.0049582 +0.012823 +0.02355 +4.1032 +1.1748 +0.00034719 +3.6448e-06 +1.6638e-06 +1.0974e-05 +2.5776e-06 +1.7872e-05 +5.1307e-06 +122.75 +64.422 +0.017031 +0.01718 +0.017889 +0.0099285 +0.01217 +0.000325 +4.6682e-05 +2.7197e-05 +3.8411e-06 +1.1383e-05 +0.022085 +0.012853 +1037 +0.23697 +40.013 +271.25 +260.47 +378.07 +987.66 +451.4 +0.11658 +0.25891 +0.43279 +0.0046512 +0.013075 +0.017484 +0.012776 +0.07833 +0.028767 +0.023585 +0.057519 +0.006165 +0.010444 +0.0092054 +0.0078274 +19.529 +6.1049 +0.010339 +0.0081509 +0.0050337 +13.506 +75.304 +42.628 +0.096098 +48.419 +48.47 +0.0097999 +0.018549 +0.017666 +6.0044 +1.8886 +0.052524 +0.0068706 +2.2691e-05 +6.6399e-06 +5.7007e-06 +0.0046673 +34.836 +160.39 +132.86 +0.039268 +0.017941 +0.015285 +0.0065772 +9.5101e-06 +2.5768e-05 +3.3214e-06 +1.7778e-05 +1.4181e-06 +6.0031e-06 +1.6431e-05 +0.0020129 +0.3236 +18.508 +102.96 +289.71 +250.24 +213.9 +941.07 +646.34 +0.16845 +670.7 +0.019079 +0.0021417 +0.0097067 +0.014573 +0.029762 +0.012856 +0.01683 +0.022418 +0.0070085 +0.12013 +0.030288 +72.09 +32.42 +18.547 +9.6748 +0.0085159 +0.0039965 +116.46 +0.031955 +124.02 +0.022491 +230.45 +73.73 +199.69 +0.0062988 +0.014835 +37.759 +46.237 +0.023324 +0.044769 +0.0079678 +0.0058148 +1.2035e-05 +0.015303 +0.0070147 +41.684 +101.63 +0.033917 +0.020698 +0.0095374 +0.011932 +6.1426e-06 +8.4487e-06 +0.00011804 +2.9996e-05 +1.9248e-06 +2.6253e-06 +2.7998e-06 +18.859 +0.0024047 +6.5178 +19.314 +62.283 +56.91 +169.01 +364.45 +988.3 +497.38 +0.28241 +0.0086644 +0.01452 +0.0027612 +0.007064 +0.010662 +0.0028807 +0.0043086 +0.0056782 +0.31627 +0.13761 +0.13861 +35.59 +75.168 +46.87 +0.017666 +0.054403 +47.963 +0.014633 +269.68 +59.672 +134.25 +0.035327 +0.062732 +0.034191 +0.0063292 +0.0068802 +0.015375 +45.986 +55.791 +0.015371 +0.052492 +0.041646 +0.025945 +2.7143e-06 +0.039346 +0.0096603 +0.0059025 +44.398 +0.023623 +0.023455 +0.016565 +4.1817e-05 +1.0333e-05 +1.1642e-05 +6.9868e-06 +1.3281e-05 +1.0185e-05 +6.0185e-06 +0.0045732 +18.023 +0.0021233 +10.976 +14.498 +39.186 +56.899 +253.57 +234 +572.48 +0.020862 +0.016775 +0.0090478 +0.006041 +0.089706 +0.026336 +0.0056516 +0.003965 +0.070576 +0.19669 +0.13979 +0.13156 +0.11158 +0.062337 +69.783 +0.014636 +0.038561 +0.019786 +0.01599 +0.0090327 +196.14 +83.745 +132.07 +45.162 +0.032471 +0.018891 +39.593 +0.013871 +0.0076791 +0.017992 +0.0060628 +0.0027495 +0.0040028 +0.010576 +0.0026723 +0.073887 +0.041474 +0.0056036 +0.011441 +37.035 +0.019409 +0.0091101 +0.01843 +2.5979e-05 +1.9588e-06 +9.9334e-06 +2.1981e-05 +9.9103e-06 +2.4215e-06 +8.8715e-06 +0.0066723 +0.01032 +0.0017681 +12.705 +20.939 +57.243 +86.402 +297.02 +313.06 +0.0048275 +0.0012072 +0.02883 +0.0050763 +0.081042 +0.003141 +0.0080397 +0.0028469 +0.0092216 +0.046696 +0.20192 +0.099798 +0.10888 +0.081279 +125.15 +54.232 +0.0056066 +0.015904 +0.022237 +52.883 +0.01055 +334.54 +103.45 +99.209 +32.083 +0.029776 +56.025 +103.14 +0.034313 +0.0058288 +0.024661 +0.010477 +0.0040482 +0.0025593 +0.0060988 +0.0028976 +0.031712 +0.090053 +0.011085 +0.016511 +88.656 +0.016001 +0.010918 +0.021256 +2.2673e-05 +4.7076e-06 +5.6549e-06 +2.7241e-05 +1.4521e-05 +3.9006e-06 +0.0034946 +0.011914 +0.0068839 +0.0020158 +7.9575 +32.761 +25.254 +54.286 +0.010723 +0.0026654 +0.0041926 +0.0012439 +0.0020542 +6.2664e-05 +0.0091266 +0.0060013 +0.0048837 +0.0026944 +0.008527 +0.0844 +0.26783 +0.15741 +371.31 +0.033401 +138.35 +70.642 +34.033 +0.0091406 +0.01914 +0.011561 +0.012597 +358.13 +222.11 +85.912 +27.331 +0.054214 +69.679 +161.87 +33.624 +0.012087 +0.021224 +0.0085426 +0.0091637 +0.0032967 +0.0099588 +0.0012455 +0.0010973 +0.04074 +0.017517 +0.028611 +93.679 +0.035507 +0.015002 +0.023814 +3.4484e-06 +1.3058e-06 +1.92e-06 +1.0105e-05 +0.006843 +0.0053583 +0.0072121 +0.006819 +0.0055213 +0.0030108 +10.868 +51.48 +47.223 +0.30758 +0.096419 +0.0027825 +0.0068663 +0.0012995 +0.0010282 +0.0012274 +0.017228 +0.0036891 +0.0087619 +0.0026678 +0.063714 +0.15106 +0.31773 +0.16443 +421.86 +0.051734 +152.39 +120.18 +60.206 +0.018053 +22.018 +0.019307 +0.017373 +375.26 +238.84 +172.97 +0.051523 +77.951 +103.32 +144.54 +47.974 +0.0074569 +0.01246 +0.0074994 +0.010675 +0.0022687 +0.017646 +0.0012388 +0.050216 +0.034964 +0.29765 +0.033175 +0.033369 +0.032873 +0.018237 +0.019119 +0.074318 +0.075527 +3.503e-06 +1.0898e-05 +0.0029441 +0.0035312 +0.0035826 +0.0111 +0.0070684 +0.0072816 +16.693 +17.589 +30.502 +0.24716 +0.086018 +0.07669 +0.088326 +0.00256 +0.00051439 +2.6213 +0.0015627 +0.0033325 +0.02119 +0.0060396 +0.010169 +0.13325 +0.306 +0.46097 +587.13 +0.021212 +0.053062 +137.92 +56.683 +0.010774 +0.016826 +42.272 +48.647 +188.31 +217.52 +0.13035 +0.04184 +108.33 +0.055323 +143.39 +77.212 +6.8583e-06 +0.0062281 +0.007497 +0.0038838 +0.0024013 +0.0056757 +0.0013842 +0.087742 +0.063351 +0.15816 +4.7724e-06 +0.026864 +0.045873 +0.016988 +0.0080418 +0.067729 +0.069539 +0.025596 +0.0037205 +0.0016765 +0.0049366 +0.0063452 +0.0057471 +0.012372 +0.017014 +19.952 +19.778 +0.54301 +0.29613 +0.17005 +0.11726 +0.09289 +0.15757 +2.1461e-05 +2.9168 +0.0024895 +0.042978 +0.023485 +0.0061835 +0.024954 +0.074019 +0.30684 +0.58287 +456 +0.1229 +147.36 +188.21 +0.0075631 +42.37 +0.028598 +39.962 +53.527 +95.719 +92.598 +0.12943 +0.046118 +134.23 +158.81 +0.065458 +1.4096e-05 +1.5739e-05 +0.0042862 +0.0043728 +0.0062933 +0.0014411 +0.0045803 +0.00084943 +0.043544 +0.081918 +7.2792e-06 +3.8644e-06 +1.2103e-06 +1.9201e-05 +0.011895 +0.010525 +0.094504 +0.035743 +0.024133 +0.087452 +0.0010599 +0.0044553 +0.0095873 +0.0095984 +0.0092944 +0.013129 +14.146 +0.35204 +0.32127 +0.42485 +0.25826 +0.20925 +0.16786 +0.0053135 +6.9471e-06 +2.2946 +0.0053938 +0.02067 +0.011002 +0.0074563 +0.042497 +0.18819 +0.59187 +0.45868 +0.16873 +0.1662 +139.72 +186.79 +3.7337e-06 +49.433 +0.029303 +31.187 +0.032739 +138.95 +141.53 +0.039169 +0.021171 +96.191 +0.034415 +279.51 +9.4937e-06 +9.06e-06 +0.0035584 +0.0060108 +0.0041609 +0.001312 +0.0015302 +0.077902 +0.036335 +0.030645 +8.9787e-06 +3.0569e-06 +3.3739e-06 +6.4366e-05 +0.011474 +0.0092952 +0.038766 +0.022884 +0.011224 +0.080374 +0.033245 +0.12729 +0.013458 +0.0071012 +0.0045467 +0.011903 +17.652 +80.177 +0.23096 +0.26308 +0.17565 +0.2424 +0.24437 +0.0060331 +1.1907e-05 +1.4167e-05 +0.0063106 +56.236 +0.010466 +0.018577 +0.01868 +0.0026522 +0.97063 +0.35778 +0.19674 +0.092407 +112.55 +0.058236 +427.52 +339.68 +0.040933 +0.010011 +70.096 +84.501 +240.21 +0.038151 +0.050434 +127.05 +219.32 +123.15 +104.16 +7.4024e-06 +1.9557e-06 +0.0042297 +0.0038302 +0.00098744 +0.0018558 +0.022957 +0.024825 +0.040776 +2.6271e-05 +6.502e-06 +1.26e-05 +1.5635e-05 +9.4413e-06 +0.025374 +0.053071 +0.034799 +0.01644 +0.16783 +0.064546 +0.16174 +0.040334 +0.0056769 +0.0054905 +0.020475 +22.488 +40.85 +0.063616 +0.15761 +0.31728 +0.59617 +0.13268 +0.086874 +0.0053337 +0.0052886 +6.6584e-06 +0.015557 +34.959 +0.021028 +0.011291 +0.0071816 +0.00056472 +0.34181 +0.15903 +0.054164 +0.060274 +0.0393 +0.22655 +446.59 +3.7064e-06 +0.016737 +0.02761 +79.237 +0.027967 +0.10589 +0.052769 +156.58 +192.82 +214.12 +38.687 +0.10934 +0.0037365 +0.0049628 +0.002863 +0.00091692 +0.0016203 +0.017719 +0.029533 +0.0095657 +6.1756e-06 +9.1459e-06 +2.4849e-05 +3.3318e-05 +8.6877e-06 +0.050108 +0.13498 +0.082309 +0.031656 +0.18614 +0.10653 +0.071859 +0.027141 +0.034654 +0.0092738 +0.014207 +18.405 +93.83 +0.050315 +0.035605 +0.30652 +1.4441 +0.39156 +0.17438 +0.03258 +0.0088939 +0.011841 +1.5326e-05 +0.014031 +65.22 +0.017492 +0.00481 +0.00080063 +0.16076 +508.08 +0.044018 +0.041611 +0.016717 +931.79 +0.021186 +63.426 +80.483 +0.026478 +84.784 +0.031827 +0.10251 +0.11968 +0.084618 +112.77 +106.32 +69.983 +0.0065734 +0.0026272 +0.0025831 +0.0039663 +0.0012807 +0.053347 +0.037967 +0.03682 +0.016427 +7.8384e-06 +1.1554e-05 +8.2844e-06 +3.1618e-05 +0.0553 +0.019853 +0.072376 +0.048441 +0.0442 +0.31428 +0.24716 +0.17733 +0.019373 +0.024107 +0.035873 +0.021115 +17.048 +76.688 +78.657 +0.074148 +0.045967 +1.2887 +0.62087 +0.3007 +0.038634 +0.21031 +0.0077422 +0.016082 +0.012879 +0.021744 +0.013182 +0.010189 +0.0011503 +0.17385 +0.08223 +0.10402 +0.017904 +0.010333 +0.046496 +0.0066585 +62.369 +83.384 +93.575 +134.94 +0.024889 +0.081264 +0.16276 +0.070911 +136.09 +0.037845 +0.049183 +0.0064011 +0.0029601 +0.0035975 +0.0029799 +0.066447 +0.029762 +0.051399 +0.072217 +0.014255 +2.0575e-05 +5.8017e-06 +1.5077e-05 +0.020783 +0.056063 +0.045459 +0.056335 +0.10585 +0.03519 +0.34963 +0.25015 +0.34376 +0.027015 +0.045724 +0.040905 +0.024973 +34.265 +0.021391 +127.98 +0.029757 +0.026289 +0.093864 +0.77301 +0.20403 +0.083885 +0.15422 +50.424 +92.187 +43.002 +0.02941 +0.021267 +0.011591 +0.00097039 +0.0012762 +0.1601 +113.38 +179.29 +0.013819 +51.486 +19.595 +69.385 +41.447 +0.030266 +0.13888 +0.04575 +0.061403 +0.068675 +0.063882 +132.12 +0.012063 +0.0077634 +0.0076019 +0.0051889 +0.0076537 +2.2543e-05 +0.028439 +0.035274 +0.036784 +0.054759 +0.038131 +1.3935e-05 +2.5902e-05 +0.020351 +0.0090192 +0.027314 +0.053877 +0.042409 +0.19835 +0.047324 +0.26273 +0.11954 +0.53536 +0.12061 +0.05329 +0.067363 +0.01657 +48.758 +42.437 +122.45 +0.031796 +0.027179 +0.075358 +0.10093 +7.2567e-06 +0.10322 +56.103 +93.453 +0.026802 +0.012612 +0.011086 +0.018938 +0.015068 +0.0033989 +0.0015462 +0.023163 +94.902 +114.04 +34.629 +39.016 +21.512 +0.056286 +0.047746 +0.052793 +0.15584 +0.19603 +0.02248 +0.052593 +0.041659 +0.019189 +0.0082503 +0.014025 +0.010687 +0.0057258 +2.1598e-06 +0.043139 +0.045588 +0.090479 +0.05503 +0.039387 +0.042339 +0.014538 +0.0051405 +0.010813 +0.0051997 +0.036221 +0.036475 +0.065658 +0.20866 +0.052873 +0.12896 +0.092389 +0.27321 +0.033125 +0.088478 +0.034121 +0.015531 +44.914 +65.539 +35.753 +0.017458 +0.045253 +0.077307 +0.067924 +0.026637 +0.014294 +29.305 +114.11 +0.01494 +0.01344 +0.012181 +0.050084 +0.050178 +0.0067229 +0.0031939 +0.046275 +102.51 +0.087949 +62.769 +16.659 +25.803 +0.0082324 +0.092846 +0.029168 +0.052237 +0.1145 +0.030636 +65.463 +0.070579 +0.013413 +0.015192 +0.017966 +0.0097813 +0.0024116 +1.0359e-06 +1.0067e-06 +0.1127 +0.12056 +0.065676 +0.06203 +0.026797 +0.021694 +0.0088884 +0.016588 +0.0098846 +0.037721 +0.018335 +0.070005 +0.37354 +0.05724 +0.11326 +0.073033 +0.04464 +0.0287 +0.063255 +0.039318 +0.043406 +47.519 +57.4 +25.324 +0.0083693 +0.093947 +0.04437 +0.094102 +59.94 +0.01158 +67.079 +139.76 +74.02 +0.013606 +0.026198 +0.070052 +0.15628 +0.014632 +0.012778 +0.059248 +79.122 +0.019022 +48.404 +13.892 +0.0056946 +0.0082659 +0.2114 +0.011517 +0.046311 +1.4831e-05 +0.024582 +0.019173 +0.018458 +0.03718 +0.032649 +0.025887 +0.0063576 +1.9762e-06 +0.043193 +0.015985 +0.047511 +0.10409 +0.1296 +0.084154 +0.040299 +0.048007 +0.0051768 +0.016451 +0.0035035 +0.021517 +1.8259e-05 +5.9901e-06 +2.2297e-06 +5.7724e-06 +0.12417 +0.051146 +0.071168 +0.060918 +0.06669 +0.046513 +0.02903 +59.259 +41.956 +0.0073955 +0.0047989 +0.038039 +0.03114 +0.043629 +0.050797 +55.954 +29.863 +0.024537 +0.02668 +0.027922 +0.033202 +0.066503 +0.1611 +0.17737 +0.43781 +0.0074561 +0.12729 +0.0070506 +56.291 +33.85 +0.010731 +0.0081716 +0.15655 +0.0187 +1.2202e-05 +6.2345e-06 +0.01361 +0.029382 +0.0095402 +0.03158 +0.090247 +0.011894 +0.01504 +0.0096962 +0.027384 +0.11425 +0.080158 +0.21568 +0.092856 +0.083416 +0.025139 +0.19959 +4.14e-06 +1.812e-05 +8.3538e-06 +4.9005e-06 +2.0769e-06 +3.7798e-06 +8.8131e-06 +1.1301e-05 +0.0484 +0.028766 +0.088471 +0.075157 +0.066148 +0.065977 +266.12 +0.0049447 +0.0041445 +0.0043865 +0.009055 +0.018994 +0.018965 +0.034072 +0.048529 +0.017236 +0.037618 +0.076183 +0.50975 +0.10035 +0.06528 +0.081282 +0.092085 +0.11896 +0.48195 +0.6391 +1.603e-05 +0.057867 +29.058 +0.020933 +0.014124 +0.0079787 +0.025455 +0.017346 +1.296e-05 +1.3914e-05 +6.7583e-06 +0.03059 +0.014543 +0.016887 +0.13697 +0.26472 +0.030719 +0.010553 +0.0045156 +0.11136 +0.070742 +0.18851 +0.044449 +0.050844 +0.033809 +0.076205 +5.2344e-06 +2.1712e-05 +1.9312e-05 +6.7138e-06 +7.9995e-06 +2.0295e-05 +4.5774e-05 +2.2191e-05 +7.8884e-06 +0.026933 +0.10231 +0.11645 +0.12576 +198.04 +0.096761 +0.0047455 +0.0073362 +0.0025471 +0.0136 +0.028871 +0.017745 +0.028767 +0.067817 +0.028027 +0.067645 +0.25625 +0.57779 +0.085892 +0.10965 +0.12236 +0.15139 +0.16923 +0.56947 +0.22471 +0.30849 +0.22468 +0.015506 +0.0093068 +0.024855 +0.0057639 +0.035378 +52.23 +0.02441 +2.585e-05 +9.6308e-06 +6.7533e-06 +0.029004 +0.024393 +0.15923 +0.3479 +0.1057 +0.072694 +0.14803 +0.071651 +0.035735 +0.098022 +0.043001 +0.038269 +0.035413 +0.04393 +1.1339e-05 +3.0329e-05 +9.4161e-06 +1.5305e-05 +9.2782e-06 +9.5161e-05 +2.9201e-05 +1.2462e-05 +0.00011793 +0.011613 +0.094925 +0.19695 +0.12493 +0.21141 +0.11405 +0.0058849 +0.011801 +0.0021139 +0.014271 +0.019698 +0.013761 +0.025994 +0.14824 +0.02386 +0.046289 +0.29063 +0.69538 +0.064948 +0.017838 +0.086376 +0.15433 +0.15599 +0.20295 +0.17315 +0.17874 +0.2129 +0.079517 +3.2003e-05 +0.002899 +0.0050484 +183.77 +0.014155 +36.712 +0.013445 +4.1731e-06 +0.0070702 +0.0051923 +0.021628 +0.099301 +0.2016 +0.20135 +0.043878 +0.12608 +0.074674 +0.044452 +0.035123 +0.032507 +0.054378 +1.6315e-05 +2.8269e-05 +0.00019011 +2.0684e-05 +1.1267e-05 +1.3311e-05 +2.9577e-05 +2.1237e-05 +1.4126e-05 +2.0694e-05 +0.11432 +0.028782 +0.10235 +0.15408 +0.15725 +0.19752 +0.13003 +0.0046896 +0.022361 +0.011088 +0.011906 +43.432 +0.023061 +0.036228 +0.11287 +0.037761 +0.07436 +0.085051 +0.04999 +0.0079682 +0.0081761 +0.047311 +0.13129 +0.15213 +0.16979 +0.10578 +0.14812 +0.013808 +0.023467 +0.048204 +12.556 +0.0070885 +255.71 +0.020812 +30.769 +129.53 +240.23 +0.014919 +0.16673 +0.036658 +0.056743 +0.13087 +0.24416 +0.042712 +0.020449 +0.03739 +0.03933 +0.067759 +16.234 +31.697 +1.9516e-05 +8.6463e-05 +4.0842e-05 +6.3739e-05 +1.1629e-05 +2.0011e-05 +1.2786e-05 +2.272e-05 +6.5623e-05 +1.45e-05 +0.029395 +0.043586 +0.10925 +0.20192 +0.21792 +0.21142 +0.09585 +0.0052593 +0.025785 +0.032696 +0.013197 +38.959 +0.023658 +0.036902 +0.063338 +0.0383 +185.26 +0.056276 +0.026444 +0.0046024 +0.007895 +0.042666 +0.034195 +0.075215 +0.21877 +0.18428 +0.16191 +1.7471e-05 +2.8696e-06 +6.9955e-06 +1.0603e-05 +19.823 +0.0010379 +1.0129 +54.023 +51.568 +159.02 +385.78 +0.091853 +0.060983 +0.067038 +0.12987 +0.10632 +0.030236 +0.023514 +0.0518 +0.059244 +0.084555 +1.1983e-05 +21.562 +11.008 +3.8875e-05 +1.9725e-05 +4.3545e-05 +4.583e-06 +7.7717e-06 +1.2011e-05 +1.0777e-05 +2.11e-05 +7.08e-06 +0.040234 +0.040473 +0.1402 +0.12991 +0.14551 +0.12313 +0.084234 +0.010915 +0.0852 +0.039277 +0.019578 +28.164 +0.042081 +0.05953 +0.09571 +0.013447 +157.01 +188.86 +0.03696 +0.0047113 +0.016511 +0.045018 +0.091871 +0.15598 +0.29835 +0.086686 +2.149e-05 +2.3093e-05 +2.5442e-06 +5.904e-06 +6.0502e-06 +4.2906e-05 +1.6602 +0.00020516 +0.0025895 +0.0018375 +445.8 +318.65 +261.02 +0.087863 +0.052394 +0.15837 +0.13037 +0.060672 +0.031582 +0.026327 +0.072026 +0.10014 +3.2825e-05 +1.9152e-05 +4.952e-06 +8.482 +0.0025594 +1.7304e-05 +1.0358e-05 +6.2688e-06 +3.2039e-06 +6.6776e-06 +1.1724e-05 +5.3414e-06 +0.033872 +0.035667 +0.067042 +0.06519 +0.12068 +0.25636 +0.22074 +37.137 +0.11334 +0.022794 +0.0099542 +0.025143 +0.042014 +0.067536 +0.019071 +0.014236 +91.786 +158.92 +0.038157 +0.003402 +0.028194 +0.040838 +0.10532 +0.15331 +0.008586 +0.0054615 +4.5374e-06 +1.8717e-06 +5.2816e-06 +1.5296e-05 +1.0399e-05 +2.6042e-05 +0.62185 +0.0010824 +0.0026506 +0.0033959 +0.0026444 +479.04 +214.65 +194.15 +0.043792 +0.15361 +0.10374 +0.01519 +43.198 +2.3796e-05 +2.6085e-05 +0.04409 +0.098714 +0.11102 +4.756e-06 +12.877 +0.0031724 +6.3343e-06 +1.1335e-05 +1.1661e-05 +3.3646e-05 +8.1637e-06 +4.4376e-06 +3.3464e-06 +0.039957 +0.063447 +0.037825 +0.025118 +0.2234 +0.31765 +0.50282 +0.011939 +57.411 +0.043228 +0.12144 +0.025953 +120.71 +0.039925 +0.01359 +0.012039 +0.028826 +0.15294 +0.071589 +0.0064168 +0.023529 +0.029625 +0.0067732 +0.0089798 +0.0080856 +0.0047942 +0.0084504 +1.6953e-06 +0.021784 +0.0025735 +0.011631 +0.0042733 +1.3064 +0.00082096 +0.95961 +0.0029043 +0.0087264 +658.77 +521.25 +81.406 +272.16 +0.009034 +0.01546 +363 +149.97 +109.57 +8.8524e-06 +3.5878e-06 +0.073884 +0.033929 +535.98 +0.0073325 +0.0041285 +6.2174e-06 +3.1851e-05 +3.1385e-05 +6.9932e-06 +2.9129e-06 +1.0351e-06 +0.10441 +0.013281 +0.015132 +0.019984 +0.021741 +0.18885 +0.13239 +1.1074 +26.303 +48.748 +0.061644 +0.16636 +0.037904 +131.81 +113.7 +0.021868 +0.016171 +0.038325 +0.15633 +191.71 +1.0046e-05 +0.0085418 +0.011494 +0.0211 +0.0097754 +0.004824 +0.00551 +118.73 +91.192 +0.0087969 +0.0018556 +0.0033902 +2.8698 +0.81065 +0.00049639 +3.049 +0.0010762 +0.019361 +0.024011 +359.22 +117.08 +322.33 +0.0088767 +1.2781e-05 +289.48 +139.67 +75.159 +0.018862 +6.2791e-06 +1.782e-05 +5.8732e-06 +1121.7 +0.010834 +0.0050934 +12.535 +3.4159e-05 +1.3706e-05 +1.5684e-05 +6.1521e-06 +268.77 +0.035627 +524.5 +0.013895 +0.010755 +0.040215 +0.10972 +0.095696 +0.23236 +32.481 +86.364 +221.58 +349.93 +0.048663 +309.34 +0.054968 +0.18848 +0.013124 +0.12016 +0.053986 +0.009043 +0.027183 +0.0040584 +0.010968 +0.019063 +0.004099 +0.0049597 +13.624 +0.033359 +0.015469 +0.013868 +0.0044656 +0.0036135 +5.8595 +1.4189 +0.00077976 +2.6897 +0.00057267 +0.005634 +0.015858 +204.42 +150.55 +1007.1 +1287.6 +0.010453 +1.353e-05 +5.1941e-06 +62.39 +112.68 +50.05 +137.15 +1.3671e-05 +5.8822e-06 +0.014974 +0.011095 +31.771 +34.431 +0.002511 +5.079e-06 +600.32 +195.61 +168.21 +0.21342 +207.73 +266.12 +0.021761 +0.059185 +0.11404 +0.25696 +173.14 +149.53 +95.446 +252.3 +0.18482 +0.003632 +0.05748 +0.091755 +0.14768 +0.078621 +0.026555 +0.011676 +0.025844 +0.0059159 +0.010483 +0.014492 +0.0069731 +7.3451 +38.808 +0.015951 +0.021409 +0.0014247 +0.0032715 +0.0038476 +6.2218 +2.694 +2.1703 +4.8302 +0.0016781 +0.048844 +161.59 +119.5 +248.43 +32.001 +12.561 +0.012678 +8.6474e-06 +1.0149e-05 +6.9468e-06 +356.92 +56.797 +191.92 +356.25 +33.916 +0.013244 +0.029297 +43.968 +0.0064735 +0.0038816 +0.0018292 +0.0021443 +200.86 +180.12 +37.087 +47.19 +171.32 +0.13179 +0.052364 +0.15254 +1.1599e-05 +226.88 +84.713 +209.84 +187.74 +47.906 +0.0053169 +0.10125 +178.03 +0.070098 +0.043349 +0.048672 +0.0042075 +0.015178 +0.0065416 +0.0092607 +0.010208 +0.0080555 +19.12 +39.266 +0.011236 +0.0040615 +0.0016801 +0.0018013 +0.0033207 +5.393 +2.2366 +2.1127 +3.5235e-06 +0.050252 +132.07 +0.01789 +0.014041 +125.63 +53.617 +0.015336 +0.014464 +3.4636e-06 +1.696e-06 +6.6269e-06 +0.003702 +0.00074215 +0.0003465 +0.0049714 +115.5 +2.156e-05 +9.7349e-05 +5.3516e-05 +0.0096312 +0.0075404 +0.005096 +0.0051966 +0.0024959 +139.59 +39.273 +21.322 +26.974 +0.020803 +16.401 +0.0025457 +0.0025383 +459.98 +193.42 +84.179 +0.014863 +0.020522 +0.00016084 +1.7917e-05 +0.047091 +0.07988 +9.0099 +0.011639 +0.002194 +0.016312 +0.018864 +0.0078267 +0.008216 +0.0087656 +39.06 +23.546 +19.356 +0.0063098 +0.0023338 +0.0041577 +0.0022427 +2.6698e-05 +7.227e-06 +0.27725 +419.66 +0.064392 +0.022564 +0.021787 +111.49 +102.2 +0.0012813 +0.0054096 +0.010334 +0.0029891 +0.0054058 +0.0057133 +0.011968 +0.0018702 +0.027322 +0.080463 +106.58 +0.025594 +0.050237 +96.077 +93.061 +0.01534 +0.011434 +0.0024718 +0.0015925 +0.011202 +65.381 +0.00073534 +11.733 +13.282 +6.6478 +0.0038782 +15.712 +0.0030385 +127.84 +127.34 +215.56 +308.83 +1.9847e-05 +2.0153e-05 +64.732 +0.03765 +13.315 +0.0073167 +0.0018185 +0.029767 +0.021272 +0.019979 +0.016616 +0.0089559 +29.07 +45.932 +19.608 +0.0035015 +0.0032335 +0.0069954 +0.0089352 +43.06 +794.49 +0.21245 +616.52 +233.67 +84.952 +66.395 +90.005 +0.0038698 +0.0015083 +0.0046053 +0.0010561 +0.0071144 +0.0091034 +0.008209 +1.2253e-05 +8.9744e-05 +7.6039e-06 +0.047782 +150.42 +0.040027 +0.044193 +0.019322 +101.92 +0.025701 +0.007282 +0.0028552 +0.0043439 +0.0052568 +0.0019558 +13.889 +7.4573 +0.012114 +5.241 +0.0037452 +7.2465e-06 +0.0048038 +0.058168 +339.08 +187.93 +108.02 +6.2185e-06 +59.321 +109.58 +54.059 +20.69 +20.313 +0.0041945 +0.027772 +0.040231 +0.015434 +0.014306 +101.48 +47.433 +18.83 +6.1647 +0.0041364 +0.0033542 +0.010677 +0.0082653 +60.257 +644.58 +0.1275 +389.42 +79.581 +97.037 +113.83 +3.2796e-05 +0.0047903 +0.004126 +0.0058991 +0.0031092 +0.017339 +1.605e-05 +1.2609e-05 +1.7936e-05 +6.4501e-05 +1.7449e-05 +7.4845e-06 +0.011357 +0.026054 +0.046495 +0.049473 +0.0031947 +0.023432 +0.0068536 +0.0063576 +14.332 +0.0025674 +0.0018393 +42.746 +2.4056e-06 +9.7862e-06 +7.3398e-06 +2.1122e-05 +4.1314e-05 +0.045136 +0.17495 +0.058969 +132.83 +216.55 +0.30233 +66.298 +211.07 +69.57 +31.831 +14.279 +0.0072048 +0.010779 +0.035736 +0.01957 +0.0185 +0.0037987 +12.863 +10.951 +0.013402 +0.013919 +0.0024233 +0.010973 +0.012686 +0.019837 +227.97 +0.053042 +93.271 +54.295 +1.226e-05 +0.0036767 +0.0077535 +0.0064672 +0.0048156 +0.0052085 +0.0031238 +1.0014e-05 +1.5015e-05 +1.0824e-05 +1.616e-05 +1.384e-05 +1.2659e-05 +9.8371e-06 +0.0069073 +0.010385 +0.027622 +0.038643 +0.0063309 +0.0024329 +0.0056721 +0.004697 +0.0026884 +0.0023512 +0.099877 +0.0034931 +0.008725 +6.7415e-06 +8.6134e-05 +7.6759e-06 +1.8656e-05 +0.004834 +0.0027538 +0.073654 +0.038183 +0.024649 +0.35456 +0.00012773 +276.96 +74.346 +88.19 +44.05 +0.012983 +21.31 +0.014347 +0.01571 +0.0070291 +0.0057068 +5.4335 +0.025604 +0.00955 +0.015079 +0.0019047 +0.010618 +0.014236 +0.06278 +0.085445 +0.048276 +4.1095e-06 +0.048213 +0.047989 +0.0034668 +0.0032237 +0.0011149 +0.002167 +0.0036577 +5.5264e-06 +3.0211e-06 +1.8916e-05 +4.1197e-06 +2.3012e-05 +2.5767e-05 +1.8535e-05 +0.0068385 +0.0034255 +0.011424 +0.055809 +0.037553 +0.0067427 +0.012455 +0.0066604 +0.013156 +0.0026306 +0.19267 +0.078501 +4.4827e-05 +4.744e-06 +0.0059846 +7.7496e-05 +0.00025935 +5.4714e-05 +0.0029221 +0.0017378 +1.7811 +0.020938 +0.025979 +0.086879 +0.17391 +304.37 +89.825 +61.692 +45.916 +25.783 +0.012624 +0.018837 +0.064838 +0.01727 +0.013804 +0.0066191 +0.018149 +0.0095369 +0.019956 +0.0022052 +0.0047261 +0.0074439 +315.74 +0.10138 +2.1778e-06 +3.919e-06 +0.033748 +0.10553 +0.005016 +2.1448e-06 +6.3402e-06 +0.001759 +0.0012243 +3.9517e-06 +3.8394e-06 +2.5718e-06 +1.0192e-05 +3.6288e-05 +3.2193e-05 +5.4223e-05 +0.0030582 +0.0016385 +0.0092145 +0.030481 +0.038342 +0.013895 +0.017972 +0.0016896 +0.0092312 +0.08609 +188.43 +0.06573 +0.029021 +7.433e-06 +7.3695e-06 +4.8337e-05 +8.7667e-05 +7.1858e-05 +0.0015272 +0.0010699 +2.4601 +3.7576 +0.016834 +0.11664 +0.084442 +0.05868 +0.023244 +0.060806 +0.011558 +28.472 +0.016109 +0.023107 +0.05207 +0.1039 +1.3616e-05 +1.8525e-05 +0.017162 +0.19275 +0.010485 +0.0039486 +0.003053 +0.011467 +0.059484 +0.017876 +7.1796e-06 +1.1671e-05 +0.075509 +0.17454 +0.018686 +2.4138e-06 +0.0019824 +0.0027499 +0.0018195 +0.019723 +3.0233e-05 +8.3009e-06 +5.889e-05 +7.9994e-05 +2.1453e-05 +2.8394e-05 +9.0087e-06 +8.9672 +7.2883 +0.014538 +0.017998 +0.014761 +0.021005 +0.0092321 +12.516 +0.061925 +0.029513 +0.05566 +0.037909 +179.09 +1.2375e-05 +4.0087e-05 +8.8514e-05 +3.2101e-05 +0.0013412 +0.00078664 +0.89624 +3.55 +0.001158 +0.0018667 +0.068114 +0.031161 +0.031688 +0.034253 +0.017922 +0.015769 +0.02662 +0.025209 +0.052556 +0.03488 +7.0855e-06 +1.1907e-05 +0.011789 +0.10873 +0.11017 +0.0049618 +0.0031649 +0.0045615 +0.022173 +0.013891 +0.022683 +0.10364 +0.087582 +0.21196 +0.021148 +1.8352e-06 +2.8232e-06 +0.0013519 +0.0036264 +0.016934 +6.6552e-06 +1.3617e-05 +6.378e-05 +0.45425 +0.072664 +9.015 +15.492 +7.6479 +9.1867 +0.015778 +0.0067765 +41.712 +0.017789 +0.0037449 +0.0044514 +1.4375e-05 +0.048775 +0.055801 +0.026523 +132.93 +0.13845 +8.0981e-05 +3.8665e-05 +3.3736e-05 +0.00047574 +0.0026617 +1.4158 +4.3822 +0.0014744 +0.014759 +0.0090592 +0.045643 +0.040808 +0.0081184 +0.0067094 +0.0031248 +0.0027379 +0.028148 +0.032456 +0.01769 +1.3061e-05 +0.0071589 +0.018124 +0.025415 +0.05735 +0.046688 +0.0020069 +0.0055479 +0.0070557 +0.013958 +0.012747 +0.14906 +0.078872 +0.1028 +3.8751e-06 +1.5453e-06 +0.0037693 +0.0020275 +0.0032217 +0.016726 +0.01259 +0.48675 +0.88775 +0.4744 +0.081733 +10.725 +17.797 +287.48 +0.019581 +0.025871 +0.0063075 +0.015637 +0.015081 +0.043178 +0.11872 +2.8357e-06 +0.037599 +0.083873 +0.02225 +118.42 +0.18708 +3.0641e-05 +1.4258e-05 +4.2786e-05 +0.0020021 +0.001169 +1.6405 +5.9521 +0.065216 +0.049208 +0.017488 +0.032801 +0.00511 +0.0097463 +0.0065539 +0.005523 +0.00077215 +0.0014614 +0.0037193 +0.010232 +0.25332 +0.058509 +0.018549 +0.02161 +0.065195 +0.052027 +0.030072 +0.0058958 +0.0081609 +0.0097312 +0.0075948 +0.14333 +0.090735 +0.12417 +5.995e-06 +7.0423e-06 +4.4508e-05 +0.0020826 +0.0059671 +209.31 +0.027465 +0.034665 +0.016915 +72.54 +87.041 +21.405 +4.7021e-05 +237.98 +67.236 +0.027363 +0.014682 +0.014806 +0.017988 +0.023227 +0.061369 +0.00094024 +9.6808e-06 +0.076082 +0.034581 +0.043079 +0.2224 +0.04594 +1.9736e-05 +1.455e-05 +0.0062836 +0.0018177 +0.020445 +0.012154 +0.063285 +0.086234 +0.0070088 +0.013822 +0.01298 +0.0047968 +0.0029455 +0.0066806 +0.0013889 +0.0014369 +0.0043484 +0.0036818 +0.085444 +0.1062 +0.025567 +0.020124 +0.055002 +0.52862 +0.029645 +0.015538 +0.0099316 +0.0040106 +0.016945 +0.074098 +0.13061 +0.11038 +2.5605e-05 +3.5843e-05 +631.81 +145.49 +0.22206 +250.34 +0.033034 +0.050935 +0.24141 +0.28197 +0.063536 +7.977e-06 +3.2448e-05 +156.01 +0.02221 +72.436 +0.022628 +0.012564 +0.034008 +0.02996 +0.043555 +0.00097728 +1.244e-05 +5.853e-06 +0.020618 +0.082709 +0.28664 +0.12577 +4.5667e-05 +3.6313e-05 +0.008373 +0.016717 +0.01901 +0.0097632 +0.029633 +0.033535 +0.0085533 +0.031068 +0.021924 +46.611 +0.0031289 +0.0061146 +0.0027941 +0.0013055 +0.0046185 +0.018323 +0.12135 +0.078446 +0.031882 +0.019595 +0.011056 +0.38652 +0.38912 +0.0085209 +67.213 +0.0034712 +0.011514 +0.051804 +0.087601 +0.17164 +128.5 +0.031565 +253.93 +111.75 +0.14814 +356.81 +0.026156 +0.058089 +0.3189 +0.25094 +1.0297e-05 +4.6378e-06 +7.4906e-06 +3.1121e-05 +0.014545 +0.033443 +0.053864 +0.039319 +0.0074503 +0.011416 +40.659 +0.00058721 +0.0011169 +1.3823e-05 +0.012464 +0.041885 +0.14295 +0.071015 +0.033569 +5.2072e-05 +0.0088318 +17.856 +0.015228 +0.012836 +0.0459 +0.024828 +0.011747 +0.045069 +1.7389e-05 +0.028808 +0.0027099 +0.011261 +0.0040598 +0.0028644 +0.0049515 +0.039432 +0.35664 +0.10991 +0.033589 +0.10983 +1.1366e-06 +0.32844 +0.26026 +0.4333 +0.012779 +0.00518 +0.026484 +0.049972 +112.02 +167.14 +130.93 +0.049329 +0.066056 +143.96 +0.027632 +0.0203 +0.021016 +0.039162 +2.0188e-05 +7.0393e-06 +4.9973e-06 +8.111e-06 +7.3274e-06 +9.5156e-06 +0.068182 +0.09426 +0.046585 +0.021713 +31.17 +19.505 +28.95 +0.00138 +0.00091091 +0.0037956 +0.0079985 +0.023487 +0.099919 +0.061019 +0.045425 +9.1811e-06 +25.726 +18.338 +0.012142 +0.0096061 +0.044639 +0.023738 +0.010194 +0.10255 +0.048933 +0.024265 +97.751 +0.015606 +0.0040599 +0.0067447 +0.014868 +0.10497 +0.29575 +0.15106 +0.063023 +0.10946 +0.01134 +0.17301 +0.19566 +0.2528 +0.10887 +0.012932 +0.063436 +110.8 +123.05 +142.8 +140.93 +0.0014374 +0.0017996 +0.012614 +0.028974 +0.060585 +0.021027 +0.0391 +4.2449e-06 +1.6027e-05 +1.6946e-06 +1.5409e-06 +6.8875e-06 +0.0043138 +0.029034 +0.081835 +0.064198 +0.048293 +40.88 +0.0077202 +0.00027069 +0.00040845 +0.00058779 +0.0015019 +0.0044188 +0.041464 +0.10839 +0.092165 +0.025123 +1.3003e-05 +27.107 +12.776 +26.091 +0.006445 +0.087614 +0.023404 +0.0056997 +0.060764 +0.049028 +0.0044936 +0.035453 +0.0080268 +0.0027515 +0.0089532 +0.015506 +0.090625 +0.090435 +0.13304 +0.05358 +0.15638 +0.37405 +0.12485 +0.20455 +0.15902 +0.25102 +0.0052265 +0.011112 +0.045963 +0.068351 +0.06856 +0.0015426 +0.001224 +0.0019932 +0.015057 +0.018968 +0.028629 +0.018983 +8.544e-06 +1.8577e-05 +2.3424e-06 +8.264e-06 +5.2771e-06 +0.0055624 +0.013485 +0.050488 +0.14894 +0.08274 +0.051705 +36.665 +0.00088171 +0.00019658 +0.00020627 +0.00076331 +0.0016331 +0.0023068 +0.096095 +0.2077 +0.077408 +0.013274 +3.6926e-05 +24.663 +33.114 +0.0054136 +55.316 +0.019602 +0.020528 +0.012546 +0.045206 +0.031396 +0.0058049 +0.0014138 +0.0053612 +0.0025246 +0.0081582 +0.026645 +0.12843 +0.11076 +0.13397 +0.10633 +0.1211 +0.0024905 +0.11642 +0.14913 +0.19463 +8.5308e-06 +1.9249e-06 +0.0048907 +0.075951 +0.14577 +0.0064646 +0.0014602 +0.0018561 +0.0035899 +0.0060252 +0.061188 +0.050613 +0.075337 +9.7946e-06 +2.5892e-06 +3.5392e-06 +4.5721e-06 +1.5179e-05 +0.017256 +105.08 +0.077641 +0.076526 +0.072035 +0.04536 +0.0016471 +0.0013518 +0.0034595 +2.6014e-06 +0.0010297 +0.000736 +0.0019813 +0.0039628 +0.2455 +0.19685 +0.017231 +5.2791e-05 +25.778 +0.0079914 +0.01069 +0.018164 +0.034836 +0.027177 +0.018058 +0.033908 +0.024003 +0.0081512 +0.0015007 +0.0058916 +0.0045367 +0.0070907 +0.012654 +0.13578 +0.073445 +0.08445 +0.1266 +0.11311 +0.0022526 +1.7569e-05 +0.053977 +0.057778 +80.143 +0.031093 +0.037576 +0.018161 +0.0875 +0.0074623 +0.028496 +0.029364 +645.05 +0.080333 +0.053064 +0.082542 +0.047009 +1.7569e-06 +5.5829e-06 +4.5731e-06 +6.3918e-06 +0.022091 +0.034571 +0.033574 +0.0768 +0.11872 +1.844e-05 +0.0010574 +0.0024056 +0.0011499 +0.0020784 +0.0018517 +4.9389e-06 +0.00072861 +0.00093063 +0.0031541 +0.0046434 +0.496 +0.011113 +2.8127e-05 +0.013279 +0.0088241 +0.017862 +59.163 +0.064015 +0.054134 +0.052228 +0.029469 +0.040511 +0.027326 +0.0038131 +0.042076 +0.0045479 +0.0091787 +8.5474e-05 +0.12727 +0.067976 +0.058239 +0.056789 +0.095526 +0.0032407 +0.088939 +0.13246 +0.035564 +0.029544 +0.022151 +0.055773 +0.004252 +0.007262 +30.686 +0.015001 +0.013333 +0.014363 +0.02123 +0.037014 +0.03098 +167.55 +2.3853e-06 +1.2282e-05 +2.4652e-05 +0.017219 +0.020816 +0.020422 +0.038375 +0.032765 +0.21806 +3.2733e-05 +0.00105 +0.0008815 +0.0020456 +0.0025376 +0.0013497 +45.111 +13.582 +0.0011425 +0.0018958 +0.0046069 +0.0019463 +3.0165e-05 +1.6494e-05 +0.012946 +0.007132 +0.13519 +64.298 +0.12418 +0.045546 +0.14058 +0.01864 +0.030111 +0.042231 +0.0077404 +0.016128 +0.023582 +7.0436e-05 +5.0665e-05 +3088.3 +0.05786 +0.02057 +0.037831 +0.024709 +0.17227 +0.10645 +0.086058 +17.81 +37.762 +0.025188 +0.014226 +0.0050057 +1307.5 +0.012392 +0.023385 +0.031728 +0.023024 +0.032335 +0.023727 +205.54 +0.040123 +139.88 +1.1989e-05 +0.039421 +0.021889 +0.014443 +0.022562 +0.023691 +3.0465e-06 +1.1116e-05 +9.5551e-06 +5.5263e-05 +0.0009072 +0.0018694 +0.0017051 +4.1645 +21.325 +9.471 +38.489 +0.0020847 +0.0042064 +0.001791 +0.00075684 +4.0808e-05 +0.013004 +0.014714 +0.059083 +388.48 +0.096755 +255.38 +142.68 +0.01413 +0.041169 +0.080286 +0.016296 +0.013436 +0.023006 +0.011762 +3.6558e-05 +0.63248 +0.016988 +0.029616 +0.047338 +0.033653 +0.18066 +0.20307 +0.017386 +18.791 +0.010026 +132.21 +0.011414 +4.0009e-05 +3.0926e-05 +35.262 +33.124 +0.015275 +0.011905 +0.019318 +0.021246 +0.036912 +1.836e-05 +152.65 +218.46 +281.49 +0.029201 +0.023121 +0.029395 +0.030489 +3.3314e-06 +1.0135e-05 +1.5282e-05 +6.723e-05 +0.00073363 +71.243 +20.087 +3.7887 +18.516 +12.847 +76.1 +22.186 +0.0024763 +0.001883 +0.00082548 +0.0030659 +0.0075263 +291.08 +162.5 +239.84 +0.10332 +0.058186 +150.77 +0.094034 +0.042019 +0.080028 +0.020965 +0.010109 +0.0041289 +0.014282 +0.0062857 +0.0059003 +0.017632 +0.011549 +0.030026 +0.030353 +0.37946 +0.0087911 +0.0060359 +0.006553 +33.665 +52.093 +0.010676 +10.314 +37.926 +41.202 +27.447 +0.010156 +0.0062362 +52.117 +0.014594 +0.023228 +2.8622 +1.921e-05 +1.6813e-05 +199.48 +183.16 +39.163 +0.019213 +0.031385 +1.5819e-05 +1.108e-05 +5.2321e-06 +0.025269 +27.912 +37.046 +10.361 +5.7562 +4.0662 +12.203 +40.135 +1.2091e-06 +0.0040135 +0.0028928 +0.0020715 +0.0035891 +598.08 +171.34 +174.55 +139.82 +0.087704 +141.27 +0.0065902 +0.14829 +0.22852 +0.063528 +0.030504 +0.013016 +0.0038112 +0.009783 +0.012799 +0.0046226 +0.0096815 +0.0074322 +0.0052556 +0.014949 +0.0025225 +0.0072068 +0.007247 +43.175 +47.352 +1.6202e-05 +11.112 +11.771 +22.597 +69.732 +0.16305 +0.2434 +0.012168 +0.045696 +68.245 +0.013049 +0.0029916 +5.8132e-05 +6.7805e-06 +0.0057089 +0.02393 +0.1148 +0.013689 +33.703 +0.0079663 +1.3417e-05 +1.9175e-05 +1.2631e-05 +78.259 +58.498 +19.021 +2.7162 +4.6395 +12.174 +2.3232e-06 +2.1142e-06 +2.93e-06 +0.0021144 +0.0022945 +0.008737 +575.26 +274.58 +183.68 +200.6 +220.76 +0.014187 +0.073614 +0.056049 +0.312 +0.035412 +0.055635 +0.0073302 +0.0059177 +0.012623 +0.010126 +0.0032884 +0.0073783 +0.0039784 +0.0042599 +0.0046013 +0.005569 +0.006369 +0.012789 +108.33 +13.276 +14.585 +22.998 +0.0047136 +10.915 +8.6091e-06 +1.3785e-05 +0.15292 +0.0083681 +0.091835 +0.032961 +0.023879 +0.0034485 +0.038483 +4.0877e-05 +1.1751e-05 +0.018483 +0.085347 +0.093713 +0.062527 +0.003009 +0.0098193 +0.0066893 +1.6512e-05 +213.74 +75.072 +71.933 +4.9597 +2.2769e-06 +29.126 +8.2615e-06 +3.0556e-06 +3.9495e-06 +7.6921e-06 +3.297e-06 +1.3081e-05 +564.02 +237.22 +171.36 +39.185 +29.134 +0.0083986 +0.018847 +972.23 +0.22854 +0.042458 +0.053396 +0.08224 +0.079061 +0.019068 +0.053097 +0.10253 +0.051729 +0.005751 +0.004647 +0.003237 +0.0068906 +10.727 +0.0046614 +0.0037095 +0.0022332 +12.502 +38.686 +9.9182 +17.926 +6.1617e-06 +1.6163e-05 +8.5615e-06 +0.0061675 +0.22461 +0.052912 +0.019644 +0.0070135 +0.050634 +541.16 +0.032168 +0.084286 +0.056803 +0.072248 +0.034002 +1.1562e-05 +4.2642e-05 +7.8126e-05 +0.0052659 +0.006041 +34.602 +41.557 +5.562 +1.3211e-06 +1.47e-06 +6.7439e-06 +5.5727e-06 +9.4388e-06 +1.7427e-05 +2.9811e-06 +9.0882e-06 +728.4 +249.2 +0.061791 +23.437 +32.988 +0.0048021 +0.020506 +0.015711 +34.949 +0.014726 +0.062243 +0.067723 +0.044727 +0.036681 +0.059954 +0.099903 +0.13508 +0.043052 +0.0054272 +0.0048573 +34.771 +25.404 +0.0086391 +0.00097096 +0.000648 +9.0249 +0.0060887 +5.5544e-06 +1.1493e-05 +2.9547e-05 +1.0904e-05 +4.6772e-06 +49.366 +254.54 +231.18 +0.015577 +0.021923 +0.062098 +0.066822 +0.13211 +0.065943 +0.082387 +0.029502 +0.022758 +3.3073e-05 +2.1478e-05 +2.1812e-05 +8.8187e-05 +0.0087352 +0.0094317 +0.0079113 +16.752 +7.7971 +1.1826e-05 +4.63e-06 +2.0368e-05 +1.5933e-05 +2.0266e-05 +7.8118e-06 +1.7134e-05 +380.77 +0.069496 +0.089892 +39.275 +0.0098952 +0.001979 +0.027499 +0.0067228 +0.0061322 +0.040721 +0.024226 +0.073827 +0.035711 +0.025049 +0.063353 +0.10358 +0.11937 +0.0066531 +35.858 +2.6822 +19.644 +39.584 +0.01094 +0.0020582 +0.0017322 +5.7799 +2.5694e-05 +3.0751e-05 +2.1913e-05 +1.033e-05 +3.2373e-06 +1.699e-05 +111.17 +0.11022 +0.089991 +0.031019 +0.011645 +0.047168 +0.2196 +2.517e-05 +0.053989 +0.036752 +0.027907 +0.02483 +0.012078 +0.00014623 +5.6745e-05 +1.2788e-05 +1.6452e-05 +2.811e-05 +0.0069861 +0.01209 +7.2599 +5.7783e-06 +5.3848e-06 +3.4549e-05 +3.0368e-05 +1.1394e-05 +1.3671e-05 +4.9957e-06 +0.45776 +406.69 +0.11691 +0.18653 +0.13001 +6.6137 +0.02764 +0.0038201 +0.011211 +0.01418 +0.012127 +0.081269 +0.033975 +0.034072 +0.17498 +0.12322 +0.079076 +35.704 +10.681 +5.9377 +16.738 +27.463 +0.0083599 +0.0039487 +0.0014554 +8.6833 +9.5537e-06 +3.4267e-05 +1.2202e-05 +7.2427e-06 +9.2746e-06 +1.0909e-05 +5.5135e-06 +338.9 +315.91 +0.065998 +0.01181 +0.028091 +0.19904 +1.0124e-05 +9.5934e-06 +0.018643 +0.017301 +0.023154 +0.01623 +0.016033 +50.999 +1.9699e-05 +8.4227e-06 +1.2183e-05 +0.0050555 +0.011597 +0.023976 +0.020239 +0.056523 +5.0472e-06 +1.3295e-05 +1.5889e-05 +9.15e-07 +6.4198e-06 +1.6449e-05 +0.22564 +0.093602 +0.079529 +0.1198 +0.034632 +0.072252 +0.0022909 +0.0074286 +0.041716 +0.01135 +0.045331 +0.020637 +0.072765 +0.13597 +0.2645 +0.026694 +33.358 +14.014 +10.617 +9.9351 +27.761 +0.0093318 +0.0040804 +0.0022519 +0.0073753 +0.020211 +1.8169e-05 +1.0232e-05 +8.8391e-06 +2.4022e-05 +0.039276 +0.15374 +990.98 +463.9 +142.01 +0.03276 +0.056955 +0.050692 +0.018199 +0.05042 +2.0371e-05 +0.010807 +0.020552 +0.016371 +0.020954 +0.023548 +0.03087 +0.06155 +2.5609e-06 +1.0415e-05 +0.001516 +0.0018586 +0.020675 +0.061482 +0.11183 +6.1337e-06 +7.9986e-06 +6.0736e-06 +7.9614e-06 +2.289e-05 +0.014487 +0.0046092 +20.664 +0.13664 +0.038028 +0.020068 +0.031558 +0.011199 +0.020948 +0.016324 +0.027706 +0.029544 +0.021927 +0.20846 +0.30527 +0.013212 +52.959 +27.854 +19.975 +16.228 +0.0046612 +0.0078561 +0.0034317 +0.014696 +0.0086729 +0.020564 +0.0055683 +7.9042e-06 +1.4217e-05 +1.425e-05 +0.07398 +0.13168 +776.39 +1358 +693.99 +0.038075 +0.013558 +0.037973 +0.036782 +0.056019 +0.097025 +0.0071486 +0.0079599 +0.0097699 +0.0082987 +0.010501 +0.088296 +0.048995 +0.059938 +0.069806 +0.045394 +0.0022206 +0.007562 +0.033574 +0.058702 +0.028235 +4.0447e-06 +8.8218e-06 +1.6329e-05 +23.341 +23.217 +0.011972 +0.0012219 +1.7718 +0.015603 +0.027835 +0.037606 +0.043736 +0.019064 +0.012254 +0.056525 +0.068291 +0.035968 +0.27076 +7.2793e-06 +28.772 +34.228 +22.52 +10.457 +0.0060153 +0.0026578 +0.0047649 +0.02826 +0.01303 +0.0084802 +0.01403 +0.006709 +9.1767 +5.9206e-06 +0.074248 +262.75 +191.71 +421.84 +1224.4 +278.96 +0.13369 +0.032374 +0.025424 +0.024176 +0.066121 +0.13134 +0.0043589 +0.0042922 +0.0066418 +0.0049555 +0.013498 +0.0060055 +0.11973 +0.07616 +0.098642 +0.039933 +0.048213 +0.01622 +0.040789 +0.10523 +0.030401 +6.3463e-06 +4.7209e-06 +2.4671e-06 +0.0063195 +20.009 +15.549 +0.0053939 +0.011337 +42.286 +0.011471 +0.022929 +0.10294 +0.16123 +0.53874 +0.50039 +72.956 +0.93807 +0.092337 +15.05 +56.047 +83.307 +34.018 +20.353 +17.732 +0.0015583 +0.0025626 +0.0020198 +0.02229 +0.0023408 +0.0083357 +0.004815 +14.674 +1.6764e-05 +196.92 +152.99 +75.154 +158.26 +246.89 +0.076349 +0.13254 +0.044161 +0.038469 +0.025212 +6.2489e-05 +5.0631e-06 +0.0041746 +0.0043172 +0.0074317 +0.0060967 +0.0055314 +0.53342 +0.38 +0.29968 +0.11195 +0.026093 +0.02315 +0.030787 +0.02133 +0.044396 +0.039229 +2.2197e-05 +8.749e-06 +3.0671e-06 +0.072722 +37.315 +25.201 +0.0081797 +87.789 +74.109 +0.011511 +0.029174 +0.088173 +0.26828 +0.4328 +0.55403 +0.53234 +25.938 +84.416 +24.48 +53.763 +45.526 +19.73 +33.766 +9.7831 +0.0010206 +0.0019956 +0.011773 +0.010903 +0.0057502 +0.0053756 +0.0037745 +24.247 +115.74 +197.74 +202.33 +140.41 +168.84 +340.69 +0.046074 +0.10748 +0.04996 +0.028392 +0.03955 +370.96 +0.16382 +0.0053248 +0.011271 +0.0069911 +0.01289 +0.0060747 +0.43096 +0.28656 +0.23283 +0.062418 +0.018571 +0.035375 +0.023971 +0.025309 +0.028623 +1.082e-05 +1.3238e-05 +6.4563e-06 +3.965e-06 +0.033488 +151.79 +0.008681 +0.01783 +199.19 +0.10755 +245.49 +0.057713 +0.17749 +189.75 +0.01649 +0.54709 +0.89435 +0.37429 +0.1345 +34.572 +43.203 +33.642 +32.296 +26.864 +12.331 +2.1306 +0.0020637 +0.0043597 +0.0089798 +0.0075311 +0.0074725 +0.011686 +0.025926 +136.7 +0.049877 +150.85 +211.44 +157.11 +4.1684e-05 +0.13015 +0.094147 +0.10151 +0.025164 +0.1433 +474.61 +0.13983 +0.0040127 +0.019885 +0.0076973 +0.012006 +0.73882 +0.38355 +0.025131 +0.024494 +0.061507 +0.030195 +0.053592 +0.037412 +2.0206e-05 +5.0042e-06 +5.6924e-06 +2.6609e-05 +8.7839e-06 +2.2109e-06 +0.036845 +131.47 +0.011109 +0.013205 +276.41 +0.08089 +0.10196 +159.35 +644.79 +0.043563 +0.014487 +0.023064 +1.0643 +0.58983 +0.20261 +12.034 +56.541 +41.672 +50.646 +61.145 +12.635 +1.5884 +0.0022695 +0.0035925 +0.012113 +0.061233 +0.01881 +0.0057532 +0.0293 +171.11 +162.28 +122.42 +173.89 +1.5926e-05 +8.1058e-05 +4.284e-06 +0.080355 +0.055501 +0.043707 +269.07 +413.57 +0.015961 +0.0068162 +0.025439 +0.0088432 +1.425 +0.28364 +0.0031255 +0.028521 +0.032357 +0.021499 +0.0090656 +8.04e-06 +1.4419e-05 +1.4268e-05 +1.3e-05 +5.3223e-06 +1.5144e-05 +2.9863e-05 +3.5042e-06 +0.049288 +0.021098 +0.0094369 +0.030537 +198.71 +0.072163 +354.41 +146.93 +131.55 +0.12183 +0.009778 +0.0075163 +0.49845 +0.40913 +0.0060795 +9.5034 +37.428 +59.557 +52.983 +62.002 +11.195 +1.089 +2.7393 +0.0018701 +0.013401 +0.02315 +0.0097791 +0.0070328 +0.027916 +165.56 +245.06 +0.034967 +169.18 +8.5929e-05 +4.2366e-05 +1.8717e-05 +0.10021 +0.031558 +200.06 +0.10314 +0.012497 +0.0086975 +0.0097122 +0.021714 +0.0089199 +0.087274 +0.012694 +0.0053245 +0.054653 +0.057212 +0.02296 +5.9899e-06 +1.7263e-06 +1.6696e-05 +1.6621e-05 +3.571e-05 +1.8074e-05 +2.2769e-06 +4.7176e-06 +2.3812e-05 +0.043436 +0.015143 +11.441 +0.021813 +264.8 +0.078261 +402.86 +0.16959 +301.94 +0.035773 +0.063414 +14.945 +0.53972 +0.54698 +0.0046838 +9.9356 +19.845 +55.532 +31.735 +67.72 +10.58 +4.4341 +6.2205 +0.0027536 +0.0024715 +0.012173 +0.011363 +0.0055759 +0.032364 +0.020689 +0.076323 +4.2954e-05 +1.2588e-05 +3.8625e-05 +2.9449e-05 +4.3779e-06 +2.7847e-05 +0.054334 +138.06 +0.11478 +0.023892 +0.0061311 +0.018105 +0.020856 +0.050839 +0.033902 +0.017528 +0.0125 +49.387 +4.3501e-06 +2.866e-06 +6.2457e-06 +4.0213e-06 +1.1443e-05 +2.1913e-05 +1.1669e-05 +4.374e-06 +1.6654e-06 +1.7226e-05 +6.2289e-06 +0.02472 +0.021831 +20.208 +0.020026 +0.061229 +0.024255 +194.21 +0.24241 +343.06 +285.82 +41.211 +16.056 +0.77545 +23.794 +28.374 +9.7707 +23.104 +31.679 +29.515 +56.297 +6.946 +5.0019 +0.0023345 +0.0033799 +0.005045 +0.0064834 +0.015759 +0.0042568 +0.026119 +55.778 +0.061425 +3.3103e-05 +2.8102e-05 +1.3799e-05 +1.5294e-05 +7.3055e-06 +8.494e-05 +38.167 +0.046239 +0.058203 +0.017923 +0.012921 +0.098313 +0.076344 +0.013708 +0.034552 +0.00889 +0.016544 +0.0027223 +1.583e-05 +9.6839e-06 +7.1621e-06 +4.3791e-06 +5.0473e-06 +6.1135e-06 +2.2685e-06 +8.3898e-06 +3.8899e-06 +7.427e-05 +6.071e-05 +0.026754 +59.492 +20.926 +0.0084708 +0.039057 +0.070821 +0.29341 +0.17214 +335.05 +369.22 +52.314 +0.93867 +32.544 +41.897 +22.614 +7.9546 +36.198 +32.599 +26.928 +103.48 +22.306 +20.51 +0.0034298 +0.0028465 +0.0048125 +0.0070851 +0.0096992 +0.0061976 +0.037184 +0.15751 +0.10942 +0.03421 +7.7362e-06 +7.6971e-06 +5.553e-06 +1.2666e-05 +88.703 +75.897 +0.038244 +0.048303 +137.69 +0.0085039 +0.049806 +0.081014 +0.010307 +0.02082 +0.016199 +0.012581 +1.919e-05 +1.2191e-05 +3.7021e-06 +2.9284e-05 +5.2602e-06 +3.2042e-05 +4.6684e-06 +1.262e-05 +4.4467e-05 +6.4395e-05 +6.337e-06 +2.208e-05 +0.022339 +0.027376 +20.286 +0.0070992 +0.050643 +0.085167 +0.23962 +563.29 +0.0062199 +0.0028433 +0.073263 +229.54 +66.044 +70.643 +18.305 +8.0687 +26.171 +21.126 +61.157 +107.32 +17.586 +21.272 +0.033452 +0.0060353 +0.0098742 +0.0099331 +0.014246 +0.0037093 +0.018775 +0.12275 +0.15631 +0.030069 +6.4358e-06 +1.8656e-05 +0.0081927 +0.0046866 +75.04 +0.029185 +238.38 +220.75 +0.06675 +0.020608 +0.041379 +0.013957 +0.010127 +0.0034505 +0.010677 +1.0019e-05 +1.1337e-05 +8.1098e-06 +1.3903e-05 +1.7152e-05 +5.7469e-06 +2.7896e-05 +8.9418e-06 +7.3589e-05 +3.2431e-05 +6.4671e-05 +3.4203e-05 +6.5661e-06 +0.016032 +0.008067 +36.993 +0.017951 +0.035025 +0.5073 +0.35334 +0.011599 +47.384 +2431.8 +563.79 +194.58 +25.323 +91.122 +30.213 +11.655 +25.942 +48.455 +78.928 +58.638 +26.934 +0.0039924 +0.022573 +0.0042995 +0.0078674 +0.0053808 +0.0094261 +0.0088364 +0.037394 +0.099686 +0.13418 +0.046436 +3.9879e-06 +0.0065058 +0.0091046 +0.0081726 +0.038179 +0.14955 +0.068313 +0.11238 +0.051743 +48.951 +0.0024442 +0.0040156 +0.0038388 +0.002515 +0.0094066 +2.4743e-06 +6.8258e-06 +1.9848e-05 +9.3696e-05 +0.00014281 +1.1725e-05 +1.5148e-05 +1.642e-05 +2.3464e-05 +2.2145e-05 +1.9224e-05 +0.0002505 +7.0668e-05 +0.020105 +0.0090126 +38.064 +0.119 +0.077707 +0.48997 +0.067877 +0.11302 +2.0386 +3178.7 +0.37702 +233.76 +53.02 +47.374 +50.522 +20.021 +23.034 +29.015 +54.767 +0.0018197 +0.0054624 +0.0044979 +0.0083368 +0.0060242 +0.0073634 +0.0065679 +0.007081 +0.053725 +0.045141 +0.071955 +0.10997 +0.034066 +0.032284 +0.0040488 +0.061653 +0.38164 +348.87 +367.37 +0.041671 +0.10443 +2719 +0.0070761 +0.0017786 +0.0076351 +0.0027222 +0.0010547 +0.00169 +2.1039e-06 +4.5338e-06 +9.5938e-06 +1.3353e-05 +3.1105e-05 +5.5649e-06 +8.3421e-06 +4.4455e-06 +1.6204e-06 +1.4049e-05 +3.4422e-05 +9.559e-06 +3.4635e-05 +0.014015 +0.19443 +0.083685 +0.035934 +0.038013 +0.090241 +0.08961 +0.091653 +0.026012 +1656.2 +596.99 +146.32 +115.47 +33.427 +56.911 +15.006 +41.318 +49.682 +0.0067841 +0.0017139 +0.0069179 +0.0042488 +0.0052427 +0.0084819 +0.010317 +0.0044679 +0.0083167 +0.034259 +0.11818 +0.037838 +0.11053 +0.041063 +2438.8 +870.57 +0.062733 +478.45 +217.58 +0.10026 +9.602e-06 +6.3524e-06 +1933 +0.010358 +0.0026237 +0.0086196 +0.0051087 +0.0025939 +0.0031543 +1.4291e-06 +4.506e-07 +3.0525e-06 +1.5593e-05 +1.8315e-05 +4.3413e-06 +2.4672e-05 +4.6868e-06 +1.4889e-05 +1.8599e-05 +0.00019303 +3.7693e-05 +4.1698e-05 +0.063052 +0.094482 +0.0097564 +0.02966 +55.713 +296.05 +0.1218 +0.16532 +0.046928 +993.74 +452.93 +133.18 +99.132 +0.012385 +40.833 +11.768 +47.938 +7.3861e-05 +0.003021 +0.0040968 +0.0027758 +0.0059848 +0.004637 +329.62 +0.0043889 +0.0098104 +0.0040548 +0.023548 +0.066996 +0.034812 +0.037051 +0.024304 +1442.3 +1082.1 +172.93 +0.12566 +3.0354e-05 +1.7953e-05 +2.9701e-05 +5.3853e-06 +1768.9 +0.0050044 +13.877 +0.0047816 +0.0042807 +0.0069952 +0.010656 +3.4318e-05 +2.5863e-06 +1.704e-05 +1.3901e-05 +9.5444e-06 +9.2367e-06 +1.2837e-05 +1.8696e-06 +1.6011e-06 +4.4065e-06 +1.034e-05 +6.8349e-06 +1.808e-05 +0.061998 +0.031202 +0.012954 +0.027942 +0.021625 +36.986 +0.098396 +0.39449 +0.054357 +1039.8 +0.17942 +94.57 +109.47 +0.012876 +94.88 +12.22 +35.449 +0.00012723 +0.0046693 +0.0017538 +0.0073975 +0.010889 +0.009922 +0.01258 +0.011348 +0.022724 +0.0075975 +0.02025 +0.090264 +0.043451 +0.024182 +2210 +1515.2 +0.5326 +0.0098017 +20.953 +1.6565e-05 +2.5871e-05 +7.7979e-06 +7.7727e-06 +0.020277 +0.0044165 +22.449 +0.0052991 +0.0037051 +0.0079419 +0.024529 +56.539 +2.2691e-06 +1.3789e-06 +1.4137e-05 +5.3556e-06 +1.0356e-05 +1.1882e-05 +1.0259e-05 +1.9621e-06 +4.3758e-06 +2.0601e-05 +1.1421e-05 +4.2741e-05 +332.88 +609.11 +0.24511 +0.031358 +0.059671 +0.012566 +0.013584 +0.044203 +0.077845 +0.081021 +221.43 +94.604 +114.79 +0.010618 +52.107 +25.404 +0.0092843 +0.0017735 +0.0065789 +0.0039076 +0.0056094 +0.016355 +0.016485 +0.049557 +0.012521 +0.026944 +0.011881 +0.024201 +0.092905 +0.071676 +1314.3 +1462.9 +0.4573 +0.014831 +0.0096322 +0.0059475 +4.2397e-06 +7.6226e-06 +1.3975e-05 +0.045651 +35.53 +10.329 +20.124 +0.0045391 +0.0034866 +0.0059594 +31.422 +44.248 +1.0363e-05 +5.6511e-06 +1.4809e-05 +9.8921e-06 +3.1666e-06 +2.5205e-06 +1.1921e-05 +4.5407e-06 +9.4984e-06 +2.3079e-05 +9.6631e-06 +1.0193e-05 +0.49248 +0.46957 +0.029495 +0.38565 +0.030247 +0.0031979 +0.0065641 +0.046215 +0.070475 +0.091791 +0.057557 +52.592 +69.486 +0.017622 +29.441 +24.222 +33.341 +0.0019508 +0.0034909 +0.0014136 +0.0030208 +0.018659 +0.0073339 +87.465 +0.027649 +0.024013 +0.041812 +0.023408 +0.060779 +827.23 +1476 +839.83 +1418.8 +788.08 +0.012868 +0.0046913 +7.26e-06 +7.2401e-06 +0.084144 +0.064664 +0.022438 +0.0045655 +18.145 +0.0067441 +0.035593 +0.05719 +53.744 +17.637 +0.01979 +1.3627e-05 +3.0573e-05 +1.1765e-05 +6.7013e-06 +1.8219e-06 +1.6733e-06 +5.7497e-06 +6.4122e-06 +1.3514e-05 +9.0312e-06 +6.6371e-06 +1.4163 +0.75429 +283.02 +0.032296 +2.3517e-05 +0.0030915 +30.034 +0.037611 +0.033724 +0.0723 +0.10562 +0.076133 +0.017687 +0.0055933 +31.283 +24.569 +28.914 +21.535 +0.002172 +0.0010677 +0.0022403 +0.015335 +0.0063851 +0.0097804 +0.016595 +0.029634 +0.049623 +0.01847 +0.041273 +0.0043664 +1680.6 +1200.9 +558.1 +803.77 +0.00598 +0.0050525 +11.609 +232.69 +0.057289 +0.14759 +0.033699 +0.011505 +0.06499 +0.2193 +0.024561 +0.07441 +0.019127 +25.486 +0.017042 +2.6531e-06 +1.137e-05 +2.7563e-06 +2.8579e-06 +1.7583e-06 +1.7441e-06 +5.683e-07 +2.4632e-06 +4.0253e-06 +1.3335e-05 +1.8874e-05 +1.4495 +1.657 +160.56 +0.0098258 +0.099854 +0.065323 +6.2389 +0.00090748 +0.036011 +0.13028 +0.18285 +0.1244 +0.093362 +0.0055069 +20.796 +12.1 +10.903 +36.408 +0.0010116 +0.001508 +0.0036442 +50.446 +0.01222 +0.012415 +0.027844 +0.042585 +0.046823 +0.015497 +0.012634 +0.0023185 +0.0050345 +0.37127 +439.81 +538.15 +416.05 +0.0072252 +15.336 +0.017873 +0.055167 +0.15856 +0.033167 +0.034835 +0.035349 +0.12771 +0.063525 +0.039283 +0.0091123 +28.824 +68.242 +6.421e-07 +4.9285e-06 +4.4429e-06 +8.224e-07 +4.7792e-06 +6.8893e-06 +1.7327e-06 +3.9469e-06 +8.043e-06 +1.3022e-05 +8.2486e-06 +1.5401 +1.2469 +0.0016882 +0.014176 +0.07348 +0.29301 +0.032375 +5.2506e-05 +0.0021982 +0.16934 +0.17276 +0.18952 +0.095711 +0.10749 +21.077 +15.804 +13.677 +63.026 +12.639 +0.0010354 +0.0019661 +0.0079071 +0.022231 +0.0067117 +0.02187 +0.019349 +0.023843 +0.029685 +0.0085012 +0.0040904 +0.0059337 +0.34102 +510.15 +389.01 +634.63 +879.12 +0.0020937 +0.012349 +0.0062511 +0.014119 +0.03273 +0.022118 +0.024025 +0.061272 +0.033089 +0.023397 +0.0080032 +18.307 +34.94 +84.42 +3.5713e-05 +2.9346e-06 +2.7064e-06 +3.5857e-06 +4.5525e-06 +6.328e-07 +4.8262e-06 +7.2376e-06 +8.9183e-06 +2.5603e-05 +1.186 +1.8 +0.0084076 +0.011248 +0.047124 +0.195 +0.023046 +0.022641 +0.023352 +45.639 +0.13109 +0.16637 +0.077952 +0.075812 +0.040568 +19.882 +19.532 +25.527 +17.65 +18.061 +5.6335 +0.023433 +0.010495 +0.0030056 +0.0012884 +0.033023 +0.036601 +0.052689 +0.013022 +0.0041979 +0.0039877 +24.928 +201.7 +527.64 +401.64 +854.85 +0.0073871 +0.0095442 +0.013127 +0.0078909 +0.029433 +0.027398 +0.039663 +0.04835 +0.04937 +0.02446 +0.013736 +25.374 +0.016583 +54.588 +2.4078e-05 +4.7571e-06 +4.2202e-06 +1.1999e-05 +3.037e-06 +9.228e-07 +2.1816e-06 +3.0977e-06 +1.7975e-05 +2.4829e-05 +0.00074315 +2.1879 +15.88 +1.9791 +0.029388 +0.48638 +0.09283 +0.011259 +0.018304 +0.0021641 +0.0015022 +0.071713 +0.16148 +0.062928 +0.054228 +0.014276 +21.905 +19.91 +5.4998 +18.334 +12.542 +17.945 +0.0043447 +0.003707 +0.0016375 +0.045518 +0.060162 +0.19838 +0.012705 +0.0063564 +0.00091131 +24.58 +0.0065859 +43.557 +199.79 +924.86 +0.49753 +83.282 +0.018154 +0.0086337 +0.0081146 +0.029329 +0.032772 +0.10738 +0.051255 +0.03471 +0.013498 +47.328 +0.02653 +5.4571e-06 +1.8742e-05 +8.2125e-06 +3.3194e-06 +8.1653e-06 +4.9311e-06 +5.8793e-06 +2.0303e-06 +6.7323e-06 +1.3689e-05 +2.0344e-05 +0.0013834 +2.9316 +14.666 +3.7547 +4.8767 +0.49656 +0.16595 +0.014105 +0.019306 +0.0035968 +0.0034877 +0.0052472 +0.13441 +0.04939 +0.06127 +56.406 +15.875 +11.952 +6.1056 +10.126 +0.0015054 +12.496 +0.010628 +0.0051689 +0.0014346 +0.053601 +0.067232 +0.10508 +0.0098978 +0.010755 +0.0015314 +20.269 +0.0025825 +27.169 +0.055162 +1172.4 +0.22114 +89.246 +42.457 +22.288 +0.0084463 +0.049794 +0.032186 +0.079851 +0.099735 +0.024592 +0.020791 +0.028935 +6.7189e-06 +1.2025e-05 +1.1858e-05 +3.864e-05 +1.0523e-05 +3.428e-05 +1.8746e-05 +3.4576e-06 +8.9765e-06 +5.9297e-06 +1.0473e-05 +1.5225e-05 +0.001386 +3.6964 +9.3979 +2.6759 +0.032304 +0.013471 +0.014597 +0.045124 +0.0059115 +0.0055685 +0.0085474 +0.0088555 +0.0015423 +0.055567 +0.047914 +38.415 +45.188 +12.348 +7.073 +8.882 +5.8715 +11.896 +0.004311 +0.016017 +0.0080801 +0.022467 +0.11748 +0.086135 +0.015229 +0.031512 +0.019456 +33.476 +0.0030172 +19.642 +0.013445 +0.0087755 +0.11863 +0.022371 +106.08 +38.605 +0.01515 +0.026889 +0.096896 +0.1414 +0.07446 +0.032058 +0.028253 +74.887 +2.4849e-05 +2.9093e-05 +2.5982e-05 +9.9116e-05 +3.283e-05 +1.1002e-05 +4.8244e-06 +4.3303e-06 +7.2392e-06 +1.7545e-05 +1.5748e-05 +3.6863e-05 +0.0023905 +3.5242 +6.3654 +4.3017 +0.088283 +1.8589e-05 +0.022916 +0.0067704 +0.0051019 +18.151 +23.151 +0.018656 +0.0051586 +0.022658 +0.040433 +51.461 +45.87 +18.168 +7.4751 +17.173 +2.7526 +9.7304 +0.0040515 +0.0080929 +0.034809 +0.011132 +0.021536 +14.179 +0.013404 +0.032131 +17.486 +24.019 +22.158 +15.302 +0.012288 +0.006166 +0.0084989 +31.189 +48.933 +29.389 +110.08 +0.0065736 +0.16813 +0.089147 +0.10011 +0.036126 +6.6279e-06 +0.0001296 +3.2493e-05 +2.5601e-05 +9.5479e-06 +4.6715e-05 +2.4702e-05 +8.9324e-05 +9.8013e-06 +3.5136e-06 +1.8783e-06 +1.7506e-05 +7.2354e-06 +5.5295e-06 +0.0033351 +0.001696 +2.601 +2.5906 +0.13579 +5121.2 +0.0040055 +22.014 +3.4513 +18.002 +22.652 +29.141 +0.0081796 +0.017671 +0.044969 +85.247 +85.333 +19.266 +6.8466 +12.896 +1.9131 +9.3217 +0.015539 +0.0084027 +0.034338 +0.010221 +0.012958 +0.015128 +0.0089326 +3.188e-05 +21.325 +31.627 +0.016584 +0.012581 +0.0080866 +0.0098395 +120.22 +0.012572 +40.934 +24.516 +0.016566 +0.0063942 +9.7364 +0.052723 +2.479e-05 +6.1274e-05 +1.7505e-05 +8.3339e-06 +4.0549e-06 +1.1917e-05 +2.3824e-06 +1.2139e-06 +8.4957e-06 +1.7797e-05 +3.1481e-06 +3.3224e-06 +9.7474e-06 +7.2072e-06 +2.5574e-05 +2.1377e-06 +0.0081456 +0.0041589 +0.0017169 +0.0015404 +5.6775 +0.013716 +21.408 +19.355 +7.2626 +12.958 +14.59 +0.019669 +0.0093569 +67.537 +0.026947 +28.612 +29.15 +23.952 +13.023 +19.264 +6.6976 +48.343 +48.574 +0.011226 +0.038177 +0.0061769 +0.0042907 +0.0056459 +0.0053078 +0.002873 +0.0021702 +20.389 +0.033027 +40.538 +0.0075358 +0.032975 +63.977 +56.477 +59.697 +19.291 +22.612 +0.0047043 +17.01 +3.2864e-06 +2.9714e-05 +0.00012298 +1.3757e-05 +4.3475e-05 +1.7595e-05 +2.0137e-05 +3.2129e-05 +1.3389e-06 +6.7862e-06 +7.6756e-06 +3.17e-06 +8.228e-07 +2.6471e-06 +6.5689e-06 +8.4098e-06 +2.0856e-06 +0.010899 +25.924 +0.0021645 +0.0010701 +0.011477 +82.767 +17.894 +11.883 +9.2488 +22.432 +455.71 +0.023341 +157.03 +54.792 +100.03 +30.925 +33.8 +46.941 +27.988 +48.418 +13.905 +16.025 +42.586 +28.061 +0.038485 +0.0079639 +0.0028888 +0.0048559 +0.0025837 +7.1918 +0.0030127 +0.0025532 +56.11 +56.822 +86.711 +121.97 +63.043 +181.89 +56.336 +14.195 +24.825 +2.3591e-05 +1.827e-05 +3.6279e-06 +1.4376e-05 +1.8934e-05 +1.3446e-05 +1.6527e-05 +4.125e-05 +4.6207e-05 +3.4286e-05 +2.1036e-06 +3.2588e-06 +1.2984e-05 +3.8536e-06 +1.4503e-06 +1.3669e-06 +7.1847e-06 +1.4763e-05 +1.4067e-05 +0.0090213 +19.736 +4.5969 +0.00078638 +19.502 +91.806 +14.176 +204.32 +0.13819 +0.035198 +0.060914 +0.010044 +93.882 +58.175 +79.734 +41.617 +46.287 +30.559 +21.121 +137.4 +24.363 +51.816 +41.144 +38.145 +0.026087 +0.0049476 +0.0044337 +0.0079109 +29.626 +0.0024538 +5.1497 +0.029303 +0.01609 +137.42 +82.424 +49.723 +56.558 +96.261 +42.012 +15.355 +0.00012868 +4.9845e-05 +6.9229e-06 +6.8235e-06 +2.3328e-06 +1.4641e-05 +5.5429e-05 +3.2456e-05 +1.1474e-05 +1.8441e-05 +3.7657e-06 +3.3751e-06 +4.6685e-06 +5.2535e-06 +4.3469e-05 +9.1557e-06 +5.3914e-06 +1.2411e-05 +2.6058e-05 +4.4777e-06 +17.281 +11.85 +5.6946 +0.0023733 +128.19 +0.087615 +0.046367 +422.31 +0.085321 +0.073082 +0.033003 +0.0072821 +0.011234 +52.158 +57.937 +2.5473 +2.4648 +3.3374 +0.018318 +0.050542 +3.9119 +22.776 +43.537 +21.112 +0.016503 +0.0085525 +3.948e-06 +6.3966e-06 +15.319 +9.9259 +5.0477 +0.081765 +0.029084 +194.05 +64.079 +91.081 +48.503 +0.025562 +6.356e-05 +1.7687e-05 +9.4067e-05 +5.5357e-05 +1.6547e-05 +6.2933e-06 +6.1666e-06 +1.1768e-06 +4.9334e-06 +1.0235e-05 +3.2313e-06 +1.8103e-05 +5.6532e-06 +1.7429e-05 +9.1581e-06 +1.6587e-05 +1.1756e-05 +0.00010874 +3.1652e-05 +2.2127e-05 +7.0532e-06 +3.3851e-06 +17.108 +7.1887 +0.12571 +0.12945 +187.86 +149.64 +0.028761 +0.15411 +0.079401 +0.050854 +0.026859 +0.014768 +69.093 +22.706 +14.888 +1.8629 +0.021731 +359.38 +0.032183 +57.431 +4.3137 +23.991 +29.138 +41.047 +2.1514e-06 +7.827e-07 +6.0142 +5.3468e-06 +0.0041131 +0.0051024 +0.11317 +0.090249 +0.033953 +339.19 +90.856 +113.68 +0.014517 +5.7038e-06 +1.9252e-05 +4.8657e-05 +9.0054e-05 +3.8425e-05 +3.8058e-05 +1.2796e-05 +1.6752e-05 +3.1015e-06 +6.3999e-06 +8.2118e-06 +1.279e-05 +1.472e-06 +2.2981e-05 +4.0355e-05 +6.2896e-05 +1.0493e-05 +2.2375e-05 +4.1069e-05 +1.5286e-05 +5.3713e-06 +4.3361e-05 +6.0175e-06 +31.496 +4.2566 +0.11797 +0.11576 +186.75 +226.15 +0.022104 +349.99 +0.095565 +0.019342 +86.293 +0.099452 +34.271 +26.241 +10.735 +0.018641 +107.8 +0.051198 +0.016038 +0.010418 +9.8047 +35.373 +81.194 +3.439e-06 +7.61e-07 +3.6021e-06 +5.4414e-06 +5.5327e-06 +0.19081 +0.073307 +0.090234 +0.12319 +0.086264 +0.08326 +0.01936 +0.028108 +0.021662 +5.5577e-06 +5.5177e-06 +1.469e-05 +1.1132e-05 +6.2654e-05 +3.5621e-05 +8.4066e-06 +1.2204e-05 +5.4041e-05 +2.6394e-06 +6.3307e-06 +1.806e-06 +6.9225e-06 +2.1656e-05 +3.8735e-05 +1.6511e-05 +4.4637e-06 +1.4374e-05 +4.4954e-05 +4.0793e-05 +2.2452e-06 +2.2494e-06 +1.7912e-06 +61.465 +0.019287 +65.953 +0.11392 +239.71 +0.058547 +0.016912 +0.094473 +0.1292 +0.0648 +0.22018 +0.053268 +47.372 +18.031 +0.07652 +0.028878 +0.0037104 +0.0041414 +0.021475 +0.0068606 +10.832 +0.17289 +8.7427e-06 +9.1913e-06 +1.4966e-05 +2.4793e-05 +9.7395e-06 +1.5154e-05 +0.16434 +0.13389 +0.050775 +0.098836 +0.001416 +0.0006465 +0.0067495 +0.027863 +0.060836 +2 +2.9726e-05 +8.1376e-06 +1.3631e-05 +1.5145e-05 +2.4469e-05 +7.8288e-06 +2.1849e-05 +2.5451e-05 +1.0246e-05 +4.2455e-06 +9.998e-07 +4.3855e-05 +1.858e-05 +2.3549e-05 +2.8397e-05 +3.4734e-06 +5.6939e-05 +6.5779e-06 +2.423e-05 +2.2365e-06 +3.7905e-06 +6.4475e-06 +0.015241 +0.018365 +53.752 +145.34 +0.09765 +179.5 +0.036857 +0.068721 +0.23709 +0.035839 +0.11922 +0.039732 +0.024024 +41.024 +34.244 +8.3399 +0.0050863 +0.0042337 +0.03024 +0.038122 +0.029289 +0.33807 +4.495e-05 +3.7642e-05 +4.7346e-05 +4.0705e-05 +0.0038559 +0.0024115 +0.00070979 +0.0020524 +0.00082542 +0.057913 +0.0441 +0.00070297 +0.046365 +0.014905 +0.091435 +1.1424 +0.53067 +6.5776e-06 +8.3743e-06 +1.7129e-05 +1.2881e-05 +9.8865e-06 +9.9205e-06 +3.6675e-05 +7.6694e-06 +5.0893e-06 +1.0022e-05 +2.2813e-05 +1.9427e-05 +5.4389e-06 +5.2722e-06 +5.2901e-06 +1.5553e-05 +1.0725e-05 +1.6306e-05 +3.6959e-05 +2.3806e-05 +2.3328e-05 +0.012838 +0.027195 +80.49 +138.2 +0.092667 +0.060986 +0.057622 +0.077715 +0.22057 +0.084524 +0.018652 +0.034357 +21.125 +26.39 +0.0064561 +4.8492 +0.0030278 +0.34505 +0.025444 +0.051536 +0.046631 +0.16017 +6.2995e-06 +0.019811 +0.0063856 +0.00082241 +0.0028476 +0.0037953 +0.0067873 +0.0038098 +0.0015502 +4.2198 +0.039038 +0.00093938 +4.4876 +0.026415 +0.033088 +0.48839 +0.64832 +2.7342e-06 +8.0711e-06 +2.6539e-05 +1.4223e-05 +3.6764e-06 +6.8373e-06 +8.6826e-06 +6.1436e-06 +9.274e-06 +1.1073e-05 +3.4654e-06 +5.3774e-06 +5.8785e-06 +4.813e-06 +6.8237e-06 +4.5184e-06 +5.324e-06 +1.5088e-05 +4.5824e-05 +6.4929e-06 +5.6958e-05 +0.015319 +0.047461 +85.638 +164.54 +0.042969 +0.075281 +0.022222 +0.10524 +0.11252 +0.10193 +0.030131 +0.031853 +12.124 +18.542 +14.119 +5.8715 +0.2912 +0.29657 +0.1285 +0.11 +0.036853 +0.11063 +0.15247 +0.32448 +0.0018927 +0.0011331 +0.0011707 +0.0040729 +0.010874 +0.002558 +0.0035538 +4.6754 +0.040359 +0.0079298 +3.2403 +8.0561 +0.00010501 +0.25493 +0.96141 +0.10004 +1.4624e-06 +1.2442e-05 +4.6415e-06 +1.1215e-05 +6.1612e-06 +4.5251e-06 +3.685e-07 +5.0648e-06 +8.627e-06 +2.7103e-05 +1.2599e-05 +3.3378e-06 +1.4017e-05 +6.9181e-06 +3.481e-06 +7.2204e-06 +3.2787e-06 +2.8272e-05 +3.4053e-05 +0.00015226 +0.020437 +1011 +0.095985 +208.76 +0.058035 +108.44 +0.070147 +0.02406 +0.035384 +25.3 +59.076 +0.043497 +6.901 +10.092 +8.3222 +5.1766 +0.54905 +0.53619 +0.50473 +0.13935 +0.095777 +0.2251 +0.25766 +0.80135 +0.0018239 +0.0016713 +0.002337 +0.0035998 +0.0093786 +0.0047002 +0.0045523 +0.044901 +0.050189 +5.2232 +4.0134 +6.9672 +2.5819 +3.6344e-05 +0.7011 +0.0768 +0.11655 +2.0792e-05 +1.4701e-05 +9.6241e-06 +2.2517e-05 +7.0283e-06 +1.6705e-06 +4.0251e-06 +1.7631e-06 +1.3341e-05 +4.9896e-06 +2.5569e-05 +2.3034e-05 +1.2899e-05 +6.4062e-06 +3.4764e-06 +2.8653e-06 +2.5073e-05 +3.1567e-05 +0.00010597 +0.034568 +0.059228 +0.21342 +0.12029 +0.053947 +99.211 +0.040963 +359.76 +0.066886 +37.36 +30.31 +4.6706 +0.014677 +9.8807 +15.884 +4.1051 +0.0038817 +0.55231 +0.59109 +167.46 +0.078159 +0.5226 +0.56291 +0.76378 +0.0007106 +0.0013787 +0.0034437 +0.0019076 +0.0035607 +0.0043835 +0.0056498 +0.030637 +0.037291 +12.448 +6.5647 +3.5156 +2.9073 +4.0136e-05 +1.059e-05 +0.084157 +0.093807 +0.048794 +1.0238e-06 +1.0553e-05 +4.6506e-06 +1.1898e-05 +6.2395e-06 +7.4887e-06 +3.7402e-06 +4.1439e-06 +8.5629e-06 +1.2357e-05 +4.826e-05 +5.641e-06 +2.809e-06 +8.891e-07 +7.8475e-06 +3.5253e-05 +5.9843e-05 +3.0841e-05 +0.014621 +0.0095998 +0.06748 +0.11069 +0.04417 +47.003 +0.044774 +0.020348 +0.032022 +12.684 +34.237 +5.2128 +0.011668 +7.5234 +18.276 +10.865 +0.0045414 +26.569 +0.63667 +0.049195 +0.11821 +0.61782 +0.47962 +0.44813 +2.0407e-05 +0.0011856 +0.0021926 +0.0016243 +0.0023729 +9.3971e-06 +0.006136 +0.036193 +0.02778 +13.821 +4.1436 +4.9326 +5.5823 +1.3516 +3.4962e-06 +6.3652e-06 +0.13857 +0.038644 +0.024684 +1.4137e-05 +4.5911e-05 +3.4995e-05 +2.6907e-05 +3.6218e-05 +1.9126e-05 +1.741e-05 +2.2072e-06 +1.6994e-05 +3.8305e-06 +5.0812e-06 +6.9623e-06 +6.206e-07 +2.1296e-06 +2.92e-05 +3.4715e-05 +0.00010713 +33.709 +13.025 +57.155 +0.068682 +124.01 +66.112 +0.083474 +224.65 +0.02535 +17.324 +45.034 +6.3636 +0.012576 +10.873 +0.0080544 +25.471 +0.004781 +15.551 +0.40495 +0.049062 +0.019432 +0.017038 +0.57639 +0.45976 +9.0267e-05 +8.6949e-05 +8.1293e-05 +2.5663e-05 +2e-05 +2.6418e-05 +0.0079064 +0.014185 +0.015354 +10.508 +2.8181 +2.7598 +2.2746 +1.6799 +6.0083 +4.4108e-06 +1.1056e-05 +0.024089 +0.020069 +0.0123 +0.0003858 +0.00030067 +4.0047e-05 +2.5624e-05 +6.1325e-05 +5.7434e-05 +3.5709e-05 +1.1586e-05 +3.4646e-06 +2.964e-06 +6.8849e-06 +1.4857e-06 +5.365e-07 +3.5297e-05 +5.0582e-05 +0.00011016 +33.97 +12.669 +33.387 +0.047444 +140.65 +41.432 +83.246 +259.38 +0.020123 +12.87 +18.824 +3.7936 +0.011577 +16.805 +16.142 +29.57 +0.0070706 +0.0051033 +7.3777 +7.363 +0.021043 +0.031109 +0.0080961 +0.18537 +0.14403 +5.4587e-05 +8.3071e-05 +6.988e-06 +5.1265e-06 +8.2991e-06 +0.011297 +0.03202 +0.094172 +0.22413 +5.7221 +1.9637 +1.4463 +4.3002 +1.944 +6.5746e-06 +1.132e-05 +0.01613 +0.0061142 +0.0035962 +0.0013512 +3.2989e-05 +2.049e-05 +1.7804e-05 +5.6547e-05 +4.957e-05 +3.7138e-05 +5.3374e-06 +6.3802e-06 +2.806e-05 +6.1452e-06 +3.3847e-05 +3.4291e-06 +2.3814e-05 +3.9771e-05 +2.1901e-05 +60.854 +13.052 +0.016932 +0.0052427 +0.053214 +0.11878 +70.043 +362.64 +490.38 +8.3072 +11.681 +4.317 +2.3841 +32.651 +20.4 +54.09 +31.998 +0.0098757 +7.6189 +7.9686 +15.778 +0.044693 +0.0075141 +0.19577 +348.45 +2.3214e-05 +7.412e-06 +2.4165e-06 +2.6018e-05 +0.05345 +0.011663 +76.155 +57.038 +0.16129 +0.22839 +1.3509 +1.3807 +3.171 +2.3589 +3.6369e-06 +9.6908e-06 +0.017091 +0.0053093 +0.0024879 +0.0027583 +9.919e-05 +3.2218e-05 +1.3575e-05 +7.6685e-05 +5.5023e-05 +1.5789e-05 +1.557e-05 +1.9741e-05 +2.7046e-05 +1.7342e-05 +3.2438e-05 +4.1117e-05 +5.3851e-05 +1.8219e-05 +1.2775e-05 +0.025879 +23.073 +0.0070134 +0.0083549 +0.043583 +0.010345 +0.022757 +334 +416.41 +196.68 +766.46 +2.4312 +25.28 +69.766 +20.157 +46.12 +37.66 +0.043186 +0.04219 +7.1951 +24.754 +14.863 +0.0064313 +25.102 +1.4088e-05 +1.8529e-05 +3.1038e-05 +1.0529e-05 +4.6473e-06 +0.010535 +22.878 +0.017649 +41.194 +0.090664 +0.10798 +0.028775 +1.639 +2.5853 +2.4007 +5.7809e-06 +2.6716e-05 +0.01853 +0.0035779 +0.0029912 +0.0051068 +0.00033967 +2.249e-05 +1.3473e-05 +4.8103e-05 +0.00020001 +4.0828e-05 +5.0174e-05 +2.0536e-05 +0.00012002 +5.4592e-05 +7.3546e-06 +1.3058e-05 +8.7965e-06 +1.7538e-05 +5.1666e-06 +1.1951 +171.55 +19.632 +0.0083139 +0.010029 +0.025407 +0.048144 +0.042391 +0.031372 +555.67 +360.55 +816.89 +44.85 +84.596 +32.748 +35.891 +53.517 +9.8612 +0.013376 +60.653 +0.014237 +27.387 +0.0049244 +0.0067492 +2.3922e-05 +7.2452e-06 +5.9104e-06 +0.0053378 +0.0081514 +0.0062733 +20.751 +0.01786 +23.671 +0.088198 +0.078959 +0.022926 +0.034568 +3.3845e-05 +1.69e-05 +6.5015e-05 +0.065395 +0.011503 +0.0040762 +0.0028143 +0.0018116 +5.6281e-06 +7.4211e-06 +6.3786e-06 +2.2665e-05 +0.00011135 +0.00018627 +0.00010305 +4.6698e-05 +3.2024e-05 +3.6744e-05 +3.0865e-05 +6.8377e-05 +5.4778e-06 +2.2752e-06 +9.8575e-06 +208.58 +94.364 +0.004836 +0.011648 +0.012029 +0.075804 +0.049265 +0.038725 +0.080226 +0.036469 +0.036289 +775.5 +519.53 +244.11 +49.293 +35.667 +81.144 +14.156 +0.013889 +77.349 +0.033457 +0.018502 +0.0035568 +0.006529 +0.0091223 +0.0074021 +0.0058671 +0.0089157 +0.0042217 +0.014455 +35.066 +0.038292 +0.017873 +0.12538 +0.041314 +0.032828 +0.019112 +0.012455 +0.0066652 +0.022172 +0.048579 +0.014267 +0.0022968 +0.0050586 +6.5482e-06 +9.6258e-06 +7.727e-06 +4.5136e-05 +7.232e-05 +5.0779e-05 +3.5879e-05 +0.00013405 +9.348e-05 +2.5919e-05 +3.1328e-05 +3.0467e-05 +1.1207e-05 +7.8028e-06 +9.2702e-06 +4.4516e-06 +0.39113 +35.288 +14.365 +0.0044938 +0.015371 +0.063103 +0.040918 +0.036328 +0.040672 +0.15297 +583.01 +225.81 +0.23176 +311.28 +61.653 +52.694 +64.776 +123.28 +40.99 +0.0040846 +0.0010936 +3.5188e-06 +3.7047e-06 +0.0094905 +0.007932 +0.0076547 +0.002858 +0.0097661 +0.0090744 +0.034178 +0.091511 +0.046314 +0.020347 +0.12142 +56.227 +0.0093426 +0.010297 +0.024747 +0.012224 +0.037972 +0.094923 +0.018488 +0.003448 +1.4067e-05 +1.6036e-05 +3.2147e-05 +5.5511e-05 +0.00016732 +0.0001485 +3.0166e-05 +3.5656e-05 +8.7711e-05 +0.00015999 +0.00012133 +7.1639e-06 +9.7078e-06 +6.2833e-06 +7.8319e-06 +1.1189e-05 +5.2087e-06 +0.007547 +0.032733 +0.081094 +0.004894 +0.011236 +0.013599 +0.056403 +0.042881 +97.626 +0.094308 +305.52 +133.87 +34.688 +325.95 +25.424 +100.06 +0.03352 +0.017043 +0.0090889 +0.0030856 +0.0018218 +8.446e-06 +86.754 +10.772 +0.011606 +0.015016 +0.0050736 +0.0087845 +0.0084283 +0.06862 +0.13597 +0.11563 +0.51584 +3.407e-06 +1.2671e-06 +0.0033992 +1.6328e-05 +2.3849e-05 +1.0527e-05 +1.9088e-05 +1.4316e-05 +4.9323e-06 +2.5146e-05 +1.3173e-05 +5.233e-06 +2.9288e-05 +0.00032381 +0.00017772 +0.00012188 +3.0211e-05 +4.5187e-05 +8.1733e-05 +9.5902e-05 +8.2853e-05 +1.3627e-05 +2.4409e-05 +7.3842e-06 +7.1618e-06 +9.1826e-06 +7.311e-07 +0.0056215 +0.019147 +0.086448 +0.013037 +0.0081244 +0.0094073 +0.045003 +0.02466 +0.008084 +0.043187 +164 +177.02 +36.064 +0.011254 +0.012352 +85.14 +0.039824 +22.617 +0.008179 +0.005574 +8.0217e-06 +1.8078e-05 +21.735 +5.0946 +0.009054 +0.016277 +0.0033063 +0.048843 +0.017403 +0.12347 +0.10391 +12.825 +82.339 +1.9462e-06 +1.2006e-05 +1.9701e-05 +2.7779e-05 +1.9921e-05 +3.1658e-05 +1.9006e-05 +2.0798e-05 +1.4864e-05 +3.0309e-05 +1.8967e-05 +1.2345e-05 +1.9997e-05 +1.6787e-05 +2.4989e-05 +9.9583e-06 +5.1502e-05 +2.8993e-05 +2.8413e-05 +6.0542e-05 +1.241e-05 +1.1731e-05 +1.6837e-05 +9.3039e-06 +5.6192e-06 +7.8605e-06 +1.8962e-05 +0.0055558 +0.0030342 +464.79 +56.911 +0.0089231 +0.014053 +0.048034 +0.059894 +0.01095 +0.02667 +0.037822 +164.58 +123.63 +0.014558 +0.0094822 +0.036346 +86.261 +0.0064579 +14.649 +0.0079264 +0.0054063 +8.7997 +12.472 +4.4108 +0.013429 +0.017788 +0.0041869 +0.041971 +0.019737 +0.038514 +0.16034 +4.8525 +2.3559e-05 +4.7942e-06 +5.7576e-06 +5.4416e-05 +4.8425e-05 +3.0715e-05 +7.0684e-05 +2.765e-05 +2.9715e-05 +2.0019e-05 +1.284e-05 +4.3112e-05 +1.543e-05 +1.0444e-05 +8.6e-06 +7.8884e-05 +3.1419e-05 +3.8494e-05 +5.7546e-05 +0.00055527 +6.7306e-05 +2.8949e-05 +3.2038e-06 +2.5226e-05 +1.2284e-05 +9.3856e-06 +1.2448e-05 +3.7224e-05 +0.013287 +0.0061206 +346.93 +69.785 +0.012487 +0.010949 +0.034717 +0.035827 +0.02094 +0.017735 +0.043602 +126.35 +0.037835 +0.040246 +0.034672 +0.018053 +25.096 +19.357 +23.633 +0.022911 +0.0072587 +8.7898 +11.646 +0.017989 +0.022137 +0.040722 +0.32167 +0.38479 +22.171 +9.0206 +20.736 +6.1981 +3.1024e-05 +0.00023437 +2.8557e-05 +2.806e-05 +5.2248e-05 +5.5235e-05 +0.00016657 +1.0042e-05 +2.0653e-05 +4.4536e-05 +2.626e-05 +1.2362e-05 +2.1098e-06 +9.823e-07 +6.6443e-06 +1.5849e-05 +3.5409e-06 +2.0897e-06 +3.8457e-05 +0.00015403 +0.00017864 +9.2947e-05 +1.211e-05 +1.8169e-05 +3.437e-06 +6.8512e-06 +7.26e-06 +6.3071e-06 +0.012771 +0.010222 +0.0041982 +0.014375 +0.013274 +0.0075615 +0.020233 +0.030613 +0.02387 +0.020867 +126.99 +248.31 +0.081841 +0.063315 +0.08924 +0.016511 +0.0094909 +31.859 +53.797 +141.34 +16.166 +31.337 +9.0155 +0.030397 +0.017525 +0.038458 +0.0083087 +0.33801 +18.772 +14.036 +39.141 +0.00016314 +0.00014338 +6.8098e-05 +2.3397e-05 +2.8988e-05 +3.6032e-05 +1.2572e-05 +5.5654e-05 +3.3438e-05 +8.6464e-06 +1.4357e-05 +8.8183e-06 +3.0601e-06 +1.347e-06 +3.0183e-06 +6.8391e-06 +6.299e-06 +1.6731e-05 +1.1755e-05 +1.9204e-05 +1.0179e-05 +4.8884e-05 +8.3021e-05 +1.5179e-05 +1.1309e-05 +1.5335e-05 +5.1284e-06 +1.1109e-05 +2.6902e-05 +0.013047 +0.01111 +0.0039982 +0.032416 +0.021263 +0.0080125 +0.0092203 +0.019871 +0.014607 +0.013921 +0.0061682 +621.74 +0.11015 +0.11608 +0.28283 +0.27126 +0.014474 +59.104 +95.17 +76.399 +184.41 +0.0046991 +0.027681 +0.024028 +0.042174 +0.017491 +0.012319 +14.12 +9.219 +8.1667 +7.9767e-05 +9.3031e-05 +6.527e-05 +1.8686e-05 +5.7061e-05 +1.6706e-05 +3.9984e-05 +3.5152e-05 +1.8556e-05 +2.6583e-05 +3.5237e-05 +9.1806e-06 +3.2438e-06 +3.0631e-06 +2.5176e-06 +2.6231e-06 +2.4591e-05 +0.00013939 +5.1838e-05 +3.2738e-05 +1.6568e-05 +9.7878e-06 +2.557e-05 +8.6376e-05 +1.7641e-05 +3.3889e-06 +1.4991e-06 +2.6878e-06 +8.7333e-06 +1.6469e-05 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/layer84_poro.geos b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/layer84_poro.geos new file mode 100644 index 00000000000..8e485ab5eca --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/layer84_poro.geos @@ -0,0 +1,13200 @@ +0.12171 +0.090872 +0.10906 +0.23513 +0.17799 +0.086045 +0.12965 +0.16832 +0.13882 +0.15 +0.18351 +0.24172 +0.2655 +0.20816 +0.25494 +0.28693 +0.27192 +0.34452 +0.35924 +0.19538 +0.16714 +0.27446 +0.25962 +0.31536 +0.2911 +0.30169 +0.39745 +0.31837 +0.0001 +0.029892 +0.052544 +0.14862 +0.005373 +0.049221 +0.06202 +0.060043 +0.097794 +0.054828 +0.11588 +0.093109 +0.10121 +0.14317 +0.019731 +0.11035 +0.36078 +0.32945 +0.26523 +0.22707 +0.23378 +0.23126 +0.21842 +0.25254 +0.29153 +0.1682 +0.12028 +0.19479 +0.26626 +0.27721 +0.27402 +0.20827 +0.097387 +0.080609 +0.070943 +0.066481 +0.17236 +0.079527 +0.14474 +0.10709 +0.12798 +0.14888 +0.16909 +0.23307 +0.26516 +0.21394 +0.22834 +0.2877 +0.28493 +0.3338 +0.22508 +0.17226 +0.18646 +0.29498 +0.25605 +0.31724 +0.30978 +0.29277 +0.39319 +0.36147 +0.056601 +0.078462 +0.10497 +0.056088 +0.041931 +0.017205 +0.023895 +0.092709 +0.08638 +0.094137 +0.13101 +0.088262 +0.039585 +0.065739 +0.097164 +0.10867 +0.34251 +0.36489 +0.31803 +0.19504 +0.21733 +0.24277 +0.20694 +0.2713 +0.25486 +0.26893 +0.14966 +0.18197 +0.22251 +0.39116 +0.25523 +0.22178 +0.13705 +0.1317 +0.077886 +0.13711 +0.07016 +0.1376 +0.18534 +0.19607 +0.089562 +0.17266 +0.19974 +0.22098 +0.24145 +0.2123 +0.2309 +0.27702 +0.30245 +0.2357 +0.22728 +0.17381 +0.19867 +0.29282 +0.2539 +0.31535 +0.33869 +0.29536 +0.37013 +0.33984 +0.10476 +0.062342 +0.12436 +0.070767 +0.062656 +0.014093 +0.000684 +0.05786 +0.051159 +0.027007 +0.093433 +0.06199 +0.029236 +0.10116 +0.064178 +0.085929 +0.35612 +0.38314 +0.32059 +0.28417 +0.21628 +0.23773 +0.24024 +0.30733 +0.24177 +0.27154 +0.15519 +0.19369 +0.35477 +0.38178 +0.28311 +0.25456 +0.15194 +0.19085 +0.13708 +0.13212 +0.11783 +0.19874 +0.15409 +0.078452 +0.18483 +0.22545 +0.23315 +0.23485 +0.19145 +0.18964 +0.17044 +0.25893 +0.30036 +0.27533 +0.22457 +0.1701 +0.19548 +0.26454 +0.27861 +0.32341 +0.37271 +0.29555 +0.36861 +0.34953 +0.003082 +0.057416 +0.14313 +0.09219 +0.019274 +0.0001 +0.088126 +0.15124 +0.1609 +0.057231 +0.089156 +0.12609 +0.039889 +0.017578 +0.069447 +0.085436 +0.34133 +0.37464 +0.37123 +0.24364 +0.22582 +0.25774 +0.23186 +0.29062 +0.22914 +0.26853 +0.31161 +0.21799 +0.21846 +0.23278 +0.23078 +0.25575 +0.095792 +0.17877 +0.09975 +0.12178 +0.080449 +0.16699 +0.15138 +0.057 +0.16665 +0.22629 +0.26554 +0.21734 +0.16881 +0.22358 +0.16547 +0.23009 +0.31384 +0.28686 +0.26063 +0.1803 +0.21898 +0.29953 +0.32801 +0.32413 +0.3679 +0.31122 +0.36693 +0.34663 +0.34335 +0.078008 +0.13975 +0.082159 +0.089084 +0.078919 +0.068792 +0.14734 +0.081133 +0.049118 +0.0001 +0.020162 +0.054173 +0.044744 +0.063183 +0.075704 +0.043777 +0.4 +0.37622 +0.24324 +0.21735 +0.27038 +0.2579 +0.29251 +0.27953 +0.25569 +0.29229 +0.23251 +0.26403 +0.27962 +0.23576 +0.23671 +0.052945 +0.059831 +0.090584 +0.10807 +0.16384 +0.071278 +0.054647 +0.19289 +0.14028 +0.19799 +0.22337 +0.22967 +0.1722 +0.21355 +0.19417 +0.23229 +0.25504 +0.28264 +0.2712 +0.28835 +0.2946 +0.35963 +0.3526 +0.34338 +0.36194 +0.28658 +0.32627 +0.31776 +0.3541 +0.038285 +0.11649 +0.085041 +0.050133 +0.040295 +0.086412 +0.096228 +0.012635 +0.01924 +0.036214 +0.04578 +0.069518 +0.058692 +0.17155 +0.071461 +0.050767 +0.1461 +0.30977 +0.27996 +0.23146 +0.28128 +0.24163 +0.25935 +0.30291 +0.24612 +0.35449 +0.34766 +0.27795 +0.26495 +0.22731 +0.2204 +0.16348 +0.12058 +0.13855 +0.1319 +0.1063 +0.10538 +0.30524 +0.19891 +0.19624 +0.22284 +0.24251 +0.20878 +0.25101 +0.25504 +0.20821 +0.22388 +0.22801 +0.25494 +0.21077 +0.23715 +0.29666 +0.34629 +0.31113 +0.31483 +0.30075 +0.30321 +0.29824 +0.32557 +0.31832 +0.13903 +0.12215 +0.12624 +0.056668 +0.09529 +0.10353 +0.040625 +0.0001 +0.0001 +0.063855 +0.026822 +0.10547 +0.074763 +0.024269 +0.11014 +0.28275 +0.27402 +0.31433 +0.31741 +0.24199 +0.29166 +0.25266 +0.25863 +0.34139 +0.2763 +0.29694 +0.20534 +0.26582 +0.25286 +0.19953 +0.21789 +0.13199 +0.16002 +0.16704 +0.20286 +0.14513 +0.13355 +0.26457 +0.19966 +0.18499 +0.17819 +0.22538 +0.19904 +0.2776 +0.25942 +0.18818 +0.27946 +0.23334 +0.27518 +0.23364 +0.25003 +0.29805 +0.29858 +0.20876 +0.30579 +0.28111 +0.30192 +0.32728 +0.31363 +0.27131 +0.27379 +0.12434 +0.086308 +0.10605 +0.096915 +0.052189 +0.082438 +0.069434 +0.058633 +0.040127 +0.050175 +0.010739 +0.064853 +0.057141 +0.25729 +0.31843 +0.27848 +0.31818 +0.32177 +0.25435 +0.25983 +0.26447 +0.25797 +0.24781 +0.25978 +0.27292 +0.22641 +0.29418 +0.23865 +0.20582 +0.24694 +0.10114 +0.072493 +0.10407 +0.085986 +0.1576 +0.10032 +0.22899 +0.17138 +0.21958 +0.20568 +0.22449 +0.22674 +0.2584 +0.30725 +0.28062 +0.27318 +0.26178 +0.28611 +0.23641 +0.24196 +0.25707 +0.30851 +0.30314 +0.22351 +0.26118 +0.25562 +0.33603 +0.31061 +0.26037 +0.27018 +0.32998 +0.092615 +0.03095 +0.14821 +0.098404 +0.091219 +0.051387 +0.11554 +0.05485 +0.061202 +0.022896 +0.11206 +0.085496 +0.24651 +0.29965 +0.27973 +0.28985 +0.32251 +0.24124 +0.28266 +0.28663 +0.32264 +0.22662 +0.24879 +0.26999 +0.20016 +0.28004 +0.051353 +0.06475 +0.051129 +0.077268 +0.10321 +0.094891 +0.14247 +0.07715 +0.091713 +0.2586 +0.21083 +0.20893 +0.20506 +0.25334 +0.23677 +0.27875 +0.31937 +0.27107 +0.24963 +0.25347 +0.31378 +0.22891 +0.24397 +0.25813 +0.33877 +0.31691 +0.26202 +0.25376 +0.25656 +0.23565 +0.30729 +0.27377 +0.26291 +0.35876 +0.37599 +0.1232 +0.10125 +0.10853 +0.055036 +0.06743 +0.0001 +0.0001 +0.0001 +0.11689 +0.38176 +0.27766 +0.27597 +0.2839 +0.27229 +0.28831 +0.24451 +0.25557 +0.25301 +0.27159 +0.31422 +0.25875 +0.26827 +0.18719 +0.12997 +0.10486 +0.055607 +0.086623 +0.050988 +0.03355 +0.091438 +0.11774 +0.14752 +0.058459 +0.082875 +0.25458 +0.20612 +0.21157 +0.22149 +0.23094 +0.25041 +0.27964 +0.35494 +0.2827 +0.28613 +0.24978 +0.31371 +0.22036 +0.24581 +0.24037 +0.33625 +0.29679 +0.27576 +0.24201 +0.28525 +0.2882 +0.18261 +0.15394 +0.31091 +0.3383 +0.38233 +0.307 +0.12243 +0.10574 +0.088475 +0.10179 +0.02012 +0.0001 +0.36059 +0.32522 +0.36242 +0.3246 +0.28435 +0.24127 +0.18479 +0.21868 +0.20907 +0.23048 +0.25963 +0.26723 +0.15914 +0.26013 +0.21694 +0.19017 +0.15268 +0.12317 +0.12752 +0.10664 +0.10038 +0.09246 +0.05358 +0.028643 +0.10916 +0.083478 +0.064611 +0.22876 +0.21225 +0.22466 +0.21933 +0.24653 +0.23026 +0.28195 +0.34067 +0.30323 +0.2919 +0.2145 +0.29657 +0.22729 +0.23633 +0.23987 +0.25023 +0.26245 +0.2657 +0.2219 +0.29027 +0.17143 +0.20896 +0.22317 +0.16444 +0.31673 +0.22995 +0.34492 +0.12118 +0.10424 +0.11945 +0.1186 +0.12341 +0.31523 +0.35039 +0.33898 +0.32343 +0.32703 +0.28752 +0.23538 +0.20902 +0.22277 +0.21809 +0.21919 +0.12186 +0.17627 +0.16682 +0.23237 +0.2278 +0.19148 +0.12544 +0.13526 +0.19068 +0.026729 +0.09053 +0.072143 +0.075924 +0.060107 +0.12981 +0.16962 +0.06718 +0.26961 +0.19806 +0.21015 +0.25734 +0.1828 +0.22952 +0.2627 +0.32143 +0.32739 +0.3259 +0.24451 +0.29721 +0.25656 +0.24011 +0.22462 +0.25839 +0.22417 +0.32369 +0.21098 +0.27352 +0.13975 +0.18264 +0.20963 +0.26693 +0.20359 +0.1693 +0.18486 +0.18138 +0.09348 +0.10275 +0.095506 +0.34055 +0.3404 +0.3939 +0.34822 +0.30328 +0.33898 +0.19079 +0.23882 +0.21684 +0.21756 +0.23741 +0.22923 +0.20295 +0.19623 +0.14336 +0.22629 +0.23727 +0.1803 +0.12047 +0.16425 +0.086769 +0.040901 +0.12008 +0.0001 +0.0001 +0.10011 +0.10844 +0.070487 +0.047769 +0.24915 +0.20603 +0.22717 +0.24087 +0.17546 +0.24611 +0.25608 +0.34331 +0.29222 +0.31364 +0.35721 +0.16362 +0.22609 +0.22392 +0.21895 +0.20885 +0.22575 +0.31243 +0.38147 +0.28884 +0.17785 +0.18091 +0.20945 +0.23838 +0.22424 +0.19526 +0.22269 +0.21063 +0.23496 +0.31492 +0.35501 +0.3659 +0.38803 +0.39821 +0.38089 +0.046906 +0.087867 +0.01045 +0.20741 +0.23433 +0.25157 +0.23348 +0.2337 +0.19883 +0.21721 +0.16632 +0.24027 +0.22143 +0.19702 +0.13652 +0.1405 +0.14407 +0.070742 +0.072875 +0.057284 +0.002563 +0.034627 +0.090152 +0.11135 +0.002781 +0.23255 +0.24193 +0.24926 +0.2322 +0.22813 +0.24242 +0.26371 +0.32984 +0.34064 +0.284 +0.36092 +0.18512 +0.1693 +0.21798 +0.26137 +0.22442 +0.26701 +0.31943 +0.18657 +0.21964 +0.158 +0.19531 +0.17974 +0.23491 +0.24649 +0.20421 +0.15909 +0.26204 +0.18165 +0.27391 +0.28563 +0.37273 +0.38385 +0.37771 +0.033152 +0.063656 +0.04601 +0.036277 +0.25451 +0.23652 +0.24005 +0.25526 +0.28225 +0.24927 +0.23846 +0.15244 +0.4 +0.21939 +0.25827 +0.080823 +0.13568 +0.10637 +0.071771 +0.13145 +0.02207 +0.0001 +0.019034 +0.046384 +0.028098 +0.040266 +0.21684 +0.21914 +0.24508 +0.25595 +0.24252 +0.27349 +0.28096 +0.32729 +0.29723 +0.28883 +0.34174 +0.17796 +0.18899 +0.21503 +0.26029 +0.26372 +0.24907 +0.32049 +0.22769 +0.23767 +0.18606 +0.22938 +0.21013 +0.1847 +0.23339 +0.21423 +0.18738 +0.1712 +0.2353 +0.24579 +0.25416 +0.32888 +0.39545 +0.396 +0.049738 +0.10341 +0.018827 +0.014978 +0.24039 +0.21598 +0.26316 +0.27794 +0.2622 +0.29163 +0.253 +0.25692 +0.21907 +0.23063 +0.098889 +0.051157 +0.10561 +0.078769 +0.008708 +0.06371 +0.0001 +0.0001 +0.00893 +0.0001 +0.039683 +0.067983 +0.039992 +0.088713 +0.25531 +0.24238 +0.26212 +0.255 +0.27446 +0.31787 +0.29252 +0.29429 +0.30593 +0.19511 +0.1824 +0.23275 +0.24398 +0.24564 +0.26979 +0.30368 +0.21729 +0.23075 +0.1813 +0.17471 +0.2152 +0.17647 +0.18225 +0.19538 +0.20119 +0.19847 +0.23092 +0.23964 +0.29673 +0.33106 +0.38179 +0.10608 +0.018184 +0.081992 +0.047596 +0.18371 +0.23504 +0.24237 +0.22797 +0.2866 +0.25502 +0.29063 +0.15591 +0.27259 +0.18885 +0.26391 +0.15195 +0.13953 +0.12885 +0.051643 +0.0001 +0.072308 +0.0001 +0.0001 +0.0001 +0.0001 +0.0001 +0.005985 +0.027867 +0.0001 +0.25875 +0.2488 +0.19152 +0.26092 +0.3205 +0.31746 +0.2901 +0.32293 +0.29079 +0.22342 +0.20278 +0.23645 +0.24891 +0.26711 +0.25755 +0.30588 +0.28542 +0.25626 +0.17598 +0.23697 +0.28373 +0.17629 +0.1848 +0.20618 +0.20496 +0.23153 +0.19995 +0.21735 +0.31059 +0.33479 +0.36362 +0.087186 +0.030154 +0.066402 +0.05737 +0.071445 +0.23614 +0.26911 +0.27248 +0.25073 +0.26893 +0.2708 +0.24624 +0.26545 +0.19437 +0.16048 +0.10146 +0.11496 +0.097755 +0.05851 +0.0001 +0.0001 +0.006804 +0.0001 +0.001876 +0.0001 +0.070518 +0.052865 +0.11264 +0.014908 +0.22628 +0.25258 +0.21814 +0.28655 +0.30171 +0.29955 +0.28739 +0.34138 +0.27502 +0.21804 +0.27962 +0.25264 +0.23293 +0.2863 +0.27134 +0.29662 +0.28015 +0.30121 +0.12845 +0.18911 +0.051587 +0.18027 +0.18904 +0.20402 +0.22043 +0.22234 +0.21802 +0.1991 +0.28231 +0.33337 +0.29079 +0.16553 +0.07598 +0.10403 +0.080855 +0.3167 +0.25294 +0.28562 +0.25733 +0.28685 +0.28472 +0.29522 +0.24568 +0.22926 +0.20886 +0.1354 +0.13887 +0.14414 +0.009986 +0.0001 +0.080849 +0.067292 +0.03823 +0.0001 +0.0001 +0.0001 +0.074944 +0.04885 +0.03186 +0.0001 +0.081826 +0.24257 +0.18354 +0.30815 +0.29907 +0.26455 +0.30281 +0.34312 +0.25762 +0.27711 +0.26135 +0.22398 +0.2019 +0.26909 +0.24453 +0.28954 +0.23247 +0.29752 +0.14778 +0.15893 +0.28118 +0.19646 +0.17682 +0.18827 +0.22512 +0.21929 +0.24672 +0.18398 +0.2041 +0.30816 +0.11184 +0.070765 +0.088249 +0.27621 +0.31778 +0.33638 +0.2773 +0.29546 +0.27734 +0.32535 +0.2858 +0.28232 +0.27387 +0.25118 +0.20735 +0.15208 +0.16973 +0.14876 +0.050128 +0.0001 +0.034826 +0.011028 +0.077587 +0.034525 +0.0001 +0.038644 +0.044388 +0.004961 +0.026902 +0.07576 +0.07605 +0.21108 +0.2402 +0.30414 +0.32406 +0.30355 +0.28924 +0.33452 +0.27247 +0.31086 +0.26866 +0.24419 +0.21772 +0.23283 +0.27389 +0.30248 +0.28919 +0.32221 +0.1777 +0.17083 +0.27526 +0.18827 +0.15998 +0.19018 +0.20706 +0.21665 +0.21537 +0.18636 +0.2882 +0.17078 +0.12294 +0.16989 +0.1481 +0.19458 +0.30216 +0.359 +0.31436 +0.28752 +0.31068 +0.3309 +0.27946 +0.29699 +0.3178 +0.27343 +0.1205 +0.17764 +0.1554 +0.19332 +0.054331 +0.056932 +0.061188 +0.0001 +0.16791 +0.091535 +0.08396 +0.10949 +0.070497 +0.013188 +0.027548 +0.067041 +0.14173 +0.23489 +0.24879 +0.33234 +0.32872 +0.24155 +0.29144 +0.25145 +0.29665 +0.30186 +0.30943 +0.24495 +0.24968 +0.28791 +0.30473 +0.3266 +0.31889 +0.30978 +0.13881 +0.16643 +0.19489 +0.18201 +0.14985 +0.19235 +0.20967 +0.17452 +0.20626 +0.23833 +0.16819 +0.15984 +0.15343 +0.17171 +0.2128 +0.18595 +0.1684 +0.2934 +0.32198 +0.30572 +0.29412 +0.34822 +0.26227 +0.3553 +0.31107 +0.25656 +0.14921 +0.16009 +0.10974 +0.16107 +0.16339 +0.060206 +0.0001 +0.053708 +0.13472 +0.15432 +0.12171 +0.025864 +0.032614 +0.009746 +0.19148 +0.14156 +0.12162 +0.31482 +0.25726 +0.31641 +0.35334 +0.21475 +0.22858 +0.2511 +0.2788 +0.30386 +0.29772 +0.28017 +0.24963 +0.28739 +0.31394 +0.2797 +0.30876 +0.19847 +0.1982 +0.15565 +0.17286 +0.13393 +0.1521 +0.20934 +0.23767 +0.24416 +0.15857 +0.15984 +0.12002 +0.14416 +0.094814 +0.064311 +0.17778 +0.19445 +0.21154 +0.26337 +0.23861 +0.28817 +0.28363 +0.34522 +0.28094 +0.33857 +0.31217 +0.24244 +0.19934 +0.13258 +0.14411 +0.18475 +0.050194 +0.089566 +0.052573 +0.0001 +0.1357 +0.052982 +0.0446 +0.025445 +0.041909 +0.0001 +0.19426 +0.14239 +0.1149 +0.32764 +0.29597 +0.31667 +0.23711 +0.20728 +0.20896 +0.31199 +0.25911 +0.31134 +0.32957 +0.2998 +0.2423 +0.24789 +0.31608 +0.098496 +0.22101 +0.23044 +0.19412 +0.16428 +0.14142 +0.12819 +0.28446 +0.2635 +0.29773 +0.13856 +0.10652 +0.11237 +0.033263 +0.031417 +0.045448 +0.13475 +0.17662 +0.20358 +0.23768 +0.27669 +0.2798 +0.25846 +0.26849 +0.30657 +0.28385 +0.32607 +0.32995 +0.27066 +0.27291 +0.1525 +0.17556 +0.16907 +0.04417 +0.034132 +0.0001 +0.067155 +0.098877 +0.077875 +0.046499 +0.062144 +0.055863 +0.13743 +0.16907 +0.13045 +0.12202 +0.31492 +0.25463 +0.2436 +0.16256 +0.22749 +0.22138 +0.30485 +0.25246 +0.2516 +0.32752 +0.31435 +0.28921 +0.21072 +0.19212 +0.22939 +0.26285 +0.23354 +0.19249 +0.12495 +0.092335 +0.30225 +0.30357 +0.32095 +0.093637 +0.11175 +0.16081 +0.14909 +0.091323 +0.085959 +0.04998 +0.15761 +0.20306 +0.23727 +0.27181 +0.25474 +0.31424 +0.27445 +0.25919 +0.35315 +0.33285 +0.32889 +0.32292 +0.29963 +0.27756 +0.16872 +0.17281 +0.17277 +0.16805 +0.015677 +0.0001 +0.0001 +0.09449 +0.083793 +0.0001 +0.047099 +0.035606 +0.14588 +0.18436 +0.079748 +0.3449 +0.2243 +0.25712 +0.13837 +0.15181 +0.21338 +0.24365 +0.27458 +0.27349 +0.25826 +0.27268 +0.29352 +0.21063 +0.21707 +0.19804 +0.25614 +0.26193 +0.22837 +0.1977 +0.12163 +0.30265 +0.32739 +0.3475 +0.31538 +0.29333 +0.10499 +0.026614 +0.08398 +0.022836 +0.11325 +0.19076 +0.17604 +0.17676 +0.14413 +0.26228 +0.22259 +0.14542 +0.28981 +0.24488 +0.34039 +0.34693 +0.31971 +0.31935 +0.26912 +0.24051 +0.18752 +0.1919 +0.19607 +0.20747 +0.003679 +0.0001 +0.072966 +0.071298 +0.043246 +0.03699 +0.044603 +0.081175 +0.098329 +0.18337 +0.23969 +0.22628 +0.21953 +0.17331 +0.1441 +0.13729 +0.23311 +0.26271 +0.30316 +0.29423 +0.22032 +0.15325 +0.24205 +0.18401 +0.22027 +0.24523 +0.22286 +0.24453 +0.0001 +0.087602 +0.15772 +0.24802 +0.29448 +0.35167 +0.29712 +0.25612 +0.22359 +0.020517 +0.053437 +0.047175 +0.21869 +0.14682 +0.15199 +0.13631 +0.11742 +0.22104 +0.21634 +0.25294 +0.30156 +0.25565 +0.30934 +0.33087 +0.29057 +0.31017 +0.2666 +0.26839 +0.084706 +0.21538 +0.19462 +0.23044 +0.18659 +0.034035 +0.14086 +0.071406 +0.062694 +0.0001 +0.075614 +0.067167 +0.21319 +0.21287 +0.23204 +0.20098 +0.23554 +0.15628 +0.13093 +0.16592 +0.20322 +0.27761 +0.39852 +0.20096 +0.13911 +0.14864 +0.19107 +0.16697 +0.20589 +0.21708 +0.24335 +0.067106 +0.06271 +0.073416 +0.092414 +0.13122 +0.35003 +0.32725 +0.29247 +0.22187 +0.18845 +0.2504 +0.20551 +0.22408 +0.087324 +0.19959 +0.11391 +0.10245 +0.12789 +0.092792 +0.24813 +0.22563 +0.26434 +0.25615 +0.31542 +0.32592 +0.34396 +0.14777 +0.25178 +0.21003 +0.24589 +0.24942 +0.18758 +0.25701 +0.049753 +0.012287 +0.046969 +0.068903 +0.095211 +0.04488 +0.19584 +0.15689 +0.20395 +0.1968 +0.2637 +0.25327 +0.21208 +0.19631 +0.1639 +0.16356 +0.21838 +0.38263 +0.26021 +0.23605 +0.16267 +0.16193 +0.20953 +0.14223 +0.22181 +0.22799 +0.08756 +0.090148 +0.092668 +0.13389 +0.11126 +0.34415 +0.32496 +0.27789 +0.27933 +0.20722 +0.21127 +0.24402 +0.20835 +0.20495 +0.112 +0.19857 +0.088791 +0.24074 +0.27931 +0.23514 +0.26449 +0.2571 +0.23298 +0.24244 +0.29557 +0.32074 +0.15557 +0.16841 +0.24854 +0.2085 +0.27172 +0.26557 +0.22129 +0.18874 +0.086693 +0.029134 +0.085302 +0.057845 +0.037879 +0.2067 +0.18924 +0.17729 +0.20633 +0.18462 +0.26222 +0.26171 +0.21055 +0.18924 +0.152 +0.18516 +0.21091 +0.26299 +0.23133 +0.24257 +0.18138 +0.15296 +0.19497 +0.16595 +0.28456 +0.26654 +0.0287 +0.024338 +0.11296 +0.10896 +0.16627 +0.36135 +0.31167 +0.31521 +0.24404 +0.22256 +0.2042 +0.20888 +0.18672 +0.23215 +0.056375 +0.21999 +0.25521 +0.25278 +0.2566 +0.2308 +0.28332 +0.32336 +0.24667 +0.18331 +0.14852 +0.21851 +0.19978 +0.21283 +0.26617 +0.24387 +0.24661 +0.22957 +0.19173 +0.21105 +0.053662 +0.05167 +0.02529 +0.018703 +0.13095 +0.18954 +0.20248 +0.20137 +0.17487 +0.27187 +0.28391 +0.22688 +0.21766 +0.18249 +0.1626 +0.25895 +0.25081 +0.25089 +0.25742 +0.23688 +0.21704 +0.17049 +0.22496 +0.17811 +0.24894 +0.25911 +0.24896 +0.24702 +0.10899 +0.074245 +0.12287 +0.34779 +0.29966 +0.32185 +0.23101 +0.18704 +0.18943 +0.18892 +0.19453 +0.29709 +0.043789 +0.19458 +0.26744 +0.26134 +0.2705 +0.23991 +0.2814 +0.27772 +0.21834 +0.16737 +0.14615 +0.18008 +0.19885 +0.16889 +0.29946 +0.27367 +0.28147 +0.2315 +0.19404 +0.24925 +0.034418 +0.037383 +0.017661 +0.10497 +0.14641 +0.19174 +0.20523 +0.205 +0.29813 +0.27195 +0.29039 +0.23231 +0.21304 +0.4 +0.4 +0.3448 +0.23543 +0.23591 +0.25138 +0.2411 +0.23131 +0.17975 +0.21285 +0.23904 +0.27331 +0.2381 +0.26604 +0.22419 +0.27202 +0.35568 +0.32165 +0.36139 +0.29242 +0.32134 +0.21076 +0.16337 +0.1418 +0.17958 +0.1319 +0.25865 +0.28248 +0.21803 +0.24626 +0.24116 +0.2477 +0.26382 +0.28526 +0.10659 +0.18006 +0.1613 +0.16997 +0.17571 +0.2015 +0.18143 +0.16953 +0.21144 +0.25047 +0.20308 +0.19818 +0.26661 +0.25005 +0.017859 +0.030581 +0.078818 +0.18609 +0.22136 +0.2292 +0.30079 +0.29385 +0.27554 +0.30769 +0.25162 +0.21941 +0.39643 +0.4 +0.047016 +0.24493 +0.28149 +0.28355 +0.21548 +0.26386 +0.22405 +0.23939 +0.31656 +0.24744 +0.21628 +0.25944 +0.28484 +0.28022 +0.28058 +0.31127 +0.37392 +0.27804 +0.30614 +0.21101 +0.19464 +0.11428 +0.13765 +0.098941 +0.25903 +0.24635 +0.20678 +0.22652 +0.23299 +0.26128 +0.27386 +0.25641 +0.067472 +0.23294 +0.17674 +0.14796 +0.13819 +0.15411 +0.20071 +0.20398 +0.21953 +0.21965 +0.2366 +0.22207 +0.21318 +0.20292 +0.006321 +0.030436 +0.075066 +0.18335 +0.21595 +0.38368 +0.30882 +0.28692 +0.28104 +0.2895 +0.23942 +0.3755 +0.3945 +0.4 +0.29212 +0.26311 +0.288 +0.30734 +0.21584 +0.26877 +0.25138 +0.23474 +0.24417 +0.32055 +0.22133 +0.28886 +0.3033 +0.29913 +0.2865 +0.31439 +0.35961 +0.25312 +0.24246 +0.20245 +0.14077 +0.098576 +0.10224 +0.11394 +0.21379 +0.2224 +0.26003 +0.25662 +0.20952 +0.29311 +0.29167 +0.27414 +0.13399 +0.076921 +0.2857 +0.24506 +0.17808 +0.1948 +0.21611 +0.20055 +0.2268 +0.21103 +0.22974 +0.30681 +0.24758 +0.1953 +0.091409 +0.017087 +0.007714 +0.045374 +0.02452 +0.32963 +0.33364 +0.27676 +0.27524 +0.29926 +0.2581 +0.4 +0.4 +0.14627 +0.18862 +0.2203 +0.27478 +0.2908 +0.23272 +0.24928 +0.29461 +0.19285 +0.25438 +0.26072 +0.30427 +0.31159 +0.30925 +0.3045 +0.2543 +0.23214 +0.30278 +0.22541 +0.23112 +0.18214 +0.15211 +0.096871 +0.035652 +0.093517 +0.24054 +0.2291 +0.24663 +0.24495 +0.26303 +0.27021 +0.28161 +0.33401 +0.11067 +0.23523 +0.3041 +0.27642 +0.178 +0.20215 +0.24052 +0.23652 +0.21892 +0.22486 +0.22565 +0.28066 +0.26194 +0.23967 +0.2094 +0.00248 +0.045017 +0.010783 +0.006673 +0.29719 +0.33431 +0.26478 +0.26149 +0.27595 +0.25704 +0.4 +0.10738 +0.2313 +0.21295 +0.19531 +0.2496 +0.26332 +0.25489 +0.24888 +0.28269 +0.24476 +0.23223 +0.25505 +0.3243 +0.29292 +0.32671 +0.28146 +0.27326 +0.23984 +0.24859 +0.19739 +0.22727 +0.20549 +0.029398 +0.076496 +0.023826 +0.096118 +0.2333 +0.24789 +0.2636 +0.27897 +0.23903 +0.26 +0.2831 +0.32731 +0.30832 +0.20749 +0.29727 +0.29093 +0.20627 +0.19018 +0.20584 +0.21035 +0.21035 +0.18774 +0.24703 +0.28964 +0.27332 +0.2852 +0.26675 +0.097157 +0.042568 +0.008071 +0.31861 +0.31218 +0.34114 +0.28003 +0.28214 +0.26952 +0.26869 +0.006735 +0.055219 +0.2564 +0.24955 +0.21979 +0.24283 +0.2571 +0.2514 +0.22965 +0.23312 +0.23659 +0.22953 +0.28769 +0.30884 +0.31593 +0.31773 +0.29405 +0.27928 +0.24918 +0.22334 +0.28235 +0.27652 +0.31673 +0.1092 +0.11691 +0.090965 +0.10025 +0.12593 +0.21331 +0.27342 +0.2619 +0.22712 +0.28301 +0.31932 +0.29487 +0.29475 +0.25309 +0.26206 +0.27239 +0.21437 +0.24296 +0.20515 +0.18846 +0.18714 +0.12023 +0.23288 +0.26303 +0.2702 +0.30249 +0.23947 +0.081555 +0.064549 +0.0204 +0.31974 +0.30814 +0.32797 +0.28493 +0.29444 +0.29767 +0.25602 +0.26028 +0.25636 +0.22657 +0.26055 +0.19799 +0.24261 +0.24358 +0.22769 +0.19887 +0.2135 +0.26936 +0.25891 +0.3156 +0.34067 +0.3133 +0.31121 +0.28403 +0.30229 +0.29076 +0.28667 +0.29142 +0.4 +0.32354 +0.34565 +0.19808 +0.036125 +0.058602 +0.13906 +0.11797 +0.22714 +0.24091 +0.26467 +0.31026 +0.26048 +0.27752 +0.29 +0.26834 +0.24479 +0.28058 +0.19983 +0.24435 +0.20189 +0.20159 +0.17453 +0.16337 +0.23936 +0.26812 +0.26809 +0.31368 +0.27127 +0.043633 +0.021766 +0.29731 +0.30938 +0.29331 +0.33714 +0.28315 +0.3072 +0.31396 +0.05465 +0.012599 +0.0001 +0.26746 +0.26699 +0.23434 +0.2375 +0.22386 +0.20416 +0.22664 +0.20159 +0.24848 +0.25828 +0.31669 +0.016202 +0.1136 +0.068726 +0.34758 +0.31373 +0.34034 +0.31345 +0.29678 +0.34356 +0.30169 +0.32571 +0.19062 +0.10621 +0.075608 +0.21939 +0.19553 +0.10162 +0.20334 +0.22523 +0.29596 +0.35228 +0.36534 +0.26102 +0.29072 +0.25639 +0.27388 +0.21976 +0.12003 +0.15876 +0.1807 +0.19386 +0.16754 +0.25345 +0.27147 +0.27082 +0.25633 +0.081143 +0.056464 +0.014912 +0.29201 +0.29092 +0.34848 +0.31763 +0.2428 +0.27389 +0.28645 +0.30355 +0.30286 +0.2922 +0.26875 +0.14481 +0.16102 +0.25781 +0.20401 +0.18063 +0.20947 +0.24833 +0.098071 +0.091034 +0.082563 +0.028833 +0.0989 +0.10948 +0.3558 +0.3052 +0.32302 +0.3136 +0.3061 +0.31651 +0.28824 +0.21498 +0.15643 +0.10286 +0.081703 +0.055777 +0.17335 +0.12247 +0.19412 +0.21485 +0.24904 +0.33851 +0.3672 +0.09568 +0.26369 +0.26104 +0.27237 +0.23173 +0.26496 +0.15727 +0.25466 +0.17182 +0.2623 +0.24636 +0.14435 +0.30225 +0.279 +0.076694 +0.10123 +0.028 +0.25759 +0.31831 +0.34859 +0.2871 +0.26486 +0.27389 +0.25651 +0.28638 +0.30722 +0.22999 +0.2594 +0.14305 +0.15469 +0.15022 +0.22441 +0.20522 +0.20954 +0.17693 +0.1978 +0.084024 +0.086915 +0.045192 +0.077185 +0.37448 +0.34013 +0.29198 +0.2892 +0.32692 +0.28909 +0.18446 +0.13796 +0.2168 +0.13326 +0.13763 +0.051351 +0.01927 +0.17964 +0.1236 +0.2139 +0.23372 +0.27885 +0.29561 +0.31769 +0.077102 +0.11542 +0.26656 +0.25157 +0.22387 +0.18871 +0.17841 +0.30073 +0.20672 +0.27374 +0.21642 +0.13691 +0.19986 +0.082679 +0.10829 +0.16663 +0.092455 +0.097502 +0.3167 +0.31017 +0.23583 +0.21611 +0.25562 +0.25394 +0.27847 +0.2226 +0.21625 +0.1114 +0.13119 +0.13707 +0.18777 +0.23277 +0.20522 +0.21609 +0.19716 +0.1812 +0.11431 +0.14303 +0.13791 +0.28143 +0.35371 +0.31263 +0.29535 +0.28204 +0.32106 +0.19965 +0.20201 +0.15473 +0.24655 +0.0899 +0.083905 +0.066346 +0.16877 +0.22079 +0.17325 +0.20788 +0.27316 +0.26226 +0.30695 +0.28266 +0.26662 +0.083303 +0.091174 +0.11396 +0.23911 +0.20872 +0.1797 +0.22831 +0.21094 +0.2431 +0.2018 +0.16581 +0.22929 +0.2105 +0.031466 +0.12363 +0.092589 +0.089922 +0.084199 +0.3053 +0.24628 +0.24657 +0.24077 +0.2214 +0.25924 +0.32168 +0.18366 +0.085103 +0.1377 +0.12929 +0.22355 +0.17751 +0.20489 +0.21126 +0.19542 +0.16451 +0.054968 +0.086922 +0.10119 +0.28702 +0.27804 +0.30247 +0.3346 +0.27361 +0.2698 +0.19559 +0.17044 +0.16835 +0.13687 +0.11449 +0.086673 +0.069108 +0.002944 +0.068049 +0.007845 +0.014521 +0.23533 +0.31136 +0.32044 +0.31252 +0.056843 +0.10284 +0.12088 +0.12196 +0.1422 +0.22515 +0.21169 +0.23317 +0.24449 +0.20607 +0.18929 +0.20833 +0.21431 +0.20771 +0.18218 +0.014586 +0.13555 +0.052188 +0.082258 +0.040066 +0.2567 +0.24183 +0.2178 +0.19545 +0.23428 +0.35245 +0.083664 +0.10035 +0.18412 +0.14143 +0.22079 +0.23889 +0.098177 +0.21517 +0.20826 +0.17328 +0.17315 +0.14596 +0.15469 +0.27524 +0.29116 +0.32753 +0.32388 +0.27158 +0.2671 +0.20483 +0.18801 +0.20596 +0.13826 +0.10484 +0.053727 +0.063851 +0.016286 +0.065766 +0.031666 +0.26633 +0.22208 +0.31261 +0.29305 +0.31183 +0.094262 +0.11605 +0.098205 +0.069263 +0.16164 +0.2519 +0.22935 +0.26344 +0.21489 +0.24802 +0.28017 +0.19843 +0.18363 +0.2141 +0.18773 +0.064623 +0.12902 +0.078184 +0.14031 +0.0696 +0.25476 +0.24859 +0.23035 +0.19212 +0.25487 +0.12276 +0.087565 +0.098042 +0.18444 +0.24767 +0.24053 +0.22514 +0.22817 +0.2116 +0.18296 +0.19157 +0.1718 +0.13336 +0.26507 +0.29231 +0.31178 +0.33357 +0.31769 +0.24421 +0.27386 +0.25738 +0.16264 +0.19734 +0.16262 +0.19549 +0.049407 +0.079647 +0.087119 +0.070552 +0.28275 +0.26086 +0.26084 +0.31457 +0.28909 +0.15123 +0.099557 +0.1194 +0.12986 +0.092013 +0.15762 +0.15558 +0.20126 +0.27023 +0.23065 +0.24185 +0.25588 +0.18441 +0.19626 +0.24066 +0.22324 +0.22888 +0.15123 +0.075641 +0.064029 +0.28492 +0.22978 +0.22799 +0.20054 +0.20308 +0.15561 +0.13939 +0.061793 +0.10863 +0.14261 +0.088394 +0.2338 +0.21479 +0.23256 +0.27003 +0.13673 +0.1689 +0.17307 +0.14233 +0.21185 +0.32149 +0.313 +0.31716 +0.30112 +0.21186 +0.27956 +0.30279 +0.085802 +0.10403 +0.094659 +0.23874 +0.23569 +0.30412 +0.073385 +0.26287 +0.28129 +0.29543 +0.28426 +0.32248 +0.17459 +0.12214 +0.1187 +0.14666 +0.12738 +0.1105 +0.12169 +0.23954 +0.20202 +0.27131 +0.22027 +0.25172 +0.25131 +0.18255 +0.17622 +0.25068 +0.25638 +0.23403 +0.095813 +0.13217 +0.064883 +0.29257 +0.23388 +0.20785 +0.21051 +0.20017 +0.18939 +0.16653 +0.087574 +0.10292 +0.12878 +0.26211 +0.083898 +0.22448 +0.25798 +0.27864 +0.20063 +0.21384 +0.15814 +0.14121 +0.18897 +0.17827 +0.29653 +0.30635 +0.279 +0.23827 +0.27893 +0.046515 +0.032458 +0.065623 +0.054977 +0.065821 +0.047548 +0.21878 +0.25976 +0.26368 +0.27696 +0.29676 +0.30315 +0.18983 +0.15763 +0.14336 +0.15299 +0.14599 +0.096271 +0.11912 +0.11959 +0.23745 +0.22432 +0.27318 +0.23952 +0.29809 +0.19592 +0.14618 +0.16354 +0.23049 +0.21174 +0.1864 +0.053284 +0.12552 +0.046438 +0.031388 +0.22076 +0.24572 +0.17056 +0.20181 +0.26517 +0.1773 +0.1013 +0.12713 +0.11771 +0.25963 +0.14345 +0.21099 +0.23197 +0.29583 +0.23913 +0.218 +0.15451 +0.16556 +0.17206 +0.17204 +0.19764 +0.30542 +0.31656 +0.042994 +0.000147 +0.077125 +0.084085 +0.095198 +0.12019 +0.2119 +0.28252 +0.27114 +0.24691 +0.26319 +0.24483 +0.29102 +0.13386 +0.23801 +0.17861 +0.13598 +0.10609 +0.16506 +0.19449 +0.16101 +0.1784 +0.23802 +0.22863 +0.30385 +0.26975 +0.32831 +0.14902 +0.12698 +0.15275 +0.21942 +0.18208 +0.1911 +0.13022 +0.1897 +0.14409 +0.10175 +0.22055 +0.26875 +0.13488 +0.16164 +0.2525 +0.20101 +0.096487 +0.13019 +0.14032 +0.14708 +0.16769 +0.19181 +0.30358 +0.33797 +0.2102 +0.21273 +0.15288 +0.15518 +0.14013 +0.16392 +0.19431 +0.26858 +0.31611 +0.046188 +0.077057 +0.003404 +0.10452 +0.071477 +0.083193 +0.2151 +0.2728 +0.28384 +0.25278 +0.27487 +0.24482 +0.088406 +0.11973 +0.16336 +0.15093 +0.12935 +0.20052 +0.22876 +0.15297 +0.12891 +0.21335 +0.24727 +0.24616 +0.2957 +0.16886 +0.17747 +0.20554 +0.2296 +0.20084 +0.23274 +0.18512 +0.20799 +0.12611 +0.20576 +0.064093 +0.19002 +0.095039 +0.2346 +0.17016 +0.1592 +0.21208 +0.20752 +0.13111 +0.15532 +0.12011 +0.098487 +0.20601 +0.18895 +0.29634 +0.34363 +0.23533 +0.21113 +0.12205 +0.14691 +0.14626 +0.17167 +0.22851 +0.27012 +0.074933 +0.08329 +0.10239 +0.072974 +0.05905 +0.057822 +0.053536 +0.23904 +0.24827 +0.25313 +0.23236 +0.28224 +0.25388 +0.10178 +0.1295 +0.17638 +0.1244 +0.26935 +0.21239 +0.18475 +0.1296 +0.16571 +0.21514 +0.29508 +0.22163 +0.1632 +0.17889 +0.17143 +0.21546 +0.21496 +0.19425 +0.20474 +0.20564 +0.17379 +0.093217 +0.094519 +0.09192 +0.097936 +0.091912 +0.1261 +0.26389 +0.25463 +0.22769 +0.18602 +0.10681 +0.1669 +0.12764 +0.16117 +0.16635 +0.24092 +0.28877 +0.30797 +0.2388 +0.22717 +0.15756 +0.13185 +0.14286 +0.16151 +0.25505 +0.03557 +0.046495 +0.041428 +0.096275 +0.059219 +0.096895 +0.083487 +0.06353 +0.23659 +0.24344 +0.26442 +0.26065 +0.28853 +0.29482 +0.10383 +0.080952 +0.15687 +0.23894 +0.25151 +0.17236 +0.2134 +0.11349 +0.20341 +0.21174 +0.17851 +0.2246 +0.17763 +0.16385 +0.18488 +0.18491 +0.205 +0.18103 +0.20671 +0.21158 +0.14698 +0.072233 +0.11765 +0.12075 +0.16967 +0.11098 +0.10723 +0.12845 +0.26301 +0.24242 +0.1755 +0.092289 +0.16012 +0.14319 +0.21861 +0.29519 +0.29142 +0.28745 +0.27127 +0.22712 +0.19577 +0.18603 +0.13579 +0.15429 +0.16119 +0.25314 +0.030203 +0.0001 +0.0001 +0.0001 +0.052339 +0.0001 +0.018935 +0.036917 +0.25994 +0.22804 +0.25252 +0.28632 +0.28402 +0.32636 +0.29841 +0.32055 +0.2883 +0.22363 +0.27891 +0.22788 +0.23199 +0.21374 +0.24341 +0.26612 +0.22529 +0.25968 +0.17878 +0.12166 +0.15129 +0.15755 +0.20362 +0.19013 +0.24777 +0.21377 +0.15088 +0.10916 +0.070344 +0.15543 +0.11059 +0.06317 +0.016983 +0.054128 +0.16187 +0.24075 +0.16873 +0.099508 +0.176 +0.15558 +0.19586 +0.26644 +0.26509 +0.26515 +0.24192 +0.25092 +0.19445 +0.16615 +0.1443 +0.15097 +0.4 +0.050793 +0.0001 +0.0001 +0.037539 +0.0001 +0.023289 +0.013406 +0.0001 +0.064131 +0.24743 +0.22155 +0.25336 +0.31358 +0.31793 +0.32508 +0.0001 +0.30118 +0.21063 +0.20602 +0.20475 +0.22788 +0.22989 +0.2422 +0.27088 +0.28137 +0.25716 +0.24158 +0.18896 +0.11899 +0.17409 +0.16944 +0.17275 +0.25952 +0.25722 +0.22296 +0.23496 +0.046716 +0.080206 +0.08876 +0.093027 +0.037702 +0.084354 +0.052063 +0.095014 +0.20143 +0.19461 +0.14241 +0.14912 +0.14017 +0.20355 +0.26482 +0.23254 +0.255 +0.26498 +0.23289 +0.19567 +0.18972 +0.14169 +0.15979 +0.24246 +0.061739 +0.0001 +0.0001 +0.012745 +0.0001 +0.079492 +0.03652 +0.019247 +0.07367 +0.037929 +0.2184 +0.23286 +0.27831 +0.32664 +0.35599 +0.19076 +0.20814 +0.191 +0.24925 +0.24446 +0.25374 +0.27011 +0.24379 +0.24946 +0.22216 +0.23014 +0.21152 +0.17958 +0.24748 +0.2058 +0.26758 +0.23783 +0.2333 +0.22693 +0.22484 +0.24167 +0.037132 +0.05674 +0.10511 +0.028577 +0.076518 +0.080267 +0.079771 +0.11799 +0.12394 +0.16427 +0.1854 +0.11265 +0.18283 +0.21935 +0.23281 +0.18915 +0.21811 +0.26164 +0.22104 +0.20953 +0.18265 +0.14932 +0.18862 +0.3689 +0.022118 +0.046295 +0.062074 +0.032405 +0.041157 +0.027545 +0.0001 +0.0001 +0.014017 +0.044028 +0.22839 +0.23023 +0.22977 +0.28 +0.22612 +0.1596 +0.16995 +0.17095 +0.216 +0.26373 +0.25878 +0.23948 +0.22665 +0.23087 +0.20441 +0.32306 +0.12777 +0.1149 +0.25606 +0.25804 +0.2395 +0.27683 +0.2388 +0.24187 +0.22113 +0.24427 +0.020691 +0.040923 +0.10343 +0.031327 +0.054625 +0.085436 +0.097843 +0.10204 +0.049736 +0.11952 +0.19425 +0.15325 +0.12893 +0.21194 +0.19078 +0.19394 +0.21213 +0.25362 +0.18778 +0.19634 +0.17239 +0.15466 +0.37613 +0.24195 +0.0001 +0.0001 +0.055294 +0.071467 +0.056592 +0.09991 +0.02871 +0.0001 +0.052694 +0.080763 +0.15206 +0.27362 +0.23136 +0.23279 +0.23179 +0.14891 +0.18004 +0.186 +0.21812 +0.2278 +0.24863 +0.2724 +0.30697 +0.16974 +0.23966 +0.24238 +0.27306 +0.22909 +0.2516 +0.27875 +0.24464 +0.26187 +0.22552 +0.22814 +0.18788 +0.13856 +0.038469 +0.002273 +0.035782 +0.018399 +0.018585 +0.0001 +0.0001 +0.049791 +0.015055 +0.20656 +0.16892 +0.11895 +0.15243 +0.25465 +0.23327 +0.1796 +0.21116 +0.26658 +0.18102 +0.17008 +0.13899 +0.17757 +0.4 +0.22628 +0.023349 +0.0001 +0.094172 +0.028391 +0.059726 +0.068894 +0.093381 +0.10515 +0.090646 +0.13027 +0.090007 +0.20928 +0.23751 +0.21994 +0.22845 +0.17561 +0.17254 +0.21207 +0.23516 +0.31735 +0.28455 +0.2321 +0.31494 +0.32972 +0.29779 +0.23841 +0.2253 +0.18837 +0.16151 +0.13898 +0.26537 +0.034312 +0.0001 +0.0001 +0.13423 +0.097243 +0.002441 +0.018456 +0.055661 +0.076011 +0.051104 +0.07243 +0.055122 +0.009525 +0.0001 +0.0001 +0.16246 +0.16637 +0.17144 +0.18243 +0.27797 +0.16942 +0.21604 +0.23584 +0.17073 +0.15382 +0.14803 +0.22002 +0.17974 +0.19438 +0.064574 +0.072249 +0.046417 +0.082649 +0.046515 +0.098781 +0.1706 +0.14814 +0.015741 +0.086318 +0.13511 +0.19703 +0.25173 +0.26932 +0.22631 +0.17698 +0.20235 +0.226 +0.24129 +0.2981 +0.26168 +0.23722 +0.30216 +0.32215 +0.30608 +0.23157 +0.25102 +0.18502 +0.1613 +0.18307 +0.1628 +0.06706 +0.054463 +0.001054 +0.094866 +0.10683 +0.053044 +0.061425 +0.054795 +0.043356 +0.18374 +0.18641 +0.17502 +0.22577 +0.28127 +0.1839 +0.15347 +0.15922 +0.1841 +0.16709 +0.2368 +0.14039 +0.20187 +0.21868 +0.17494 +0.12098 +0.15094 +0.21316 +0.18335 +0.045068 +0.064763 +0.07554 +0.13977 +0.11553 +0.11338 +0.11597 +0.071255 +0.024764 +0.044824 +0.19585 +0.16463 +0.247 +0.22862 +0.25817 +0.2245 +0.21622 +0.20251 +0.24216 +0.20247 +0.22412 +0.27356 +0.28787 +0.33689 +0.30879 +0.32545 +0.30817 +0.22742 +0.27015 +0.14347 +0.17558 +0.17963 +0.29229 +0.2756 +0.061025 +0.073354 +0.10966 +0.046027 +0.048752 +0.071142 +0.13692 +0.20135 +0.19967 +0.18561 +0.37023 +0.34025 +0.27305 +0.16734 +0.13728 +0.16403 +0.15646 +0.1705 +0.1316 +0.18052 +0.19719 +0.15509 +0.10659 +0.18327 +0.19173 +0.21168 +0.22705 +0.09091 +0.060255 +0.094316 +0.063134 +0.052686 +0.064015 +0.13123 +0.12196 +0.045882 +0.17396 +0.15262 +0.19519 +0.22385 +0.24342 +0.19457 +0.19809 +0.20262 +0.18702 +0.18431 +0.19998 +0.22803 +0.29558 +0.31222 +0.29588 +0.2988 +0.009865 +0.25616 +0.31589 +0.23475 +0.22536 +0.2024 +0.27138 +0.29094 +0.28662 +0.10042 +0.15309 +0.030233 +0.17627 +0.091669 +0.14821 +0.1656 +0.1939 +0.070953 +0.38905 +0.31039 +0.26322 +0.15179 +0.09915 +0.14261 +0.12145 +0.15094 +0.13159 +0.17393 +0.18959 +0.15126 +0.11785 +0.16487 +0.15188 +0.21893 +0.17532 +0.18637 +0.073998 +0.036434 +0.0921 +0.043843 +0.11805 +0.17503 +0.13609 +0.1255 +0.17022 +0.18945 +0.22021 +0.21423 +0.26198 +0.16251 +0.2165 +0.16468 +0.1937 +0.22932 +0.21713 +0.21172 +0.23769 +0.32217 +0.29405 +0.29564 +0.18622 +0.31206 +0.32443 +0.27198 +0.27749 +0.23396 +0.30439 +0.28482 +0.27926 +0.2454 +0.089182 +0.1609 +0.18716 +0.13457 +0.17468 +0.13789 +0.081937 +0.10106 +0.38053 +0.34358 +0.27914 +0.16434 +0.13938 +0.15618 +0.12428 +0.15232 +0.12485 +0.18895 +0.29171 +0.12882 +0.14556 +0.15879 +0.14242 +0.23513 +0.15862 +0.18322 +0.19237 +0.21895 +0.11215 +0.15442 +0.099487 +0.1472 +0.12117 +0.12717 +0.16074 +0.14495 +0.18479 +0.2321 +0.31448 +0.31873 +0.31561 +0.29806 +0.23007 +0.23415 +0.24007 +0.2518 +0.23758 +0.33456 +0.27139 +0.25773 +0.20924 +0.32742 +0.26808 +0.22302 +0.23066 +0.22839 +0.2899 +0.29475 +0.30492 +0.20847 +0.030657 +0.15546 +0.15197 +0.14294 +0.17636 +0.072258 +0.081037 +0.080905 +0.39712 +0.30778 +0.30297 +0.19065 +0.16304 +0.17262 +0.13996 +0.12571 +0.10681 +0.20027 +0.29571 +0.31025 +0.14604 +0.13557 +0.17339 +0.22801 +0.17382 +0.21378 +0.22666 +0.21008 +0.11438 +0.13288 +0.052756 +0.15946 +0.10753 +0.10281 +0.052294 +0.15761 +0.18907 +0.22668 +0.31203 +0.28683 +0.28338 +0.29243 +0.22975 +0.24685 +0.24288 +0.20359 +0.256 +0.23178 +0.29659 +0.25034 +0.21068 +0.28045 +0.24369 +0.21394 +0.22513 +0.26066 +0.25512 +0.28332 +0.3019 +0.22115 +0.043952 +0.16544 +0.19506 +0.18618 +0.20234 +0.16001 +0.093341 +0.007629 +0.2793 +0.29235 +0.3143 +0.18097 +0.1754 +0.13513 +0.15078 +0.12159 +0.074643 +0.31145 +0.2886 +0.14109 +0.14233 +0.1502 +0.16024 +0.19819 +0.17782 +0.19938 +0.25744 +0.20983 +0.13289 +0.1072 +0.12121 +0.1539 +0.11984 +0.14847 +0.27421 +0.19827 +0.17622 +0.24152 +0.2767 +0.29651 +0.18312 +0.23527 +0.21856 +0.26329 +0.23109 +0.20057 +0.25019 +0.088933 +0.28738 +0.23696 +0.24031 +0.26398 +0.007741 +0.24176 +0.23416 +0.2462 +0.24861 +0.2866 +0.29099 +0.22812 +0.085521 +0.050847 +0.21917 +0.18873 +0.21048 +0.19647 +0.18593 +0.038136 +0.3726 +0.36938 +0.25608 +0.28713 +0.32768 +0.25537 +0.23537 +0.31818 +0.3121 +0.21235 +0.21921 +0.13309 +0.12404 +0.10396 +0.19754 +0.20377 +0.12188 +0.16621 +0.24864 +0.23903 +0.14564 +0.19606 +0.23952 +0.13518 +0.093199 +0.091574 +0.1238 +0.18863 +0.1918 +0.21494 +0.28692 +0.22732 +0.19396 +0.2092 +0.23271 +0.25926 +0.23777 +0.24209 +0.15309 +0.15761 +0.12113 +0.2312 +0.2858 +0.27541 +0.27634 +0.26044 +0.2154 +0.25829 +0.27798 +0.32146 +0.32508 +0.065884 +0.12481 +0.037967 +0.040457 +0.15953 +0.22821 +0.24318 +0.24843 +0.21575 +0.041564 +0.36324 +0.26214 +0.23948 +0.29762 +0.30247 +0.21153 +0.28107 +0.27336 +0.21996 +0.20447 +0.15185 +0.14133 +0.22202 +0.19464 +0.20818 +0.13561 +0.11566 +0.11088 +0.19984 +0.19237 +0.21403 +0.20169 +0.20637 +0.14607 +0.13488 +0.20691 +0.20814 +0.19764 +0.19441 +0.29795 +0.22622 +0.16682 +0.21658 +0.19479 +0.22967 +0.22348 +0.20647 +0.13702 +0.041555 +0.11485 +0.25998 +0.27482 +0.33787 +0.27449 +0.22518 +0.19435 +0.27554 +0.23293 +0.0001 +0.020896 +0.021656 +0.064173 +0.1197 +0.11515 +0.069743 +0.041183 +0.23858 +0.22857 +0.18766 +0.27462 +0.33123 +0.29998 +0.23758 +0.29084 +0.31162 +0.20977 +0.27992 +0.2935 +0.238 +0.21435 +0.17886 +0.25517 +0.26808 +0.19498 +0.23065 +0.14566 +0.090091 +0.12138 +0.075661 +0.19687 +0.20534 +0.22131 +0.22199 +0.13719 +0.087379 +0.21232 +0.19285 +0.21189 +0.25591 +0.29389 +0.23429 +0.14449 +0.21205 +0.19462 +0.18643 +0.20349 +0.059804 +0.1182 +0.10017 +0.043297 +0.012837 +0.3144 +0.33376 +0.25737 +0.30416 +0.23261 +0.24789 +0.15652 +0.04133 +0.075733 +0.077413 +0.061243 +0.13242 +0.11555 +0.089051 +0.091326 +0.11163 +0.25585 +0.26614 +0.23079 +0.29175 +0.30272 +0.23589 +0.3044 +0.37882 +0.28796 +0.28142 +0.31168 +0.28465 +0.28973 +0.19195 +0.26278 +0.29188 +0.31226 +0.2953 +0.15063 +0.081865 +0.096015 +0.083677 +0.136 +0.16088 +0.22127 +0.22392 +0.17077 +0.14139 +0.16193 +0.17398 +0.19512 +0.25492 +0.30857 +0.19822 +0.14022 +0.19477 +0.21208 +0.19593 +0.1788 +0.18491 +0.098731 +0.053509 +0.21426 +0.26606 +0.29056 +0.34789 +0.28144 +0.30661 +0.054223 +0.041927 +0.083467 +0.086084 +0.095373 +0.05399 +0.10052 +0.098013 +0.19404 +0.12399 +0.065252 +0.28532 +0.24814 +0.26005 +0.24591 +0.33244 +0.27282 +0.2787 +0.30465 +0.37994 +0.30454 +0.29916 +0.27075 +0.1859 +0.22392 +0.22237 +0.26837 +0.30473 +0.086714 +0.058816 +0.056096 +0.08184 +0.13247 +0.080142 +0.11922 +0.13847 +0.14855 +0.24511 +0.009489 +0.15161 +0.1438 +0.13035 +0.20382 +0.26089 +0.10904 +0.21271 +0.15617 +0.18736 +0.24419 +0.20793 +0.25187 +0.16894 +0.31736 +0.21411 +0.22865 +0.2617 +0.27716 +0.33125 +0.30923 +0.051152 +0.016561 +0.048735 +0.073555 +0.082155 +0.080772 +0.095044 +0.016215 +0.095804 +0.12721 +0.12552 +0.22983 +0.27845 +0.22278 +0.21924 +0.24216 +0.20897 +0.20683 +0.3219 +0.31162 +0.33391 +0.30378 +0.33328 +0.22703 +0.17529 +0.23483 +0.24775 +0.27938 +0.017748 +0.033741 +0.048162 +0.040969 +0.26284 +0.15341 +0.076914 +0.10602 +0.13032 +0.15849 +0.020042 +0.16095 +0.16747 +0.17459 +0.12277 +0.20247 +0.23588 +0.21237 +0.23416 +0.18433 +0.20199 +0.22734 +0.19549 +0.34145 +0.272 +0.29744 +0.29954 +0.24438 +0.24664 +0.26188 +0.3269 +0.32017 +0.007434 +0.0001 +0.075635 +0.15113 +0.084627 +0.15033 +0.1688 +0.10676 +0.075388 +0.12158 +0.14129 +0.22148 +0.29745 +0.24485 +0.25133 +0.17987 +0.23745 +0.22705 +0.3265 +0.24055 +0.28704 +0.29323 +0.26879 +0.29524 +0.19448 +0.24554 +0.27237 +0.29903 +0.077754 +0.053364 +0.3006 +0.34235 +0.30769 +0.35461 +0.08085 +0.13779 +0.11176 +0.17804 +0.18806 +0.201 +0.19296 +0.15195 +0.17349 +0.23649 +0.23972 +0.21642 +0.2387 +0.21241 +0.20845 +0.21566 +0.27613 +0.30116 +0.29475 +0.26753 +0.29668 +0.21549 +0.28205 +0.29057 +0.0001 +0.052913 +0.030961 +0.035848 +0.11947 +0.15078 +0.11237 +0.11741 +0.11692 +0.041212 +0.079873 +0.12501 +0.10574 +0.18333 +0.2081 +0.21517 +0.22047 +0.18324 +0.21847 +0.23239 +0.23575 +0.25817 +0.30013 +0.28158 +0.25428 +0.30728 +0.21241 +0.21587 +0.19939 +0.26517 +0.000421 +0.33615 +0.32325 +0.34447 +0.32582 +0.32884 +0.35359 +0.17373 +0.11535 +0.15477 +0.16142 +0.22541 +0.17969 +0.2779 +0.2264 +0.26928 +0.23363 +0.17734 +0.22488 +0.17046 +0.18715 +0.21064 +0.085055 +0.34259 +0.34143 +0.29174 +0.25075 +0.25914 +0.27274 +0.11984 +0.043478 +0.0001 +0.0001 +0.071221 +0.087536 +0.095366 +0.16663 +0.1063 +0.021308 +0.050717 +0.080306 +0.065244 +0.16928 +0.17461 +0.21399 +0.22509 +0.2446 +0.31567 +0.22606 +0.24127 +0.27865 +0.2691 +0.30199 +0.24443 +0.2824 +0.32209 +0.27704 +0.21359 +0.20837 +0.21591 +0.27846 +0.33793 +0.30935 +0.33807 +0.09629 +0.0001 +0.080814 +0.1782 +0.14044 +0.13893 +0.18793 +0.21497 +0.18542 +0.2849 +0.23708 +0.26503 +0.23766 +0.14032 +0.21835 +0.20729 +0.17016 +0.19582 +0.13302 +0.29097 +0.2879 +0.24972 +0.25975 +0.25747 +0.31326 +0.29512 +0.11375 +0.21085 +0.097998 +0.09677 +0.11558 +0.1662 +0.12798 +0.051203 +0.01552 +0.037862 +0.10644 +0.27396 +0.24307 +0.18446 +0.21878 +0.23792 +0.23669 +0.3082 +0.25767 +0.27406 +0.24931 +0.29186 +0.29787 +0.23309 +0.28716 +0.27875 +0.29812 +0.18999 +0.24685 +0.22418 +0.26891 +0.25698 +0.092555 +0.11586 +0.09607 +0.10489 +0.13335 +0.21554 +0.13913 +0.14019 +0.17615 +0.19537 +0.18541 +0.27694 +0.26119 +0.27252 +0.26058 +0.18896 +0.2159 +0.22425 +0.18899 +0.22235 +0.21973 +0.25438 +0.27331 +0.21958 +0.21885 +0.13739 +0.29886 +0.3324 +0.35994 +0.4 +0.21807 +0.15314 +0.085793 +0.12964 +0.11813 +0.020272 +0.037482 +0.0001 +0.28632 +0.29608 +0.27801 +0.18579 +0.21629 +0.26059 +0.27189 +0.30221 +0.27768 +0.30341 +0.26103 +0.27071 +0.28035 +0.22334 +0.28891 +0.29665 +0.17224 +0.19033 +0.22986 +0.19674 +0.2468 +0.24883 +0.10093 +0.11064 +0.099139 +0.10906 +0.22431 +0.19926 +0.15822 +0.15768 +0.18161 +0.1994 +0.19395 +0.24322 +0.23986 +0.22829 +0.28031 +0.204 +0.21582 +0.029338 +0.26704 +0.23316 +0.215 +0.2226 +0.28609 +0.24964 +0.25242 +0.13154 +0.16223 +0.088726 +0.39906 +0.4 +0.4 +0.4 +0.12289 +0.057848 +0.042108 +0.026917 +0.029236 +0.0001 +0.25926 +0.3031 +0.26042 +0.17844 +0.13581 +0.15877 +0.26415 +0.34119 +0.28339 +0.31916 +0.26619 +0.28911 +0.26337 +0.19818 +0.16835 +0.16466 +0.17257 +0.24824 +0.26781 +0.27003 +0.26382 +0.27669 +0.2207 +0.29766 +0.20943 +0.23055 +0.27577 +0.20353 +0.18847 +0.2055 +0.1964 +0.18586 +0.24336 +0.23112 +0.21085 +0.21831 +0.28652 +0.20726 +0.0001 +0.022684 +0.24019 +0.18752 +0.19343 +0.17895 +0.27894 +0.21366 +0.22558 +0.13157 +0.15154 +0.076051 +0.03056 +0.26749 +0.37278 +0.4 +0.4 +0.17162 +0.0001 +0.0001 +0.012463 +0.0001 +0.28168 +0.25235 +0.25085 +0.18551 +0.2153 +0.15826 +0.21361 +0.35258 +0.30407 +0.29776 +0.26872 +0.30352 +0.32443 +0.19262 +0.08168 +0.069459 +0.25781 +0.23352 +0.2851 +0.29703 +0.25461 +0.24572 +0.24432 +0.29931 +0.23206 +0.24677 +0.27821 +0.22057 +0.16693 +0.19129 +0.19529 +0.29187 +0.25976 +0.25707 +0.24527 +0.15384 +0.065618 +0.11527 +0.017792 +0.043114 +0.21632 +0.17228 +0.22365 +0.23121 +0.297 +0.22112 +0.22282 +0.13321 +0.13683 +0.29672 +0.068805 +0.053545 +0.29009 +0.34338 +0.4 +0.4 +0.34808 +0.1611 +0.048655 +0.072108 +0.28396 +0.26645 +0.22262 +0.17119 +0.15663 +0.14858 +0.1956 +0.18355 +0.30159 +0.30184 +0.27139 +0.28933 +0.36104 +0.32079 +0.063837 +0.057729 +0.027434 +0.0001 +0.2848 +0.29209 +0.23009 +0.23493 +0.24881 +0.27166 +0.27125 +0.27319 +0.26219 +0.22887 +0.098091 +0.089577 +0.23751 +0.26554 +0.26205 +0.26196 +0.2504 +0.11215 +0.095811 +0.039712 +0.051098 +0.22324 +0.22 +0.20083 +0.24046 +0.20635 +0.27453 +0.19531 +0.18551 +0.13487 +0.25812 +0.05386 +0.0001 +0.034126 +0.11999 +0.34757 +0.24802 +0.21159 +0.38783 +0.15002 +0.19716 +0.26151 +0.2804 +0.25433 +0.20779 +0.19208 +0.17772 +0.19412 +0.22198 +0.15677 +0.29006 +0.28531 +0.25209 +0.29258 +0.32834 +0.30742 +0.11164 +0.069628 +0.35451 +0.35735 +0.31798 +0.33606 +0.20549 +0.215 +0.23751 +0.26805 +0.087387 +0.094948 +0.039248 +0.08467 +0.06456 +0.22913 +0.20194 +0.10104 +0.23508 +0.23241 +0.26624 +0.14266 +0.09373 +0.095851 +0.054171 +0.047412 +0.17431 +0.18525 +0.18518 +0.21435 +0.20976 +0.2279 +0.19672 +0.093418 +0.11423 +0.08518 +0.039301 +0.065881 +0.039427 +0.14278 +0.27958 +0.23774 +0.1912 +0.19876 +0.16258 +0.24391 +0.29942 +0.24273 +0.20058 +0.21115 +0.13576 +0.23664 +0.20348 +0.23609 +0.0001 +0.29062 +0.26663 +0.31226 +0.31704 +0.33593 +0.32944 +0.30254 +0.36515 +0.32942 +0.33411 +0.33331 +0.21566 +0.21151 +0.23054 +0.23602 +0.10369 +0.014954 +0.042838 +0.06059 +0.11598 +0.12476 +0.00369 +0.15918 +0.088163 +0.20037 +0.27513 +0.27874 +0.26595 +0.24281 +0.25979 +0.26717 +0.21138 +0.15245 +0.17722 +0.16675 +0.1977 +0.26362 +0.20758 +0.065604 +0.11382 +0.066266 +0.002024 +0.053744 +0.063225 +0.04603 +0.093819 +0.24596 +0.20993 +0.21019 +0.17442 +0.22453 +0.26606 +0.24677 +0.19767 +0.21098 +0.26155 +0.20409 +0.18645 +0.19883 +0.0001 +0.14355 +0.26362 +0.30627 +0.30778 +0.30701 +0.32062 +0.30747 +0.37572 +0.36387 +0.038605 +0.20315 +0.21982 +0.21845 +0.23774 +0.22642 +0.28307 +0.041568 +0.077838 +0.031005 +0.09386 +0.086383 +0.088681 +0.066761 +0.042958 +0.084416 +0.14074 +0.27411 +0.27106 +0.28317 +0.27705 +0.30526 +0.29905 +0.18781 +0.18425 +0.15497 +0.20193 +0.027274 +0.071968 +0.088385 +0.12876 +0.10643 +0.035202 +0.11031 +0.11723 +0.055626 +0.063213 +0.092387 +0.19961 +0.2391 +0.16991 +0.16264 +0.25587 +0.23838 +0.20805 +0.20443 +0.1755 +0.17621 +0.35202 +0.0001 +0.19013 +0.17299 +0.16817 +0.28729 +0.2615 +0.29417 +0.30232 +0.2734 +0.11262 +0.084469 +0.19369 +0.22921 +0.2449 +0.2121 +0.25798 +0.25538 +0.28808 +0.034594 +0.04797 +0.1019 +0.10751 +0.094182 +0.097474 +0.045743 +0.002873 +0.056976 +0.13389 +0.1865 +0.29568 +0.22633 +0.26359 +0.30363 +0.31388 +0.17053 +0.15033 +0.18166 +0.21322 +0.20087 +0.067547 +0.050292 +0.094798 +0.12527 +0.13188 +0.10698 +0.06742 +0.12879 +0.079287 +0.11672 +0.17117 +0.23857 +0.15591 +0.14125 +0.25074 +0.22607 +0.19605 +0.1704 +0.20902 +0.14768 +0.18582 +0.2081 +0.16935 +0.14971 +0.17805 +0.30048 +0.28993 +0.28791 +0.30279 +0.26482 +0.26297 +0.22908 +0.29398 +0.27441 +0.24461 +0.19917 +0.24454 +0.26634 +0.28343 +0.069244 +0.008628 +0.14044 +0.15017 +0.027018 +0.088333 +0.038441 +0.2389 +0.19039 +0.18491 +0.17195 +0.22871 +0.2193 +0.20887 +0.18214 +0.3018 +0.17706 +0.17165 +0.1666 +0.17152 +0.18832 +0.07472 +0.057556 +0.06327 +0.16123 +0.12046 +0.20677 +0.052798 +0.1042 +0.098459 +0.04832 +0.1667 +0.21838 +0.15644 +0.12085 +0.2769 +0.24762 +0.24788 +0.19649 +0.17668 +0.15072 +0.17638 +0.19662 +0.21079 +0.14808 +0.19206 +0.21377 +0.12885 +0.26824 +0.27003 +0.27981 +0.23442 +0.28611 +0.28303 +0.27039 +0.21564 +0.18714 +0.26039 +0.27559 +0.085295 +0.086071 +0.1038 +0.081813 +0.096553 +0.018755 +0.043115 +0.22022 +0.2256 +0.19006 +0.16373 +0.17712 +0.22656 +0.27855 +0.15452 +0.15838 +0.13803 +0.12213 +0.11941 +0.1354 +0.14763 +0.17844 +0.16584 +0.006388 +0.059432 +0.10019 +0.1404 +0.20951 +0.20774 +0.10771 +0.29728 +0.25888 +0.25177 +0.22468 +0.16082 +0.3231 +0.26145 +0.26022 +0.25198 +0.23165 +0.18065 +0.2062 +0.21594 +0.27995 +0.20193 +0.15373 +0.15439 +0.34253 +0.12084 +0.28379 +0.29173 +0.2695 +0.24913 +0.27397 +0.28333 +0.27529 +0.24488 +0.1745 +0.28465 +0.049465 +0.069251 +0.066179 +0.088024 +0.0001 +0.10066 +0.024447 +0.069745 +0.25234 +0.16603 +0.20861 +0.17486 +0.19515 +0.2345 +0.2586 +0.29956 +0.17163 +0.16776 +0.11879 +0.10044 +0.14014 +0.12688 +0.16328 +0.17662 +0.062394 +0.077214 +0.1369 +0.0982 +0.096153 +0.22463 +0.18076 +0.24914 +0.2373 +0.2111 +0.25376 +0.30058 +0.30773 +0.22592 +0.26688 +0.21815 +0.19756 +0.17786 +0.21749 +0.25117 +0.2745 +0.27812 +0.18466 +0.1357 +0.34635 +0.28218 +0.29157 +0.26946 +0.27133 +0.27256 +0.29473 +0.29576 +0.29368 +0.23186 +0.19957 +0.0412 +0.073723 +0.090608 +0.10541 +0.13541 +0.0001 +0.11832 +0.0001 +0.0001 +0.0001 +0.19527 +0.22559 +0.2043 +0.30316 +0.26999 +0.28733 +0.29743 +0.29225 +0.20276 +0.20796 +0.19705 +0.14019 +0.14084 +0.17991 +0.17824 +0.1815 +0.19577 +0.19211 +0.22029 +0.2479 +0.2227 +0.2756 +0.24697 +0.22509 +0.08327 +0.086882 +0.025937 +0.0001 +0.24593 +0.2432 +0.30397 +0.16681 +0.11773 +0.15083 +0.23563 +0.24121 +0.31302 +0.23361 +0.23509 +0.32973 +0.25676 +0.23854 +0.2914 +0.27955 +0.29694 +0.23221 +0.30655 +0.23155 +0.23818 +0.20733 +0.028879 +0.038443 +0.11713 +0.12 +0.079753 +0.0001 +0.054565 +0.16805 +0.02066 +0.0001 +0.039062 +0.22676 +0.21151 +0.33714 +0.32039 +0.27895 +0.26652 +0.28034 +0.24421 +0.10028 +0.17445 +0.14018 +0.17328 +0.20145 +0.19954 +0.31002 +0.30679 +0.32854 +0.27851 +0.33545 +0.084464 +0.066914 +0.25188 +0.20766 +0.17664 +0.070439 +0.047506 +0.040095 +0.25767 +0.28777 +0.27703 +0.26282 +0.11638 +0.14376 +0.10966 +0.22495 +0.26938 +0.21669 +0.21973 +0.21246 +0.25315 +0.26858 +0.25068 +0.28034 +0.28958 +0.21735 +0.26413 +0.21804 +0.21223 +0.21058 +0.063711 +0.061425 +0.092777 +0.052314 +0.12536 +0.087468 +0.142 +0.10151 +0.0001 +0.0001 +0.049792 +0.18209 +0.26159 +0.28818 +0.31721 +0.32836 +0.3002 +0.26318 +0.20218 +0.10485 +0.12238 +0.14116 +0.17442 +0.23757 +0.28735 +0.29045 +0.33944 +0.022346 +0.015904 +0.040725 +0.070406 +0.2282 +0.251 +0.19849 +0.13726 +0.089487 +0.045611 +0.04611 +0.24552 +0.28996 +0.28095 +0.24829 +0.27724 +0.23677 +0.1212 +0.15459 +0.22277 +0.19673 +0.23825 +0.25499 +0.2035 +0.23918 +0.20954 +0.29196 +0.29293 +0.22276 +0.22251 +0.22675 +0.20435 +0.079081 +0.10753 +0.11236 +0.084465 +0.073989 +0.041911 +0.078336 +0.1171 +0.023753 +0.0001 +0.0001 +0.27301 +0.27427 +0.279 +0.32627 +0.29395 +0.34297 +0.29048 +0.25694 +0.10608 +0.11005 +0.13622 +0.33199 +0.28149 +0.2151 +0.11571 +0.10355 +0.11559 +0.062352 +0.0923 +0.064315 +0.029329 +0.22031 +0.25523 +0.22559 +0.082344 +0.01927 +0.051679 +0.071536 +0.071189 +0.063424 +0.25215 +0.23669 +0.25104 +0.23971 +0.2698 +0.22665 +0.20162 +0.14926 +0.2354 +0.27607 +0.23798 +0.23503 +0.21392 +0.26649 +0.26539 +0.21895 +0.20635 +0.241 +0.23534 +0.05383 +0.061898 +0.076024 +0.048422 +0.037149 +0.076475 +0.11521 +0.13093 +0.071075 +0.22676 +0.22273 +0.2897 +0.34479 +0.27758 +0.31131 +0.31334 +0.33555 +0.28904 +0.24032 +0.22544 +0.37981 +0.376 +0.30895 +0.26282 +0.17055 +0.062979 +0.056553 +0.056888 +0.12411 +0.097737 +0.12926 +0.17863 +0.23647 +0.22863 +0.24414 +0.075868 +0.0001 +0.0001 +0.03865 +0.00602 +0.052969 +0.077649 +0.24581 +0.2452 +0.25236 +0.27748 +0.24804 +0.2439 +0.14757 +0.19204 +0.19318 +0.24019 +0.22478 +0.20407 +0.12649 +0.18698 +0.23364 +0.18636 +0.2246 +0.23758 +0.23163 +0.064655 +0.041687 +0.066346 +0.092811 +0.02945 +0.081379 +0.16852 +0.32823 +0.24474 +0.25324 +0.26755 +0.36962 +0.31394 +0.29906 +0.3646 +0.31879 +0.33521 +0.18532 +0.19689 +0.35804 +0.35036 +0.29867 +0.2944 +0.009296 +0.092114 +0.11088 +0.033724 +0.054195 +0.10109 +0.18893 +0.19421 +0.20367 +0.20066 +0.0001 +0.015837 +0.026605 +0.03934 +0.031435 +0.24936 +0.10128 +0.078063 +0.066014 +0.2489 +0.27082 +0.22836 +0.2731 +0.22839 +0.18401 +0.20622 +0.17533 +0.18954 +0.25811 +0.20475 +0.11431 +0.19692 +0.23018 +0.25484 +0.17757 +0.19255 +0.23963 +0.19933 +0.062663 +0.046407 +0.26834 +0.2887 +0.2559 +0.3152 +0.33252 +0.28498 +0.25813 +0.28724 +0.34138 +0.31931 +0.26194 +0.36947 +0.34277 +0.22733 +0.22531 +0.21554 +0.14651 +0.29472 +0.3059 +0.28352 +0.31719 +0.069765 +0.082299 +0.20763 +0.23161 +0.1699 +0.17633 +0.19683 +0.21505 +0.07185 +0.0001 +0.030053 +0.029563 +0.0001 +0.06016 +0.26221 +0.15614 +0.065875 +0.069109 +0.18444 +0.25087 +0.25392 +0.29635 +0.19734 +0.18669 +0.22042 +0.20972 +0.16329 +0.20035 +0.27873 +0.1261 +0.16136 +0.20367 +0.26446 +0.23768 +0.16879 +0.11892 +0.16233 +0.23597 +0.26706 +0.27194 +0.30517 +0.24738 +0.31105 +0.18913 +0.21944 +0.26448 +0.28373 +0.24723 +0.25903 +0.019384 +0.4 +0.4 +0.4 +0.22698 +0.20455 +0.18538 +0.28167 +0.30444 +0.28913 +0.27962 +0.25741 +0.26557 +0.24391 +0.20105 +0.19428 +0.04815 +0.10321 +0.099139 +0.04826 +0.063793 +0.009682 +0.020765 +0.02969 +0.021224 +0.27869 +0.12735 +0.0001 +0.019467 +0.15161 +0.19862 +0.24107 +0.28198 +0.1685 +0.16353 +0.19082 +0.1889 +0.17386 +0.21013 +0.27887 +0.33531 +0.13373 +0.17578 +0.21584 +0.31667 +0.33519 +0.37398 +0.26445 +0.26534 +0.26284 +0.2583 +0.051835 +0.12903 +0.16055 +0.1993 +0.2255 +0.26106 +0.28961 +0.10894 +0.155 +0.069906 +0.4 +0.4 +0.4 +0.4 +0.19193 +0.19973 +0.11948 +0.033237 +0.29386 +0.27708 +0.26132 +0.27075 +0.24973 +0.12171 +0.063793 +0.0001 +0.062313 +0.21545 +0.12098 +0.11913 +0.059555 +0.03259 +0.065308 +0.003063 +0.30817 +0.11822 +0.21804 +0.23534 +0.14242 +0.19826 +0.21337 +0.24511 +0.22029 +0.17365 +0.19032 +0.22849 +0.17614 +0.25335 +0.27494 +0.3237 +0.18066 +0.28004 +0.30674 +0.30158 +0.31098 +0.37589 +0.24973 +0.24864 +0.21922 +0.25405 +0.065824 +0.12574 +0.1477 +0.17999 +0.22573 +0.046688 +0.076829 +0.14944 +0.14066 +0.16661 +0.18217 +0.12223 +0.4 +0.4 +0.4 +0.2274 +0.16564 +0.058034 +0.15392 +0.25511 +0.24532 +0.25316 +0.043978 +0.065449 +0.048977 +0.072629 +0.1165 +0.11408 +0.14642 +0.11171 +0.043268 +0.011695 +0.021028 +0.0001 +0.35874 +0.067389 +0.20809 +0.20257 +0.15515 +0.20202 +0.23445 +0.22696 +0.19785 +0.23241 +0.20782 +0.23199 +0.18573 +0.24571 +0.289 +0.28745 +0.18488 +0.31906 +0.28463 +0.2841 +0.22703 +0.2444 +0.24297 +0.24882 +0.2516 +0.23337 +0.12274 +0.1488 +0.16167 +0.17505 +0.17752 +0.065365 +0.044503 +0.10529 +0.11901 +0.16826 +0.15126 +0.16635 +0.13488 +0.4 +0.4 +0.4 +0.16057 +0.046422 +0.14115 +0.1004 +0.22788 +0.24408 +0.27074 +0.12387 +0.092939 +0.094349 +0.15336 +0.14574 +0.13146 +0.052083 +0.069239 +0.030315 +0.017243 +0.018326 +0.025589 +0.03944 +0.024206 +0.21929 +0.26249 +0.27982 +0.25873 +0.24103 +0.21129 +0.20632 +0.2249 +0.22916 +0.18622 +0.21579 +0.22857 +0.32709 +0.22378 +0.23448 +0.27759 +0.3142 +0.31875 +0.24939 +0.24503 +0.26434 +0.26704 +0.020028 +0.06662 +0.17132 +0.14497 +0.16838 +0.18551 +0.06787 +0.049901 +0.056812 +0.15909 +0.19424 +0.17922 +0.20008 +0.14331 +0.4 +0.4 +0.4 +0.4 +0.39228 +0.15482 +0.11289 +0.066404 +0.22531 +0.26567 +0.18613 +0.14584 +0.075679 +0.092485 +0.056233 +0.063004 +0.088861 +0.045028 +0.043275 +0.028568 +0.055803 +0.19296 +0.02442 +0.21402 +0.24366 +0.30112 +0.27954 +0.29277 +0.2591 +0.20829 +0.20697 +0.17036 +0.18544 +0.18859 +0.15205 +0.22484 +0.31073 +0.21321 +0.25789 +0.27427 +0.32007 +0.28851 +0.2122 +0.2489 +0.28519 +0.077723 +0.049849 +0.031919 +0.17362 +0.14364 +0.171 +0.1698 +0.04863 +0.046593 +0.070034 +0.17611 +0.16809 +0.15707 +0.18626 +0.10319 +0.4 +0.4 +0.4 +0.4 +0.4 +0.4 +0.089589 +0.046888 +0.10281 +0.26974 +0.27713 +0.11872 +0.1517 +0.12461 +0.091822 +0.14553 +0.09018 +0.11702 +0.035033 +0.075164 +0.044238 +0.1972 +0.18189 +0.22415 +0.27006 +0.29219 +0.26524 +0.29042 +0.26329 +0.223 +0.20214 +0.18957 +0.16092 +0.16668 +0.24386 +0.20377 +0.15875 +0.2101 +0.25827 +0.26654 +0.26648 +0.31314 +0.27597 +0.27944 +0.10163 +0.14124 +0.15055 +0.10903 +0.092503 +0.16233 +0.20725 +0.21249 +0.009571 +0.21498 +0.2224 +0.1703 +0.17239 +0.15883 +0.20224 +0.4 +0.4 +0.4 +0.4 +0.4 +0.4 +0.4 +0.3432 +0.035645 +0.080126 +0.24337 +0.24499 +0.041423 +0.098495 +0.11653 +0.087324 +0.059468 +0.11843 +0.13826 +0.045758 +0.076767 +0.049184 +0.2283 +0.17584 +0.27593 +0.27979 +0.25432 +0.28679 +0.27734 +0.26251 +0.24113 +0.22682 +0.17789 +0.15286 +0.22842 +0.21911 +0.21395 +0.1924 +0.19807 +0.24909 +0.28514 +0.2996 +0.22226 +0.27699 +0.29791 +0.27637 +0.26181 +0.0001 +0.043771 +0.024712 +0.20011 +0.1956 +0.19912 +0.25309 +0.17693 +0.20036 +0.17115 +0.154 +0.16949 +0.4 +0.4 +0.4 +0.4 +0.4 +0.4 +0.4 +0.38269 +0.37629 +0.035356 +0.086719 +0.28206 +0.20747 +0.19312 +0.039957 +0.070189 +0.014627 +0.050677 +0.13601 +0.052103 +0.060834 +0.092128 +0.10926 +0.17939 +0.17615 +0.28152 +0.27635 +0.23853 +0.30349 +0.27961 +0.22762 +0.21873 +0.16402 +0.14766 +0.20391 +0.20911 +0.1799 +0.23463 +0.21166 +0.21996 +0.2879 +0.356 +0.22725 +0.32336 +0.21886 +0.26311 +0.17919 +0.14765 +0.26707 +0.10845 +0.038083 +0.092908 +0.19809 +0.22939 +0.24669 +0.23665 +0.20539 +0.18334 +0.14876 +0.16006 +0.4 +0.4 +0.4 +0.4 +0.4 +0.4 +0.4 +0.36784 +0.080638 +0.040387 +0.19447 +0.25097 +0.2191 +0.18679 +0.27398 +0.058985 +0.084637 +0.0001 +0.11942 +0.029852 +0.001867 +0.087224 +0.027983 +0.16964 +0.21681 +0.26222 +0.30976 +0.24012 +0.29626 +0.20877 +0.26429 +0.25535 +0.23316 +0.25172 +0.2477 +0.19335 +0.21852 +0.22615 +0.23246 +0.25597 +0.24872 +0.21321 +0.2143 +0.31558 +0.23962 +0.21685 +0.19438 +0.154 +0.26926 +0.18693 +0.098917 +0.24513 +0.23241 +0.23132 +0.21771 +0.23616 +0.29169 +0.18394 +0.16833 +0.4 +0.4 +0.4 +0.4 +0.4 +0.4 +0.4 +0.37046 +0.34215 +0.35729 +0.19292 +0.19526 +0.27837 +0.22547 +0.21347 +0.2779 +0.10025 +0.11967 +0.076624 +0.059866 +0.054003 +0.027284 +0.032438 +0.10629 +0.16227 +0.23904 +0.26197 +0.3107 +0.29245 +0.29439 +0.20577 +0.25721 +0.22897 +0.24901 +0.23689 +0.24226 +0.20912 +0.2138 +0.20976 +0.26029 +0.27561 +0.27212 +0.24421 +0.25492 +0.26649 +0.23726 +0.25972 +0.069638 +0.079311 +0.27343 +0.20568 +0.14542 +0.16654 +0.27873 +0.25754 +0.23826 +0.23927 +0.27164 +0.4 +0.4 +0.4 +0.4 +0.4 +0.4 +0.4 +0.4 +0.4 +0.36166 +0.35146 +0.14308 +0.17662 +0.17877 +0.22655 +0.24904 +0.24148 +0.27066 +0.087658 +0.13103 +0.10522 +0.18804 +0.14017 +0.098434 +0.072404 +0.10766 +0.18637 +0.27832 +0.27508 +0.31655 +0.29596 +0.30656 +0.20235 +0.18748 +0.20844 +0.24154 +0.2064 +0.20226 +0.1942 +0.38502 +0.32953 +0.22716 +0.23376 +0.28177 +0.28624 +0.24582 +0.26963 +0.27104 +0.28029 +0.017862 +0.30459 +0.3125 +0.26022 +0.20966 +0.25075 +0.13337 +0.1944 +0.24735 +0.22587 +0.21349 +0.4 +0.4 +0.4 +0.4 +0.4 +0.4 +0.4 +0.4 +0.4 +0.37513 +0.082183 +0.10759 +0.07137 +0.15351 +0.23985 +0.24658 +0.24331 +0.29621 +0.096342 +0.1308 +0.14311 +0.039666 +0.18966 +0.3128 +0.3117 +0.082324 +0.24084 +0.28169 +0.26432 +0.28601 +0.25083 +0.30556 +0.24075 +0.23148 +0.17736 +0.24723 +0.23152 +0.26062 +0.25218 +0.2524 +0.27725 +0.20217 +0.20604 +0.044 +0.2912 +0.21762 +0.25438 +0.26495 +0.25751 +0.049575 +0.27891 +0.33978 +0.34393 +0.068802 +0.25076 +0.26801 +0.28593 +0.25114 +0.27167 +0.20538 +0.4 +0.4 +0.4 +0.4 +0.4 +0.4 +0.4 +0.4 +0.4 +0.059715 +0.064167 +0.082028 +0.052115 +0.12636 +0.23266 +0.22564 +0.24754 +0.28126 +0.24987 +0.12442 +0.10923 +0.050323 +0.23166 +0.37012 +0.31211 +0.25567 +0.23423 +0.26474 +0.27755 +0.25026 +0.23443 +0.15873 +0.22719 +0.19563 +0.19339 +0.23197 +0.20779 +0.24396 +0.20782 +0.24963 +0.2844 +0.21566 +0.1942 +0.089295 +0.28661 +0.20955 +0.25888 +0.27519 +0.11221 +0.059831 +0.29958 +0.34686 +0.32322 +0.23402 +0.20874 +0.15551 +0.2539 +0.16434 +0.27812 +0.21523 +0.4 +0.4 +0.4 +0.4 +0.4 +0.4 +0.4 +0.0639 +0.049292 +0.026705 +0.084781 +0.087055 +0.090262 +0.15219 +0.2142 +0.20138 +0.23924 +0.25565 +0.23935 +0.089425 +0.069929 +0.054533 +0.036286 +0.39497 +0.3796 +0.24705 +0.22575 +0.27204 +0.24579 +0.23865 +0.22741 +0.20116 +0.20533 +0.18939 +0.19735 +0.2278 +0.20797 +0.22936 +0.22696 +0.27159 +0.28909 +0.19631 +0.16408 +0.28965 +0.25284 +0.18506 +0.22081 +0.28238 +0.099248 +0.26954 +0.32286 +0.31717 +0.24655 +0.19565 +0.2471 +0.16252 +0.1666 +0.17232 +0.25129 +0.21711 +0.23758 +0.2672 +0.4 +0.4 +0.4 +0.4 +0.042058 +0.011017 +0.0606 +0.034737 +0.1335 +0.091107 +0.064815 +0.15884 +0.20372 +0.21863 +0.21932 +0.24272 +0.20875 +0.15754 +0.041663 +0.067638 +0.001851 +0.33668 +0.32938 +0.26947 +0.22514 +0.19502 +0.22561 +0.22891 +0.10505 +0.19682 +0.16932 +0.19009 +0.21151 +0.22163 +0.20847 +0.23715 +0.20981 +0.24241 +0.25683 +0.17053 +0.13335 +0.29984 +0.25091 +0.25553 +0.30865 +0.32135 +0.043546 +0.29666 +0.32851 +0.24497 +0.25052 +0.22096 +0.22595 +0.20424 +0.1841 +0.16686 +0.22859 +0.21484 +0.21319 +0.28979 +0.27169 +0.4 +0.4 +0.4 +0.086344 +0.11402 +0.095525 +0.10889 +0.1177 +0.11593 +0.19047 +0.13995 +0.15798 +0.19863 +0.23017 +0.24491 +0.22093 +0.10011 +0.059856 +0.0001 +0.039673 +0.005489 +0.29375 +0.29493 +0.23755 +0.22281 +0.16461 +0.16856 +0.15057 +0.17198 +0.16215 +0.17929 +0.22017 +0.23689 +0.27231 +0.22294 +0.21787 +0.24907 +0.23862 +0.18108 +0.29998 +0.29084 +0.2637 +0.26334 +0.33428 +0.32415 +0.33541 +0.24684 +0.27458 +0.22553 +0.2446 +0.16451 +0.21686 +0.27142 +0.28318 +0.2541 +0.21404 +0.19828 +0.2424 +0.26162 +0.2517 +0.4 +0.4 +0.25465 +0.21907 +0.039554 +0.061751 +0.020393 +0.27632 +0.2274 +0.23605 +0.17007 +0.16245 +0.19405 +0.24418 +0.27125 +0.12732 +0.045922 +0.024951 +0.069058 +0.045562 +0.059325 +0.05068 +0.28133 +0.25373 +0.12504 +0.15551 +0.17028 +0.20591 +0.17752 +0.14094 +0.17373 +0.2229 +0.23907 +0.22535 +0.20991 +0.25016 +0.24083 +0.22763 +0.3096 +0.30591 +0.26671 +0.25564 +0.19365 +0.18465 +0.2186 +0.27065 +0.25687 +0.27858 +0.22116 +0.20674 +0.24023 +0.23909 +0.28626 +0.25297 +0.24543 +0.24935 +0.20405 +0.20802 +0.226 +0.23723 +0.18575 +0.22989 +0.22737 +0.19662 +0.20422 +0.042669 +0.34212 +0.2673 +0.26459 +0.25702 +0.16491 +0.18016 +0.1807 +0.19648 +0.13669 +0.16472 +0.098392 +0.052895 +0.045123 +0.021693 +0.060092 +0.24678 +0.27739 +0.19046 +0.10739 +0.18048 +0.19893 +0.20863 +0.19743 +0.17053 +0.18526 +0.204 +0.23558 +0.20542 +0.21198 +0.26651 +0.20475 +0.22414 +0.22879 +0.24927 +0.22204 +0.21863 +0.23906 +0.19324 +0.2146 +0.2973 +0.30382 +0.27602 +0.24649 +0.19694 +0.22972 +0.26809 +0.25731 +0.23305 +0.24143 +0.28043 +0.26114 +0.16721 +0.23633 +0.2236 +0.18461 +0.20562 +0.22046 +0.24532 +0.19239 +0.097143 +0.34556 +0.25837 +0.28556 +0.2135 +0.16521 +0.19438 +0.18885 +0.071609 +0.12606 +0.13055 +0.06514 +0.037243 +0.079155 +0.049216 +0.27572 +0.25673 +0.27187 +0.20097 +0.12279 +0.16373 +0.21186 +0.22959 +0.17316 +0.19509 +0.25776 +0.19855 +0.24293 +0.25064 +0.24341 +0.1818 +0.19124 +0.23987 +0.19803 +0.19588 +0.22911 +0.20462 +0.27267 +0.21715 +0.22803 +0.31041 +0.30431 +0.27686 +0.21595 +0.19626 +0.225 +0.28098 +0.27705 +0.24881 +0.30426 +0.30309 +0.2753 +0.15512 +0.16557 +0.14609 +0.21019 +0.3046 +0.27045 +0.30048 +0.29603 +0.22878 +0.35357 +0.2428 +0.26207 +0.22594 +0.22116 +0.21133 +0.20457 +0.10642 +0.091056 +0.11216 +0.10485 +0.10553 +0.11743 +0.052611 +0.32715 +0.26998 +0.27234 +0.18814 +0.13967 +0.1731 +0.24302 +0.20375 +0.17752 +0.18096 +0.19017 +0.21841 +0.28306 +0.21842 +0.21831 +0.21479 +0.20435 +0.24165 +0.18662 +0.18696 +0.20743 +0.20999 +0.26271 +0.28767 +0.34753 +0.31907 +0.28509 +0.28342 +0.22408 +0.22263 +0.22997 +0.2514 +0.2718 +0.24386 +0.29352 +0.28497 +0.26714 +0.22179 +0.19873 +0.15657 +0.23051 +0.27596 +0.30504 +0.28163 +0.31738 +0.24404 +0.20001 +0.24823 +0.24558 +0.26287 +0.23036 +0.17403 +0.19941 +0.050924 +0.11065 +0.12107 +0.11141 +0.081339 +0.066512 +0.26681 +0.33245 +0.2842 +0.27137 +0.13443 +0.12913 +0.20533 +0.22011 +0.13017 +0.11093 +0.2009 +0.16434 +0.16682 +0.052556 +0.2039 +0.18248 +0.23259 +0.24115 +0.23623 +0.16859 +0.18305 +0.20801 +0.23508 +0.21253 +0.27014 +0.31203 +0.35376 +0.31431 +0.2338 +0.23649 +0.20114 +0.24904 +0.27671 +0.28702 +0.21107 +0.28452 +0.28879 +0.28583 +0.22705 +0.1733 +0.14382 +0.2103 +0.29096 +0.27108 +0.29298 +0.30401 +0.33294 +0.2661 +0.24448 +0.28769 +0.2846 +0.21796 +0.1904 +0.17201 +0.10335 +0.15279 +0.09758 +0.10919 +0.22781 +0.24458 +0.28638 +0.33623 +0.26354 +0.24627 +0.13793 +0.16786 +0.20963 +0.26192 +0.26424 +0.078547 +0.20785 +0.1753 +0.17123 +0.18745 +0.18756 +0.17492 +0.22538 +0.26895 +0.20251 +0.15969 +0.17051 +0.224 +0.24175 +0.27208 +0.29042 +0.27663 +0.32708 +0.3178 +0.22683 +0.19648 +0.14041 +0.25868 +0.28105 +0.29419 +0.28283 +0.29695 +0.30245 +0.2978 +0.2906 +0.1981 +0.16803 +0.24519 +0.27542 +0.3077 +0.28637 +0.28655 +0.31056 +0.3215 +0.26266 +0.28935 +0.26316 +0.21067 +0.26529 +0.21233 +0.21661 +0.19514 +0.058764 +0.095952 +0.26307 +0.26454 +0.3431 +0.28543 +0.24604 +0.24178 +0.16132 +0.12676 +0.18738 +0.26456 +0.2734 +0.25374 +0.2496 +0.16043 +0.16439 +0.16392 +0.18246 +0.20061 +0.23457 +0.23644 +0.26248 +0.16564 +0.16922 +0.26509 +0.22617 +0.24431 +0.28032 +0.22873 +0.30997 +0.35124 +0.17794 +0.12749 +0.12642 +0.22598 +0.24194 +0.34815 +0.29204 +0.30573 +0.28563 +0.3306 +0.29288 +0.11272 +0.21624 +0.23665 +0.27594 +0.32638 +0.29868 +0.27684 +0.32359 +0.32615 +0.27699 +0.093678 +0.22258 +0.22179 +0.26242 +0.208 +0.22812 +0.23699 +0.16543 +0.23743 +0.25243 +0.27368 +0.28585 +0.25623 +0.24315 +0.24721 +0.2009 +0.09905 +0.27669 +0.27937 +0.24965 +0.2249 +0.20758 +0.22531 +0.026543 +0.17961 +0.1834 +0.17872 +0.19935 +0.21975 +0.26382 +0.18182 +0.19333 +0.24686 +0.24728 +0.27399 +0.22227 +0.2375 +0.31757 +0.23422 +0.19158 +0.13802 +0.091129 +0.23055 +0.22843 +0.38364 +0.32999 +0.29403 +0.25914 +0.34479 +0.14366 +0.096603 +0.24232 +0.24135 +0.28144 +0.31116 +0.28451 +0.29222 +0.327 +0.32076 +0.10187 +0.11556 +0.149 +0.17823 +0.24983 +0.26294 +0.20567 +0.22444 +0.15083 +0.18216 +0.22019 +0.25496 +0.27533 +0.25284 +0.23961 +0.2682 +0.1896 +0.35851 +0.28976 +0.25593 +0.23812 +0.21789 +0.23051 +0.26807 +0.15912 +0.21587 +0.21464 +0.18868 +0.21642 +0.24188 +0.2658 +0.18379 +0.19472 +0.24407 +0.25069 +0.30199 +0.27188 +0.23512 +0.050702 +0.21101 +0.15248 +0.15695 +0.10133 +0.20271 +0.25374 +0.37427 +0.31265 +0.32181 +0.30432 +0.36288 +0.10581 +0.064 +0.21683 +0.21304 +0.28924 +0.30933 +0.24238 +0.3751 +0.36663 +0.35283 +0.026858 +0.088392 +0.088532 +0.10536 +0.23959 +0.26668 +0.16009 +0.19648 +0.13436 +0.18868 +0.19615 +0.24397 +0.26222 +0.27437 +0.25259 +0.25773 +0.13399 +0.09073 +0.25029 +0.26663 +0.23337 +0.18326 +0.23492 +0.27099 +0.077225 +0.085638 +0.22964 +0.17419 +0.1997 +0.18 +0.22251 +0.2026 +0.17983 +0.24912 +0.21202 +0.29351 +0.23388 +0.21137 +0.21194 +0.17867 +0.16706 +0.14751 +0.12714 +0.23477 +0.27704 +0.35896 +0.3312 +0.36014 +0.29811 +0.4 +0.37374 +0.069552 +0.11239 +0.21512 +0.2466 +0.28578 +0.23592 +0.35841 +0.35292 +0.30578 +0.049787 +0.0449 +0.10198 +0.12548 +0.12556 +0.27626 +0.17783 +0.2087 +0.16387 +0.21948 +0.22865 +0.21411 +0.20818 +0.28317 +0.26076 +0.26818 +0.13274 +0.13517 +0.26171 +0.23888 +0.20687 +0.16933 +0.23147 +0.22617 +0.32896 +0.33398 +0.048516 +0.13146 +0.18492 +0.18295 +0.21446 +0.16603 +0.17788 +0.26636 +0.22855 +0.27601 +0.32689 +0.33932 +0.20881 +0.17398 +0.081212 +0.22825 +0.25023 +0.28211 +0.35723 +0.39711 +0.32471 +0.35208 +0.34391 +0.39655 +0.38175 +0.22254 +0.27198 +0.24592 +0.27069 +0.30404 +0.22167 +0.35156 +0.35757 +0.33445 +0.10337 +0.10007 +0.075821 +0.09285 +0.055982 +0.2604 +0.23222 +0.21608 +0.1939 +0.24387 +0.21957 +0.23855 +0.21798 +0.24022 +0.29823 +0.29378 +0.15567 +0.17091 +0.26224 +0.27008 +0.23497 +0.19207 +0.23586 +0.19968 +0.19159 +0.35638 +0.31608 +0.060707 +0.1711 +0.17634 +0.18162 +0.19817 +0.19598 +0.2623 +0.24653 +0.27275 +0.31587 +0.30608 +0.20973 +0.278 +0.30811 +0.23051 +0.25413 +0.2484 +0.35951 +0.38832 +0.33628 +0.37431 +0.3345 +0.36701 +0.37054 +0.31962 +0.26556 +0.26924 +0.26879 +0.28947 +0.37366 +0.34729 +0.33704 +0.3149 +0.15206 +0.11532 +0.10718 +0.069033 +0.24055 +0.22819 +0.23653 +0.22236 +0.18356 +0.23204 +0.1937 +0.22733 +0.19671 +0.2397 +0.19054 +0.18418 +0.18055 +0.17752 +0.16987 +0.28501 +0.25941 +0.23391 +0.25561 +0.23954 +0.22069 +0.22438 +0.31867 +0.1519 +0.21386 +0.20374 +0.19902 +0.18698 +0.21433 +0.26059 +0.25112 +0.30125 +0.2984 +0.19204 +0.30285 +0.28035 +0.27562 +0.2491 +0.24241 +0.26127 +0.35206 +0.38744 +0.3307 +0.36306 +0.33042 +0.34068 +0.29603 +0.30634 +0.2769 +0.29619 +0.28987 +0.38986 +0.37057 +0.3897 +0.33359 +0.33877 +0.073638 +0.070933 +0.063204 +0.24965 +0.26395 +0.22775 +0.26542 +0.25807 +0.21247 +0.20077 +0.18942 +0.182 +0.18675 +0.24101 +0.20627 +0.18434 +0.21604 +0.215 +0.18487 +0.24652 +0.2539 +0.2761 +0.28169 +0.23656 +0.22883 +0.26819 +0.20928 +0.13107 +0.1583 +0.21302 +0.22812 +0.21141 +0.1809 +0.17728 +0.23325 +0.25637 +0.29496 +0.3202 +0.29128 +0.26617 +0.28934 +0.30587 +0.25756 +0.34153 +0.3454 +0.36789 +0.36487 +0.35781 +0.29844 +0.096507 +0.33336 +0.28063 +0.30533 +0.28655 +0.10919 +0.37463 +0.35592 +0.34192 +0.36046 +0.34868 +0.050824 +0.036656 +0.23391 +0.23369 +0.27145 +0.27087 +0.27429 +0.22722 +0.19948 +0.22722 +0.19125 +0.20495 +0.15349 +0.20367 +0.21245 +0.16264 +0.20687 +0.21336 +0.19001 +0.22701 +0.21024 +0.21339 +0.32917 +0.10801 +0.20716 +0.24352 +0.19288 +0.10097 +0.15817 +0.19957 +0.22183 +0.18119 +0.16287 +0.16047 +0.2075 +0.27991 +0.27785 +0.304 +0.29934 +0.22419 +0.16489 +0.12435 +0.22362 +0.29856 +0.31298 +0.35951 +0.36334 +0.22721 +0.10883 +0.061217 +0.30417 +0.3093 +0.28867 +0.029891 +0.34534 +0.33983 +0.35913 +0.33733 +0.35835 +0.36969 +0.35345 +0.24495 +0.24662 +0.2242 +0.27165 +0.25938 +0.23773 +0.20812 +0.22896 +0.229 +0.20803 +0.20281 +0.19852 +0.16723 +0.17933 +0.14036 +0.25283 +0.21414 +0.22556 +0.22718 +0.2047 +0.26121 +0.25705 +0.27392 +0.2137 +0.24536 +0.19131 +0.12063 +0.18234 +0.18564 +0.26406 +0.15782 +0.16322 +0.16716 +0.23627 +0.30324 +0.27684 +0.31126 +0.29241 +0.23577 +0.20948 +0.17087 +0.22218 +0.28748 +0.30429 +0.3488 +0.32492 +0.20779 +0.11444 +0.22278 +0.29746 +0.3119 +0.27085 +0.03317 +0.09853 +0.30823 +0.32495 +0.34078 +0.334 +0.34456 +0.24341 +0.26256 +0.25058 +0.27482 +0.28622 +0.24628 +0.21757 +0.21165 +0.2398 +0.30966 +0.33049 +0.27203 +0.22158 +0.18739 +0.1818 +0.15547 +0.23725 +0.22511 +0.22229 +0.22345 +0.21574 +0.27858 +0.27375 +0.22794 +0.22671 +0.23186 +0.18037 +0.10708 +0.21341 +0.31233 +0.28461 +0.28901 +0.13517 +0.18768 +0.20861 +0.30722 +0.32851 +0.3221 +0.26064 +0.26949 +0.23151 +0.22642 +0.24524 +0.27487 +0.031952 +0.32205 +0.33839 +0.32368 +0.23633 +0.27337 +0.25235 +0.10182 +0.021788 +0.25256 +0.24288 +0.31357 +0.33282 +0.31452 +0.31294 +0.34574 +0.38951 +0.27053 +0.29173 +0.3061 +0.288 +0.080375 +0.074662 +0.066508 +0.077573 +0.26051 +0.30003 +0.23637 +0.19266 +0.17204 +0.15526 +0.15571 +0.18549 +0.15987 +0.27772 +0.21841 +0.16688 +0.22062 +0.29532 +0.32993 +0.24095 +0.20953 +0.23598 +0.20681 +0.28843 +0.29404 +0.31153 +0.31305 +0.28609 +0.26051 +0.20456 +0.21565 +0.32051 +0.31613 +0.30792 +0.28406 +0.25476 +0.22905 +0.25591 +0.09576 +0.060041 +0.31898 +0.33655 +0.25528 +0.2946 +0.27807 +0.18608 +0.11974 +0.1267 +0.2381 +0.32767 +0.32004 +0.3301 +0.33199 +0.35893 +0.346 +0.38933 +0.1121 +0.11382 +0.0001 +0.026722 +0.081457 +0.09921 +0.10377 +0.12797 +0.25021 +0.2857 +0.26252 +0.22412 +0.18012 +0.1591 +0.14153 +0.22241 +0.26346 +0.27527 +0.28475 +0.21175 +0.1964 +0.28752 +0.32533 +0.32277 +0.34175 +0.23356 +0.16674 +0.14536 +0.30912 +0.35536 +0.30513 +0.30323 +0.24435 +0.20623 +0.087074 +0.19702 +0.33023 +0.25722 +0.28918 +0.26411 +0.23223 +0.26483 +0.079659 +0.10597 +0.060134 +0.30373 +0.22869 +0.27865 +0.26523 +0.25956 +0.12271 +0.1112 +0.1717 +0.33316 +0.28019 +0.31122 +0.33946 +0.34824 +0.36335 +0.38569 +0.098692 +0.014943 +0.0001 +0.0001 +0.007921 +0.11374 +0.14358 +0.10504 +0.059295 +0.23879 +0.25552 +0.23491 +0.20748 +0.18576 +0.14749 +0.23775 +0.25935 +0.29344 +0.26125 +0.21144 +0.18766 +0.30627 +0.32275 +0.31755 +0.33047 +0.23328 +0.16645 +0.12168 +0.16237 +0.37329 +0.29094 +0.32095 +0.22263 +0.23022 +0.25034 +0.23148 +0.20706 +0.22841 +0.23456 +0.2638 +0.22662 +0.30368 +0.19647 +0.087223 +0.007069 +0.07115 +0.21373 +0.24737 +0.21993 +0.24996 +0.23577 +0.19992 +0.20957 +0.25329 +0.29403 +0.3428 +0.33746 +0.3118 +0.33005 +0.35214 +0.11261 +0.06633 +0.039907 +0.011341 +0.054709 +0.03307 +0.12673 +0.12387 +0.098226 +0.21418 +0.21398 +0.23672 +0.23048 +0.17397 +0.14556 +0.201 +0.29325 +0.29753 +0.20432 +0.22793 +0.25217 +0.2973 +0.32138 +0.29657 +0.32387 +0.23244 +0.17451 +0.13533 +0.33328 +0.32392 +0.28829 +0.30719 +0.22463 +0.21999 +0.20797 +0.24265 +0.22846 +0.054169 +0.22683 +0.235 +0.28251 +0.27405 +0.28729 +0.24807 +0.072141 +0.20065 +0.12611 +0.26892 +0.24626 +0.25017 +0.21956 +0.22171 +0.21921 +0.20754 +0.26148 +0.3391 +0.3422 +0.32238 +0.12436 +0.12807 +0.084041 +0.10693 +0.0001 +0.038668 +0.036953 +0.0001 +0.065521 +0.10375 +0.21245 +0.23927 +0.20152 +0.24221 +0.24704 +0.19453 +0.16866 +0.22642 +0.26392 +0.26336 +0.19401 +0.2217 +0.25674 +0.28858 +0.29224 +0.2754 +0.32549 +0.2528 +0.31121 +0.21556 +0.2917 +0.29979 +0.29563 +0.29823 +0.2414 +0.20859 +0.19401 +0.27263 +0.24046 +0.21075 +0.25847 +0.19814 +0.2954 +0.29314 +0.28422 +0.24334 +0.20192 +0.18599 +0.26401 +0.25595 +0.24509 +0.22951 +0.25988 +0.21216 +0.2176 +0.20803 +0.24535 +0.33515 +0.23967 +0.20322 +0.13064 +0.18833 +0.096679 +0.10258 +0.043267 +0.057132 +0.0001 +0.0001 +0.034578 +0.080525 +0.21888 +0.2316 +0.1878 +0.27851 +0.26458 +0.20002 +0.17412 +0.22833 +0.2359 +0.26649 +0.20602 +0.23089 +0.24477 +0.29291 +0.29806 +0.27908 +0.32952 +0.27044 +0.33076 +0.28322 +0.28203 +0.33973 +0.26406 +0.27088 +0.24229 +0.23061 +0.19545 +0.087169 +0.05468 +0.039091 +0.014275 +0.24778 +0.16168 +0.15496 +0.28167 +0.2525 +0.20105 +0.2013 +0.23534 +0.25158 +0.26757 +0.23633 +0.28009 +0.20994 +0.21195 +0.19935 +0.24256 +0.30897 +0.07907 +0.20569 +0.2599 +0.11067 +0.018214 +0.0001 +0.016239 +0.035038 +0.01959 +0.040685 +0.021912 +0.13251 +0.23492 +0.20922 +0.22635 +0.30566 +0.25936 +0.16321 +0.1582 +0.25826 +0.29236 +0.27182 +0.17888 +0.28172 +0.34766 +0.32263 +0.26806 +0.26558 +0.3503 +0.29236 +0.27736 +0.26497 +0.24355 +0.33691 +0.25026 +0.27255 +0.21902 +0.2697 +0.088447 +0.052836 +0.10955 +0.01446 +0.002116 +0.0001 +0.22394 +0.1634 +0.14138 +0.13303 +0.19761 +0.17252 +0.18496 +0.25271 +0.26125 +0.24843 +0.30567 +0.23711 +0.21823 +0.20457 +0.26492 +0.29542 +0.15171 +0.07061 +0.087443 +0.25344 +0.23487 +0.007284 +0.005826 +0.072397 +0.067566 +0.056776 +0.030822 +0.11795 +0.21513 +0.2501 +0.21779 +0.28062 +0.23538 +0.20818 +0.20604 +0.23086 +0.30109 +0.25941 +0.21122 +0.33388 +0.34261 +0.32938 +0.28392 +0.25683 +0.31339 +0.31412 +0.28249 +0.27619 +0.25919 +0.27117 +0.23928 +0.2574 +0.24176 +0.19981 +0.0001 +0.047075 +0.033595 +0.0001 +0.0001 +0.0001 +0.2121 +0.18284 +0.13621 +0.14561 +0.13095 +0.1435 +0.20248 +0.19201 +0.29067 +0.27145 +0.33488 +0.2149 +0.35731 +0.063148 +0.16415 +0.30425 +0.27855 +0.27291 +0.078221 +0.24409 +0.27461 +0.086283 +0.081187 +0.069993 +0.070227 +0.080777 +0.035938 +0.056604 +0.23391 +0.21853 +0.21174 +0.29599 +0.23822 +0.23131 +0.23553 +0.23556 +0.25862 +0.22411 +0.29099 +0.30104 +0.34389 +0.33863 +0.29165 +0.25414 +0.24149 +0.27723 +0.32329 +0.2713 +0.30033 +0.25988 +0.18424 +0.12665 +0.1994 +0.23211 +0.18883 +0.0997 +0.30794 +0.28135 +0.30003 +0.30513 +0.21295 +0.18138 +0.23998 +0.12238 +0.14847 +0.1458 +0.24955 +0.20274 +0.25195 +0.27162 +0.20243 +0.2794 +0.32181 +0.28542 +0.14981 +0.14998 +0.27611 +0.28379 +0.23913 +0.26597 +0.26624 +0.10352 +0.13882 +0.026945 +0.017382 +0.11045 +0.10978 +0.30117 +0.24519 +0.23407 +0.20722 +0.25279 +0.24599 +0.25389 +0.19934 +0.25297 +0.15481 +0.26795 +0.28397 +0.28304 +0.33856 +0.35456 +0.3337 +0.25733 +0.23708 +0.30296 +0.30148 +0.050383 +0.21421 +0.20627 +0.20622 +0.16119 +0.21083 +0.22976 +0.33964 +0.32545 +0.26559 +0.26515 +0.30701 +0.21285 +0.21763 +0.19885 +0.20582 +0.26494 +0.15045 +0.13982 +0.25107 +0.22016 +0.25453 +0.22415 +0.16145 +0.27035 +0.30937 +0.29012 +0.33032 +0.14088 +0.16448 +0.12768 +0.27743 +0.21701 +0.20857 +0.212 +0.10783 +0.10183 +0.11479 +0.12074 +0.29172 +0.31315 +0.26914 +0.22523 +0.19722 +0.2363 +0.23827 +0.24961 +0.24468 +0.2504 +0.10529 +0.24491 +0.25603 +0.28475 +0.33781 +0.32939 +0.26564 +0.22699 +0.20762 +0.23677 +0.25056 +0.27112 +0.26125 +0.23034 +0.23303 +0.18802 +0.18902 +0.3164 +0.32392 +0.34719 +0.23468 +0.24198 +0.2353 +0.23133 +0.24606 +0.17241 +0.20559 +0.25972 +0.2782 +0.12885 +0.25218 +0.21907 +0.24489 +0.25801 +0.17496 +0.032743 +0.023565 +0.31408 +0.28416 +0.2855 +0.31484 +0.1101 +0.11096 +0.18171 +0.22298 +0.2327 +0.15019 +0.29087 +0.12925 +0.2783 +0.26323 +0.26638 +0.22904 +0.23315 +0.21531 +0.26487 +0.22541 +0.26176 +0.20017 +0.18361 +0.12137 +0.19501 +0.26154 +0.25613 +0.38526 +0.35632 +0.26748 +0.24513 +0.20147 +0.1983 +0.23295 +0.26819 +0.25501 +0.23283 +0.21931 +0.18856 +0.3385 +0.34026 +0.342 +0.31147 +0.26065 +0.23113 +0.26605 +0.25543 +0.24361 +0.17445 +0.17563 +0.21013 +0.2544 +0.27304 +0.24638 +0.2286 +0.28128 +0.28615 +0.19899 +0.048957 +0.045531 +0.0001 +0.33483 +0.26154 +0.34864 +0.33013 +0.17825 +0.20738 +0.26197 +0.1829 +0.27727 +0.30801 +0.23985 +0.22202 +0.24985 +0.24594 +0.21238 +0.23388 +0.21992 +0.22497 +0.26183 +0.25137 +0.042815 +0.22264 +0.15133 +0.21361 +0.28987 +0.30748 +0.3534 +0.32398 +0.26834 +0.24725 +0.19673 +0.22364 +0.20503 +0.20758 +0.19572 +0.19919 +0.1904 +0.2954 +0.34468 +0.31029 +0.32819 +0.26466 +0.23541 +0.21377 +0.25632 +0.24383 +0.18545 +0.16135 +0.17005 +0.18956 +0.24671 +0.252 +0.26218 +0.30439 +0.28985 +0.18489 +0.21648 +0.041318 +0.092712 +0.066144 +0.29798 +0.34907 +0.28579 +0.1896 +0.18917 +0.097665 +0.050431 +0.018204 +0.27504 +0.27283 +0.24073 +0.20517 +0.21785 +0.2379 +0.19742 +0.22385 +0.26031 +0.24348 +0.30288 +0.2763 +0.30023 +0.17557 +0.18126 +0.23658 +0.3425 +0.27313 +0.031816 +0.032984 +0.29661 +0.27721 +0.22227 +0.23159 +0.18944 +0.17404 +0.15503 +0.20092 +0.20941 +0.33007 +0.35916 +0.18746 +0.20009 +0.27279 +0.24854 +0.21219 +0.25294 +0.088953 +0.077796 +0.25382 +0.22287 +0.17789 +0.23359 +0.21946 +0.11495 +0.28549 +0.23777 +0.1704 +0.23307 +0.25261 +0.2519 +0.29963 +0.33107 +0.36481 +0.35589 +0.37036 +0.4 +0.4 +0.4 +0.18577 +0.2106 +0.30427 +0.24745 +0.14014 +0.19702 +0.20436 +0.20864 +0.31266 +0.30103 +0.23889 +0.29877 +0.27093 +0.28207 +0.26095 +0.15411 +0.21668 +0.13423 +0.21062 +0.022725 +0.038918 +0.20671 +0.25975 +0.21827 +0.22764 +0.21267 +0.15286 +0.11538 +0.19249 +0.20432 +0.31556 +0.3654 +0.19881 +0.19716 +0.25998 +0.25463 +0.22484 +0.29169 +0.29761 +0.26936 +0.20763 +0.19981 +0.20221 +0.14217 +0.21361 +0.13374 +0.2314 +0.21411 +0.20268 +0.24305 +0.22177 +0.26205 +0.28802 +0.11192 +0.077037 +0.053057 +0.4 +0.4 +0.4 +0.4 +0.4 +0.23055 +0.24516 +0.24323 +0.19243 +0.21227 +0.20562 +0.28351 +0.20637 +0.26967 +0.284 +0.25899 +0.29453 +0.04807 +0.2664 +0.37872 +0.19465 +0.14993 +0.22163 +0.11122 +0.21567 +0.22612 +0.1799 +0.23288 +0.19205 +0.26723 +0.1219 +0.11536 +0.18551 +0.18788 +0.28727 +0.31843 +0.21063 +0.20485 +0.24317 +0.25937 +0.24852 +0.32001 +0.26685 +0.28674 +0.21991 +0.22076 +0.175 +0.16512 +0.16812 +0.039856 +0.24663 +0.2179 +0.23736 +0.18861 +0.23062 +0.062332 +0.068167 +0.07122 +0.10733 +0.0001 +0.007449 +0.29675 +0.4 +0.4 +0.4 +0.4 +0.22207 +0.23112 +0.20694 +0.24136 +0.2245 +0.20135 +0.25995 +0.045065 +0.069958 +0.023766 +0.0001 +0.013156 +0.19359 +0.4 +0.30645 +0.15873 +0.20199 +0.11066 +0.18125 +0.20765 +0.16556 +0.22124 +0.17988 +0.26242 +0.33294 +0.11139 +0.15225 +0.18319 +0.2132 +0.29643 +0.19547 +0.26788 +0.2864 +0.24884 +0.29256 +0.30287 +0.28296 +0.27699 +0.20405 +0.23872 +0.14838 +0.0001 +0.25344 +0.26798 +0.23509 +0.24777 +0.22103 +0.18227 +0.07652 +0.032325 +0.10412 +0.12459 +0.049662 +0.058835 +0.04383 +0.30459 +0.24959 +0.3884 +0.38296 +0.36417 +0.36251 +0.25834 +0.20981 +0.23855 +0.24514 +0.26823 +0.20369 +0.16882 +0.066668 +0.064846 +0.013689 +0.032038 +0.35008 +0.35797 +0.31069 +0.29249 +0.25862 +0.094015 +0.083049 +0.18502 +0.13035 +0.15857 +0.21203 +0.2992 +0.34086 +0.12363 +0.16402 +0.185 +0.21618 +0.28466 +0.23036 +0.28584 +0.26642 +0.23913 +0.2763 +0.31229 +0.29428 +0.19312 +0.18958 +0.016123 +0.2483 +0.21116 +0.26792 +0.27557 +0.29392 +0.2475 +0.20129 +0.068408 +0.077786 +0.067485 +0.022065 +0.064429 +0.0001 +0.023867 +0.22012 +0.27249 +0.23648 +0.37839 +0.33437 +0.3663 +0.36982 +0.2708 +0.22968 +0.26221 +0.3523 +0.27648 +0.026637 +0.025591 +0.16834 +0.024246 +0.002478 +0.0001 +0.34026 +0.33446 +0.34141 +0.26267 +0.27059 +0.22655 +0.077379 +0.1629 +0.13222 +0.17987 +0.27183 +0.29695 +0.31706 +0.13584 +0.15324 +0.14486 +0.25539 +0.19882 +0.12354 +0.31897 +0.27887 +0.24691 +0.31833 +0.35117 +0.26118 +0.25864 +0.042058 +0.030788 +0.26489 +0.22118 +0.28077 +0.074916 +0.053434 +0.28587 +0.21088 +0.094293 +0.099078 +0.081569 +0.035512 +0.051782 +0.0001 +0.05769 +0.22765 +0.2737 +0.21671 +0.38157 +0.36069 +0.32881 +0.36491 +0.2655 +0.326 +0.32513 +0.31495 +0.3024 +0.2733 +0.057404 +0.12893 +0.070567 +0.023793 +0.030308 +0.33378 +0.34735 +0.30906 +0.32356 +0.23738 +0.21411 +0.28408 +0.28776 +0.26348 +0.33971 +0.26488 +0.28246 +0.13479 +0.16056 +0.14683 +0.14222 +0.00981 +0.053193 +0.14667 +0.28908 +0.31064 +0.27178 +0.32002 +0.30553 +0.2656 +0.24093 +0.054197 +0.034824 +0.24662 +0.21711 +0.28218 +0.062809 +0.28275 +0.28134 +0.2229 +0.19733 +0.10236 +0.089712 +0.09131 +0.071544 +0.028618 +0.069352 +0.071875 +0.30433 +0.28024 +0.38253 +0.4 +0.35452 +0.363 +0.17254 +0.1879 +0.32279 +0.29991 +0.32479 +0.25374 +0.27343 +0.089295 +0.14473 +0.12867 +0.089765 +0.32265 +0.37299 +0.33686 +0.33737 +0.30005 +0.33775 +0.28924 +0.17773 +0.24845 +0.35136 +0.25216 +0.15643 +0.1384 +0.14205 +0.15376 +0.15203 +0.06325 +0.053392 +0.19373 +0.22679 +0.17251 +0.29946 +0.30395 +0.35886 +0.32598 +0.27933 +0.22537 +0.23675 +0.24155 +0.2459 +0.28134 +0.028757 +0.11636 +0.26094 +0.21531 +0.245 +0.11331 +0.074273 +0.021055 +0.27119 +0.24237 +0.27491 +0.26702 +0.31016 +0.26559 +0.21529 +0.39587 +0.37703 +0.35539 +0.15841 +0.2127 +0.10647 +0.30868 +0.31575 +0.30839 +0.28581 +0.30744 +0.11383 +0.058999 +0.055503 +0.34043 +0.4 +0.32828 +0.31885 +0.31415 +0.1683 +0.21356 +0.21248 +0.23038 +0.31683 +0.33532 +0.3054 +0.312 +0.19126 +0.15052 +0.17042 +0.015128 +0.29672 +0.19629 +0.18241 +0.13783 +0.20325 +0.31189 +0.39083 +0.33512 +0.33041 +0.29113 +0.2167 +0.23272 +0.22402 +0.065266 +0.058641 +0.26048 +0.21191 +0.2183 +0.2422 +0.24273 +0.23717 +0.28794 +0.28348 +0.25522 +0.29128 +0.26761 +0.21753 +0.18844 +0.20067 +0.17694 +0.38034 +0.4 +0.36518 +0.36223 +0.19499 +0.29628 +0.30463 +0.29273 +0.31043 +0.29682 +0.1256 +0.087186 +0.1182 +0.33019 +0.4 +0.30499 +0.307 +0.19165 +0.18022 +0.20787 +0.22091 +0.4 +0.32878 +0.32337 +0.29767 +0.29565 +0.25698 +0.32532 +0.21823 +0.1259 +0.24692 +0.19023 +0.19725 +0.1845 +0.22477 +0.24228 +0.38117 +0.33264 +0.31186 +0.30613 +0.24022 +0.22143 +0.20197 +0.064677 +0.022436 +0.056288 +0.22377 +0.21984 +0.31065 +0.31617 +0.3484 +0.38249 +0.32277 +0.32387 +0.31471 +0.077633 +0.24024 +0.21413 +0.17263 +0.32877 +0.33967 +0.38318 +0.33898 +0.38044 +0.22421 +0.053981 +0.26763 +0.30334 +0.32148 +0.32888 +0.26565 +0.14594 +0.12076 +0.3079 +0.39101 +0.21099 +0.16204 +0.13908 +0.17466 +0.18255 +0.21338 +0.38975 +0.31972 +0.34732 +0.31622 +0.28224 +0.27622 +0.2786 +0.23477 +0.26572 +0.21813 +0.18159 +0.20794 +0.23865 +0.31748 +0.19807 +0.1647 +0.34384 +0.31377 +0.30574 +0.21768 +0.19915 +0.18035 +0.085467 +0.052067 +0.21901 +0.21712 +0.29518 +0.29089 +0.28255 +0.33872 +0.24066 +0.25305 +0.28276 +0.1256 +0.099953 +0.2216 +0.22644 +0.21221 +0.34787 +0.36518 +0.39527 +0.34791 +0.39161 +0.2279 +0.056402 +0.13299 +0.32002 +0.28942 +0.33555 +0.30478 +0.16203 +0.1475 +0.29677 +0.28093 +0.24827 +0.18157 +0.1521 +0.16444 +0.1932 +0.2116 +0.23729 +0.29677 +0.37988 +0.30478 +0.28339 +0.25567 +0.31298 +0.26369 +0.26835 +0.242 +0.1687 +0.26803 +0.23652 +0.31127 +0.33246 +0.15271 +0.33712 +0.30438 +0.30286 +0.23003 +0.14431 +0.20672 +0.25927 +0.18149 +0.21968 +0.22317 +0.29412 +0.28125 +0.32257 +0.28824 +0.24728 +0.25739 +0.0001 +0.048539 +0.060858 +0.078375 +0.24214 +0.3401 +0.34583 +0.33681 +0.38162 +0.36261 +0.37406 +0.25974 +0.23799 +0.10727 +0.30752 +0.26546 +0.31037 +0.31446 +0.28469 +0.080744 +0.27694 +0.20373 +0.24161 +0.21086 +0.17187 +0.17727 +0.21521 +0.22742 +0.0001 +0.2757 +0.33667 +0.30781 +0.30562 +0.21539 +0.30431 +0.27169 +0.28232 +0.22798 +0.21737 +0.16957 +0.097303 +0.29528 +0.29843 +0.31813 +0.16003 +0.27942 +0.28424 +0.23073 +0.29818 +0.38142 +0.2452 +0.18874 +0.22311 +0.23868 +0.12949 +0.13008 +0.32653 +0.29002 +0.076296 +0.040473 +0.0001 +0.0001 +0.029249 +0.057263 +0.31907 +0.33274 +0.36105 +0.35688 +0.36219 +0.34065 +0.32994 +0.25256 +0.26722 +0.24908 +0.30251 +0.26093 +0.2918 +0.30025 +0.32848 +0.074898 +0.22417 +0.17486 +0.22654 +0.19959 +0.19977 +0.19956 +0.20298 +0.21641 +0.23463 +0.28687 +0.19081 +0.30214 +0.31095 +0.27425 +0.32626 +0.31673 +0.304 +0.23334 +0.267 +0.19594 +0.31885 +0.30954 +0.28289 +0.36666 +0.37723 +0.13338 +0.29098 +0.32083 +0.31976 +0.3711 +0.21649 +0.12256 +0.12089 +0.1599 +0.099952 +0.27218 +0.2923 +0.2981 +0.01672 +0.046593 +0.014831 +0.020652 +0.02976 +0.27954 +0.27952 +0.31493 +0.36439 +0.35907 +0.3291 +0.33052 +0.25287 +0.22029 +0.24375 +0.24109 +0.29851 +0.298 +0.26266 +0.28485 +0.32375 +0.052186 +0.24282 +0.2194 +0.19987 +0.30434 +0.20184 +0.20264 +0.21906 +0.20576 +0.21237 +0.2866 +0.23653 +0.31733 +0.29393 +0.29147 +0.37668 +0.33016 +0.30908 +0.23404 +0.20536 +0.22737 +0.29675 +0.26037 +0.28754 +0.39294 +0.37095 +0.1485 +0.14444 +0.2414 +0.2337 +0.27535 +0.19591 +0.12779 +0.10369 +0.1646 +0.10988 +0.26852 +0.29194 +0.0001 +0.021117 +0.043858 +0.051763 +0.0001 +0.24326 +0.24458 +0.25531 +0.3224 +0.28098 +0.31827 +0.27235 +0.26463 +0.2262 +0.21161 +0.22106 +0.2368 +0.22408 +0.27363 +0.24481 +0.30304 +0.34155 +0.052966 +0.2099 +0.17514 +0.31255 +0.20094 +0.19032 +0.21649 +0.17756 +0.20101 +0.22727 +0.27761 +0.24425 +0.31766 +0.34126 +0.29164 +0.36879 +0.28438 +0.28244 +0.23667 +0.19307 +0.18774 +0.38872 +0.26523 +0.30547 +0.35032 +0.14108 +0.12885 +0.1455 +0.25727 +0.24014 +0.15188 +0.22297 +0.1339 +0.13018 +0.18696 +0.28413 +0.29274 +0.2689 +0.0001 +0.038052 +0.084013 +0.001213 +0.017729 +0.21405 +0.26445 +0.273 +0.31445 +0.32467 +0.29194 +0.21573 +0.25812 +0.24693 +0.065937 +0.19608 +0.22603 +0.22539 +0.19272 +0.28512 +0.27017 +0.33909 +0.039837 +0.1273 +0.2784 +0.31858 +0.19508 +0.1907 +0.19013 +0.20395 +0.19591 +0.24251 +0.26201 +0.23578 +0.33042 +0.34849 +0.2954 +0.32173 +0.27733 +0.26062 +0.26311 +0.20233 +0.22517 +0.34497 +0.0001 +0.27847 +0.33438 +0.13911 +0.13138 +0.13989 +0.1687 +0.2295 +0.18446 +0.15646 +0.23837 +0.22701 +0.2802 +0.29309 +0.3033 +0.26886 +0.037871 +0.025418 +0.0001 +0.0001 +0.19211 +0.22254 +0.24079 +0.27385 +0.29917 +0.13699 +0.24215 +0.22131 +0.22712 +0.29374 +0.25656 +0.026052 +0.23296 +0.23404 +0.19862 +0.21958 +0.21177 +0.35954 +0.0001 +0.18949 +0.23177 +0.30985 +0.28077 +0.19745 +0.26164 +0.24228 +0.19952 +0.21941 +0.26196 +0.22967 +0.25413 +0.35979 +0.28781 +0.090248 +0.28164 +0.29839 +0.2733 +0.21876 +0.25797 +0.4 +0.2867 +0.28329 +0.29778 +0.13409 +0.16461 +0.15537 +0.1676 +0.15695 +0.32675 +0.17434 +0.21576 +0.32218 +0.25443 +0.30041 +0.26543 +0.24651 +0.057455 +0.082285 +0.070295 +0.25037 +0.22051 +0.20612 +0.23638 +0.27466 +0.33484 +0.15001 +0.25151 +0.2782 +0.221 +0.27923 +0.23118 +0.19473 +0.22352 +0.24358 +0.23519 +0.19929 +0.21696 +0.07882 +0.000271 +0.19543 +0.21875 +0.1737 +0.070113 +0.32095 +0.25158 +0.21892 +0.20533 +0.24959 +0.25499 +0.21701 +0.29944 +0.26635 +0.058452 +0.030062 +0.27602 +0.28655 +0.27882 +0.27778 +0.24901 +0.3045 +0.28805 +0.29816 +0.19423 +0.16696 +0.14737 +0.15951 +0.14558 +0.15926 +0.30282 +0.16179 +0.2151 +0.28788 +0.30244 +0.22407 +0.28214 +0.22807 +0.26636 +0.03327 +0.26985 +0.25247 +0.2348 +0.1815 +0.23134 +0.064489 +0.20273 +0.13122 +0.067282 +0.30582 +0.23098 +0.22978 +0.20543 +0.22822 +0.21696 +0.20984 +0.23964 +0.2264 +0.20811 +0.20503 +0.0001 +0.17321 +0.20719 +0.16694 +0.26812 +0.30269 +0.25417 +0.2408 +0.24335 +0.2304 +0.25116 +0.24217 +0.32381 +0.24025 +0.22159 +0.0001 +0.31699 +0.26535 +0.25777 +0.27604 +0.28875 +0.29341 +0.33023 +0.16375 +0.19459 +0.15114 +0.12374 +0.15878 +0.11887 +0.1076 +0.29717 +0.34563 +0.23372 +0.29592 +0.29128 +0.24289 +0.21105 +0.003778 +0.28342 +0.28354 +0.23392 +0.28661 +0.23113 +0.21713 +0.20606 +0.083148 +0.12349 +0.020913 +0.02038 +0.34213 +0.16849 +0.15582 +0.17529 +0.18691 +0.21054 +0.20419 +0.19984 +0.17723 +0.19068 +0.21072 +0.23299 +0.22846 +0.27042 +0.26866 +0.26701 +0.26515 +0.24798 +0.24446 +0.20885 +0.25424 +0.27769 +0.26732 +0.35506 +0.26411 +0.24735 +0.19713 +0.26197 +0.27352 +0.29865 +0.23755 +0.27054 +0.25882 +0.1983 +0.1664 +0.18954 +0.14376 +0.1523 +0.16175 +0.25518 +0.29463 +0.3035 +0.33048 +0.26118 +0.27514 +0.2755 +0.27248 +0.22868 +0.34256 +0.043476 +0.046579 +0.22706 +0.2773 +0.27017 +0.21002 +0.20534 +0.045605 +0.020938 +0.10195 +0.13219 +0.11271 +0.14464 +0.17279 +0.18958 +0.20152 +0.22703 +0.20219 +0.0001 +0.17718 +0.1877 +0.21227 +0.22769 +0.3177 +0.30992 +0.28405 +0.30128 +0.29853 +0.24845 +0.21277 +0.18167 +0.15153 +0.21412 +0.29822 +0.29256 +0.28075 +0.26645 +0.19703 +0.23959 +0.27397 +0.2441 +0.23874 +0.25762 +0.26528 +0.22048 +0.18381 +0.18855 +0.17835 +0.016348 +0.27357 +0.24519 +0.30448 +0.26721 +0.14478 +0.11623 +0.27654 +0.2618 +0.23272 +0.23001 +0.21545 +0.074554 +0.080653 +0.33962 +0.24983 +0.18679 +0.25013 +0.2147 +0.22531 +0.071346 +0.11859 +0.13176 +0.10862 +0.1232 +0.14788 +0.19831 +0.2098 +0.19245 +0.012965 +0.0001 +0.011781 +0.22723 +0.21371 +0.21559 +0.31809 +0.28274 +0.28816 +0.29941 +0.28891 +0.33095 +0.23908 +0.24069 +0.18913 +0.20231 +0.17075 +0.27295 +0.30005 +0.29024 +0.21239 +0.2419 +0.24422 +0.25407 +0.21351 +0.25499 +0.25113 +0.20932 +0.1807 +0.16941 +0.34131 +0.31974 +0.28046 +0.25789 +0.28586 +0.055653 +0.075477 +0.095851 +0.30894 +0.27929 +0.21959 +0.21923 +0.24989 +0.26777 +0.08997 +0.089782 +0.26374 +0.17088 +0.25484 +0.18812 +0.22542 +0.27834 +0.2324 +0.15838 +0.13037 +0.18015 +0.15461 +0.20546 +0.049631 +0.11941 +0.036244 +0.061906 +0.0001 +0.004824 +0.031653 +0.087849 +0.29362 +0.29748 +0.27905 +0.31139 +0.31516 +0.33641 +0.29479 +0.19285 +0.19304 +0.19814 +0.17731 +0.12793 +0.16297 +0.12301 +0.21856 +0.18229 +0.34293 +0.2241 +0.25895 +0.26563 +0.26037 +0.23228 +0.30635 +0.25565 +0.31445 +0.33104 +0.29386 +0.2586 +0.26248 +0.10823 +0.080935 +0.12493 +0.31188 +0.2908 +0.22048 +0.22308 +0.27721 +0.26877 +0.26246 +0.21179 +0.23956 +0.15582 +0.24697 +0.18038 +0.092531 +0.12991 +0.12579 +0.25696 +0.28532 +0.21118 +0.15801 +0.18805 +0.023119 +0.0001 +0.10754 +0.075582 +0.004586 +0.004153 +0.056244 +0.009258 +0.28919 +0.32831 +0.34556 +0.34601 +0.33297 +0.32378 +0.31513 +0.236 +0.26656 +0.18807 +0.17585 +0.11188 +0.14369 +0.15437 +0.23673 +0.24864 +0.2816 +0.31398 +0.30183 +0.27287 +0.25737 +0.28133 +0.29546 +0.2662 +0.30425 +0.29362 +0.32061 +0.093567 +0.12815 +0.1229 +0.15004 +0.11239 +0.29244 +0.28807 +0.22299 +0.23766 +0.23995 +0.26521 +0.20686 +0.30346 +0.20941 +0.17003 +0.22141 +0.17135 +0.095751 +0.067389 +0.11556 +0.081133 +0.30302 +0.25233 +0.28914 +0.16069 +0.14062 +0.071101 +0.078372 +0.073483 +0.064986 +0.02749 +0.050185 +0.027444 +0.3454 +0.32592 +0.28608 +0.33754 +0.35131 +0.266 +0.31442 +0.24852 +0.25008 +0.21591 +0.14633 +0.13209 +0.14829 +0.13891 +0.13079 +0.28617 +0.22833 +0.30606 +0.25176 +0.22794 +0.25161 +0.27232 +0.30183 +0.29557 +0.30033 +0.31397 +0.052323 +0.11003 +0.11932 +0.07731 +0.074499 +0.14097 +0.29202 +0.28643 +0.19653 +0.27406 +0.21811 +0.24573 +0.17325 +0.004265 +0.20379 +0.17521 +0.22979 +0.20022 +0.20757 +0.078771 +0.048415 +0.080821 +0.056754 +0.07309 +0.24721 +0.23407 +0.15713 +0.035209 +0.070879 +0.13215 +0.065149 +0.080996 +0.092078 +0.074218 +0.20577 +0.29478 +0.30316 +0.30101 +0.32033 +0.24937 +0.26775 +0.23342 +0.21403 +0.18757 +0.15795 +0.14957 +0.16176 +0.10289 +0.12797 +0.27607 +0.23862 +0.28959 +0.27118 +0.27193 +0.23326 +0.26995 +0.30326 +0.30446 +0.27614 +0.34854 +0.11518 +0.17289 +0.15286 +0.038479 +0.075704 +0.078003 +0.097303 +0.26943 +0.26713 +0.3053 +0.25964 +0.25949 +0.20896 +0.02331 +0.049791 +0.17298 +0.20369 +0.19295 +0.16403 +0.15162 +0.24188 +0.13666 +0.054771 +0.067916 +0.16089 +0.23022 +0.24193 +0.23191 +0.19938 +0.12129 +0.071811 +0.10687 +0.039491 +0.0001 +0.031878 +0.20557 +0.27297 +0.29981 +0.3669 +0.39594 +0.24479 +0.21946 +0.20797 +0.18224 +0.18547 +0.1386 +0.14351 +0.12955 +0.24908 +0.29725 +0.23993 +0.24284 +0.29128 +0.30002 +0.22299 +0.25607 +0.27867 +0.27024 +0.31027 +0.22408 +0.25765 +0.16104 +0.086681 +0.12654 +0.10464 +0.24206 +0.27607 +0.31502 +0.28188 +0.35036 +0.29154 +0.24327 +0.20081 +0.15938 +0.25532 +0.094959 +0.20046 +0.19499 +0.179 +0.15896 +0.13255 +0.33896 +0.36808 +0.085008 +0.043541 +0.17549 +0.17714 +0.20171 +0.23591 +0.26209 +0.064579 +0.08987 +0.039286 +0.033799 +0.022537 +0.18552 +0.21207 +0.24824 +0.37311 +0.38124 +0.34084 +0.34958 +0.19062 +0.18452 +0.19615 +0.13854 +0.16726 +0.12352 +0.2524 +0.28961 +0.23755 +0.294 +0.28794 +0.28051 +0.24828 +0.23343 +0.22752 +0.23113 +0.17864 +0.19729 +0.21071 +0.24234 +0.10251 +0.085541 +0.093309 +0.22727 +0.30361 +0.29806 +0.2797 +0.30877 +0.30617 +0.19355 +0.15537 +0.17375 +0.26429 +0.28669 +0.18067 +0.18282 +0.1871 +0.17013 +0.13458 +0.33468 +0.38436 +0.32186 +0.3313 +0.25311 +0.19622 +0.21124 +0.25786 +0.27952 +0.3166 +0.11542 +0.050501 +0.04051 +0.26622 +0.22093 +0.23172 +0.23192 +0.23914 +0.35712 +0.32046 +0.34383 +0.33658 +0.19349 +0.20902 +0.11045 +0.1632 +0.11392 +0.20546 +0.065993 +0.26984 +0.31716 +0.2788 +0.2855 +0.27403 +0.26194 +0.26698 +0.15976 +0.17082 +0.21311 +0.18627 +0.24771 +0.28893 +0.074987 +0.18481 +0.18398 +0.28835 +0.33487 +0.29229 +0.30163 +0.21717 +0.19276 +0.17057 +0.17367 +0.27165 +0.28806 +0.17176 +0.16532 +0.153 +0.16693 +0.088651 +0.12518 +0.34909 +0.31306 +0.36175 +0.23021 +0.22467 +0.15204 +0.25237 +0.29089 +0.3164 +0.027274 +0.000969 +0.001982 +0.27562 +0.24149 +0.21893 +0.2702 +0.25644 +0.22379 +0.27186 +0.30014 +0.32174 +0.35059 +0.23312 +0.2256 +0.13583 +0.28952 +0.2174 +0.24949 +0.27937 +0.32171 +0.2825 +0.26242 +0.25805 +0.28804 +0.27701 +0.24517 +0.19664 +0.20773 +0.16278 +0.25909 +0.28325 +0.12402 +0.17704 +0.17346 +0.31381 +0.3102 +0.28624 +0.28521 +0.21629 +0.17852 +0.16152 +0.20733 +0.045343 +0.077592 +0.13978 +0.16123 +0.17452 +0.12945 +0.099728 +0.33081 +0.36583 +0.2979 +0.34088 +0.19867 +0.15977 +0.13696 +0.26192 +0.29183 +0.27093 +0.078182 +0.048692 +0.035013 +0.22048 +0.20828 +0.21625 +0.24838 +0.23278 +0.25361 +0.26602 +0.29951 +0.29598 +0.30327 +0.27132 +0.23971 +0.32911 +0.12579 +0.1218 +0.29584 +0.28198 +0.32419 +0.24614 +0.24664 +0.25476 +0.30686 +0.23638 +0.30171 +0.17352 +0.26915 +0.22936 +0.25183 +0.28481 +0.18929 +0.19198 +0.18664 +0.30907 +0.33437 +0.29652 +0.13408 +0.17046 +0.15989 +0.14523 +0.18508 +0.19991 +0.14234 +0.15236 +0.17569 +0.16279 +0.14186 +0.072002 +0.3056 +0.36338 +0.31272 +0.13856 +0.19328 +0.21026 +0.18636 +0.25638 +0.29891 +0.0001 +0.0001 +0.061231 +0.061499 +0.23192 +0.18179 +0.23202 +0.22752 +0.22495 +0.23471 +0.23368 +0.21768 +0.25076 +0.23224 +0.26525 +0.25246 +0.30524 +0.30496 +0.18704 +0.29196 +0.3045 +0.30218 +0.23812 +0.2669 +0.23467 +0.29816 +0.29132 +0.22679 +0.2977 +0.30415 +0.21777 +0.09225 +0.12537 +0.1815 +0.19446 +0.20735 +0.27605 +0.28567 +0.060103 +0.11382 +0.17361 +0.16545 +0.13826 +0.17282 +0.18643 +0.20155 +0.1565 +0.20139 +0.15445 +0.12174 +0.32205 +0.32393 +0.16182 +0.14938 +0.16242 +0.17891 +0.20166 +0.18748 +0.067393 +0.052924 +0.0001 +0.0001 +0.10153 +0.083003 +0.17197 +0.20469 +0.19646 +0.24318 +0.21691 +0.27015 +0.23736 +0.21585 +0.24952 +0.23492 +0.23891 +0.26339 +0.30591 +0.25819 +0.17587 +0.31221 +0.30314 +0.30186 +0.26123 +0.28831 +0.24996 +0.33001 +0.27883 +0.28679 +0.28239 +0.22107 +0.26521 +0.070639 +0.14777 +0.16791 +0.2439 +0.20984 +0.2633 +0.044169 +0.069948 +0.049491 +0.17771 +0.19166 +0.13617 +0.17146 +0.20803 +0.28636 +0.22822 +0.19658 +0.15395 +0.34635 +0.32809 +0.13803 +0.18259 +0.14 +0.14672 +0.12216 +0.083255 +0.081877 +0.085277 +0.067064 +0.037438 +0.040225 +0.036183 +0.086034 +0.15515 +0.17809 +0.23337 +0.24638 +0.30555 +0.24833 +0.24478 +0.20518 +0.26357 +0.24826 +0.28415 +0.25959 +0.33043 +0.27602 +0.27977 +0.32841 +0.30268 +0.29239 +0.28993 +0.28532 +0.28875 +0.3639 +0.26128 +0.21562 +0.27914 +0.091206 +0.082528 +0.10132 +0.16333 +0.19754 +0.23611 +0.2384 +0.25859 +0.044452 +0.028833 +0.0001 +0.17574 +0.15733 +0.15391 +0.17802 +0.22596 +0.26922 +0.23202 +0.2004 +0.15586 +0.15884 +0.1982 +0.17488 +0.18443 +0.16087 +0.15905 +0.12676 +0.10411 +0.004997 +0.047565 +0.091766 +0.07026 +0.061582 +0.028085 +0.009847 +0.16174 +0.16884 +0.23983 +0.20044 +0.28364 +0.2487 +0.23761 +0.28256 +0.29039 +0.26157 +0.20254 +0.24996 +0.29674 +0.34029 +0.29873 +0.33945 +0.28756 +0.29233 +0.27965 +0.30425 +0.32071 +0.33224 +0.2827 +0.25967 +0.078258 +0.11733 +0.10103 +0.1532 +0.17738 +0.21637 +0.24047 +0.10522 +0.098695 +0.084956 +0.044311 +0.0001 +0.04512 +0.15432 +0.14655 +0.26871 +0.25104 +0.27235 +0.25788 +0.1607 +0.18909 +0.21178 +0.19198 +0.19167 +0.21016 +0.024161 +0.042042 +0.11632 +0.15313 +0.083352 +0.061332 +0.062033 +0.088549 +0.083708 +0.030844 +0.03871 +0.093835 +0.15061 +0.22703 +0.21105 +0.23777 +0.23369 +0.22348 +0.28228 +0.28036 +0.28695 +0.27076 +0.20816 +0.27672 +0.26314 +0.27774 +0.34398 +0.30155 +0.32559 +0.25364 +0.27372 +0.2726 +0.30868 +0.31997 +0.28557 +0.10574 +0.12587 +0.14032 +0.15908 +0.20959 +0.2261 +0.25228 +0.09257 +0.091821 +0.00544 +0.098801 +0.052131 +0.034978 +0.32173 +0.27513 +0.27686 +0.28196 +0.26358 +0.16894 +0.1864 +0.19465 +0.16822 +0.18154 +0.15998 +0.31884 +0.058708 +0.075721 +0.072739 +0.055151 +0.088133 +0.11464 +0.08773 +0.032783 +0.07611 +0.098682 +0.029645 +0.1181 +0.16586 +0.23162 +0.20041 +0.22239 +0.20483 +0.22631 +0.27058 +0.32601 +0.26968 +0.31918 +0.33567 +0.26513 +0.25751 +0.26146 +0.32755 +0.32933 +0.32432 +0.25083 +0.24927 +0.30992 +0.28669 +0.28756 +0.31826 +0.12601 +0.12009 +0.12959 +0.14988 +0.20385 +0.28263 +0.25277 +0.27347 +0.041372 +0.051799 +0.08779 +0.054085 +0.32885 +0.32079 +0.27715 +0.30507 +0.20492 +0.23659 +0.19157 +0.20381 +0.20349 +0.19898 +0.31065 +0.30025 +0.065132 +0.11507 +0.1268 +0.06978 +0.098154 +0.000559 +0.009784 +0.019661 +0.052294 +0.079918 +0.082371 +0.092684 +0.093299 +0.17526 +0.17483 +0.15336 +0.20833 +0.21643 +0.25187 +0.26861 +0.27066 +0.27694 +0.33105 +0.36747 +0.26619 +0.28439 +0.31184 +0.33757 +0.28825 +0.27646 +0.25737 +0.25481 +0.34623 +0.28896 +0.20833 +0.23254 +0.16669 +0.091768 +0.13925 +0.1416 +0.17542 +0.26039 +0.23932 +0.25942 +0.068885 +0.028661 +0.34463 +0.32265 +0.35274 +0.30336 +0.27304 +0.27346 +0.26089 +0.25579 +0.1753 +0.24914 +0.24599 +0.24782 +0.28731 +0.061436 +0.11794 +0.10406 +0.033471 +0.087101 +0.11234 +0.0001 +0.060055 +0.048104 +0.089312 +0.024873 +0.035104 +0.068793 +0.085135 +0.1321 +0.12484 +0.16453 +0.23174 +0.19657 +0.20591 +0.26503 +0.15836 +0.28359 +0.25727 +0.34335 +0.27218 +0.29823 +0.29887 +0.30451 +0.26737 +0.24409 +0.28271 +0.27459 +0.33288 +0.25617 +0.2245 +0.21388 +0.17517 +0.081404 +0.11188 +0.19133 +0.29134 +0.26615 +0.22878 +0.25547 +0.015252 +0.25994 +0.36472 +0.30566 +0.22599 +0.22872 +0.23466 +0.28759 +0.25612 +0.25886 +0.28014 +0.24162 +0.25683 +0.23031 +0.28827 +0.078547 +0.046156 +0.064222 +0.0001 +0.029972 +0.070715 +0.016699 +0.048382 +0.073467 +0.080614 +0.009339 +0.0001 +0.000539 +0.095081 +0.14696 +0.15425 +0.17155 +0.19552 +0.20491 +0.19648 +0.21444 +0.25638 +0.3019 +0.31311 +0.27272 +0.31942 +0.28813 +0.33043 +0.28633 +0.25296 +0.24602 +0.28643 +0.2307 +0.25601 +0.27198 +0.22627 +0.2353 +0.18475 +0.11887 +0.13505 +0.25712 +0.29905 +0.29014 +0.24308 +0.23669 +0.18697 +0.26138 +0.22816 +0.22038 +0.23992 +0.23525 +0.2299 +0.28728 +0.26245 +0.2809 +0.29061 +0.22411 +0.24905 +0.24777 +0.26118 +0.056835 +0.016486 +0.037831 +0.0001 +0.0001 +0.030391 +0.0001 +0.07138 +0.17088 +0.081756 +0.005509 +0.0001 +0.076787 +0.11324 +0.14809 +0.15223 +0.13736 +0.19167 +0.16185 +0.21253 +0.24244 +0.22782 +0.27566 +0.29368 +0.29316 +0.28281 +0.2967 +0.32633 +0.28569 +0.26816 +0.22618 +0.21894 +0.21531 +0.26706 +0.25522 +0.26856 +0.23766 +0.15645 +0.13402 +0.12838 +0.28324 +0.29781 +0.27975 +0.24096 +0.20743 +0.25189 +0.27396 +0.22738 +0.20824 +0.20936 +0.21952 +0.086842 +0.035232 +0.2483 +0.26635 +0.25876 +0.21988 +0.28051 +0.25052 +0.2718 +0.042661 +0.002153 +0.057242 +0.046652 +0.0001 +0.03887 +0.13176 +0.078474 +0.11201 +0.055036 +0.063983 +0.04826 +0.043991 +0.19746 +0.13718 +0.18064 +0.21238 +0.11488 +0.1301 +0.19995 +0.27837 +0.25768 +0.26723 +0.24406 +0.28068 +0.30995 +0.29087 +0.31377 +0.27654 +0.27095 +0.027297 +0.22499 +0.16603 +0.25111 +0.30207 +0.24176 +0.32309 +0.17129 +0.1515 +0.12689 +0.25841 +0.29334 +0.24254 +0.25156 +0.2166 +0.26148 +0.25615 +0.24186 +0.19827 +0.022891 +0.080331 +0.017243 +0.0001 +0.21829 +0.30202 +0.27576 +0.23998 +0.29561 +0.28915 +0.25364 +0.071623 +0.054216 +0.049665 +0.006147 +0.036134 +0.070422 +0.058376 +0.060452 +0.091808 +0.063578 +0.036646 +0.073358 +0.12375 +0.23194 +0.15261 +0.15782 +0.20592 +0.18537 +0.18954 +0.20783 +0.27142 +0.25789 +0.2709 +0.2596 +0.29518 +0.30272 +0.2656 +0.28019 +0.26542 +0.26914 +0.12387 +0.17181 +0.16518 +0.2667 +0.28604 +0.24478 +0.23407 +0.18 +0.14029 +0.12051 +0.20455 +0.25893 +0.21164 +0.24813 +0.26044 +0.23235 +0.26842 +0.18922 +0.21962 +0.04989 +0.079242 +0.075542 +0.007179 +0.33454 +0.30058 +0.297 +0.2866 +0.27899 +0.29632 +0.26639 +0.2803 +0.031462 +0.031807 +0.041354 +0.050518 +0.067497 +0.034261 +0.029366 +0.090692 +0.091643 +0.025114 +0.038758 +0.09812 +0.25298 +0.26661 +0.4 +0.26297 +0.20199 +0.19656 +0.22467 +0.20129 +0.25261 +0.20958 +0.26311 +0.29087 +0.28816 +0.26418 +0.27994 +0.25916 +0.2995 +0.1392 +0.16368 +0.18324 +0.23899 +0.29226 +0.27643 +0.33204 +0.18151 +0.13439 +0.13246 +0.2069 +0.27373 +0.23054 +0.28664 +0.23234 +0.26881 +0.16997 +0.19104 +0.21108 +0.013669 +0.11145 +0.072926 +0.31642 +0.3073 +0.3182 +0.28882 +0.31676 +0.30168 +0.27948 +0.27927 +0.28407 +0.12822 +0.084005 +0.012004 +0.01754 +0.066084 +0.10824 +0.071328 +0.070013 +0.045027 +0.032209 +0.096907 +0.09168 +0.19842 +0.25724 +0.24863 +0.4 +0.19147 +0.173 +0.20143 +0.19958 +0.27445 +0.21084 +0.21117 +0.22767 +0.28385 +0.2576 +0.25377 +0.2555 +0.17699 +0.16019 +0.15792 +0.17919 +0.23543 +0.24324 +0.28224 +0.30951 +0.21523 +0.14593 +0.15791 +0.22469 +0.18919 +0.30086 +0.29252 +0.21215 +0.25736 +0.17443 +0.17595 +0.1798 +0.1421 +0.063377 +0.29725 +0.27233 +0.29936 +0.29741 +0.30985 +0.31801 +0.28537 +0.28824 +0.27355 +0.25704 +0.34762 +0.080791 +0.1214 +0.094104 +0.13273 +0.073883 +0.082295 +0.061289 +0.0001 +0.06523 +0.098085 +0.1123 +0.21524 +0.12919 +0.24988 +0.21995 +0.079898 +0.18499 +0.22716 +0.19265 +0.22889 +0.21096 +0.20799 +0.19517 +0.29461 +0.28216 +0.27688 +0.24853 +0.18878 +0.23252 +0.15656 +0.19186 +0.24184 +0.23111 +0.28757 +0.31939 +0.19703 +0.11291 +0.16741 +0.21545 +0.2139 +0.2126 +0.27897 +0.223 +0.22273 +0.16283 +0.16509 +0.14625 +0.15182 +0.23864 +0.27647 +0.25224 +0.252 +0.25793 +0.3344 +0.31971 +0.29756 +0.29486 +0.30524 +0.26179 +0.33176 +0.0001 +0.020696 +0.1168 +0.10592 +0.060266 +0.019128 +0.017684 +0.060722 +0.079614 +0.070629 +0.098849 +0.21048 +0.15822 +0.262 +0.20355 +0.22978 +0.17672 +0.25702 +0.2806 +0.24778 +0.23536 +0.20983 +0.21438 +0.22074 +0.29358 +0.25701 +0.25279 +0.20236 +0.20908 +0.143 +0.21081 +0.21936 +0.26224 +0.28729 +0.31045 +0.14693 +0.11361 +0.12804 +0.18595 +0.21142 +0.1081 +0.25913 +0.19897 +0.18372 +0.18032 +0.22073 +0.13767 +0.14011 +0.23226 +0.26374 +0.23351 +0.26364 +0.3402 +0.31918 +0.32584 +0.29474 +0.29435 +0.32296 +0.27031 +0.29744 +0.07639 +0.067639 +0.1067 +0.078687 +0.085448 +0.036031 +0.0001 +0.059555 +0.078754 +0.096521 +0.086022 +0.21088 +0.19864 +0.21781 +0.20603 +0.20415 +0.23062 +0.2107 +0.078956 +0.31742 +0.22687 +0.22765 +0.21188 +0.21379 +0.1581 +0.29004 +0.24432 +0.19901 +0.18524 +0.22079 +0.22849 +0.22048 +0.26565 +0.26657 +0.30802 +0.11466 +0.095852 +0.12872 +0.1405 +0.23019 +0.13755 +0.07328 +0.17854 +0.1463 +0.17843 +0.21501 +0.23081 +0.14766 +0.24764 +0.15792 +0.1748 +0.27462 +0.30007 +0.31503 +0.3373 +0.3344 +0.28293 +0.31479 +0.24021 +0.30152 +0.26486 +0.072521 +0.10548 +0.074254 +0.068433 +0.056307 +0.0001 +0.036687 +0.021201 +0.0357 +0.13118 +0.16998 +0.18474 +0.23824 +0.21081 +0.23969 +0.23253 +0.20002 +0.17332 +0.15484 +0.35479 +0.20429 +0.21543 +0.21158 +0.17208 +0.2254 +0.24535 +0.18881 +0.19575 +0.20133 +0.16159 +0.11641 +0.26078 +0.28726 +0.35346 +0.27023 +0.088274 +0.12752 +0.16896 +0.18691 +0.14458 +0.083355 +0.3404 +0.11446 +0.19179 +0.23264 +0.19727 +0.17946 +0.27431 +0.11407 +0.18227 +0.24691 +0.30578 +0.3276 +0.34397 +0.29989 +0.28737 +0.28777 +0.22236 +0.27605 +0.24808 +0.033039 +0.14852 +0.11737 +0.062543 +0.050796 +0.039055 +0.020766 +0.11406 +0.15853 +0.099994 +0.18589 +0.20488 +0.25525 +0.24619 +0.24837 +0.24548 +0.20242 +0.1911 +0.1484 +0.12154 +0.11492 +0.1962 +0.22228 +0.19047 +0.20649 +0.35734 +0.19432 +0.23062 +0.1752 +0.15043 +0.13936 +0.20487 +0.29276 +0.32592 +0.29667 +0.10812 +0.16719 +0.18391 +0.15644 +0.15883 +0.10816 +0.33383 +0.25923 +0.23611 +0.23828 +0.19131 +0.20316 +0.23386 +0.12641 +0.16876 +0.25263 +0.27365 +0.29314 +0.31678 +0.31068 +0.29115 +0.27475 +0.26789 +0.26013 +0.0001 +0.11941 +0.10654 +0.0001 +0.0001 +0.0001 +0.0001 +0.083213 +0.055197 +0.13856 +0.14887 +0.18323 +0.22066 +0.24967 +0.24593 +0.21705 +0.22992 +0.21817 +0.16546 +0.194 +0.13056 +0.11836 +0.073611 +0.2342 +0.18179 +0.18472 +0.21199 +0.17582 +0.18705 +0.16394 +0.13326 +0.16869 +0.1977 +0.16034 +0.30106 +0.32216 +0.086092 +0.13339 +0.17018 +0.16448 +0.16695 +0.14275 +0.30881 +0.26857 +0.23615 +0.28124 +0.18586 +0.21307 +0.24285 +0.23984 +0.24494 +0.26108 +0.28555 +0.254 +0.32031 +0.29247 +0.26636 +0.29902 +0.29119 +0.097117 +0.08394 +0.081066 +0.055597 +0.075235 +0.0001 +0.0001 +0.0001 +0.044257 +0.063146 +0.113 +0.10458 +0.17194 +0.22852 +0.24313 +0.2123 +0.2178 +0.26289 +0.23865 +0.24905 +0.33819 +0.16889 +0.0922 +0.070207 +0.067865 +0.20736 +0.19083 +0.23974 +0.16545 +0.19099 +0.14802 +0.18362 +0.2044 +0.18532 +0.3163 +0.32349 +0.33107 +0.29757 +0.12477 +0.15222 +0.1876 +0.20532 +0.28568 +0.28682 +0.28496 +0.21852 +0.2586 +0.36635 +0.19934 +0.23087 +0.27458 +0.27435 +0.2756 +0.24843 +0.26018 +0.27515 +0.28701 +0.28391 +0.27453 +0.29684 +0.036273 +0.035065 +0.0001 +0.05485 +0.093792 +0.016438 +0.065881 +0.11004 +0.1115 +0.14094 +0.044499 +0.02085 +0.17976 +0.20247 +0.24778 +0.22263 +0.23667 +0.03458 +0.21278 +0.29495 +0.37146 +0.17252 +0.1893 +0.25109 +0.25948 +0.24883 +0.18281 +0.2 +0.16321 +0.21143 +0.12288 +0.1652 +0.16866 +0.16701 +0.30362 +0.33902 +0.31302 +0.28657 +0.25166 +0.30046 +0.1591 +0.23248 +0.32097 +0.33038 +0.30696 +0.2599 +0.23229 +0.33654 +0.29136 +0.23753 +0.23169 +0.28359 +0.28996 +0.19256 +0.26363 +0.2622 +0.239 +0.25549 +0.0001 +0.015472 +0.045952 +0.045416 +0.0001 +0.066767 +0.070177 +0.052685 +0.065042 +0.074998 +0.14902 +0.0257 +0.070126 +0.040773 +0.18455 +0.23114 +0.22305 +0.23392 +0.25553 +0.25002 +0.2687 +0.15139 +0.16299 +0.15926 +0.18047 +0.23063 +0.23925 +0.25237 +0.20691 +0.18829 +0.17346 +0.2155 +0.13044 +0.16111 +0.192 +0.16435 +0.34937 +0.33379 +0.32067 +0.30204 +0.25934 +0.31387 +0.36777 +0.048142 +0.33104 +0.34217 +0.3146 +0.27925 +0.20682 +0.29661 +0.18395 +0.22139 +0.24429 +0.29001 +0.32848 +0.20769 +0.20501 +0.28013 +0.012246 +0.062176 +0.071009 +0.0001 +0.059509 +0.10218 +0.078849 +0.12899 +0.094953 +0.12071 +0.096578 +0.091524 +0.10919 +0.03272 +0.008325 +0.016611 +0.16657 +0.23421 +0.22432 +0.20928 +0.24555 +0.19407 +0.20955 +0.15564 +0.18107 +0.14004 +0.19451 +0.19079 +0.2393 +0.22491 +0.20633 +0.18989 +0.1528 +0.17607 +0.14524 +0.16172 +0.17924 +0.33825 +0.31589 +0.34815 +0.31172 +0.27528 +0.23454 +0.28055 +0.38893 +0.21909 +0.22162 +0.34145 +0.32405 +0.3109 +0.25614 +0.14215 +0.16624 +0.22732 +0.22565 +0.29809 +0.296 +0.20992 +0.23371 +0.0001 +0.0001 +0.012915 +0.078625 +0.017115 +0.079885 +0.1048 +0.12693 +0.13832 +0.12737 +0.085172 +0.10186 +0.047674 +0.044694 +0.064653 +0.022415 +0.0001 +0.16071 +0.23907 +0.21206 +0.22828 +0.14132 +0.18041 +0.21009 +0.17014 +0.203 +0.18335 +0.14565 +0.23572 +0.20619 +0.22253 +0.19858 +0.18099 +0.13089 +0.20071 +0.14928 +0.14517 +0.23763 +0.15128 +0.30847 +0.3361 +0.33064 +0.23871 +0.23181 +0.27676 +0.34728 +0.22064 +0.2134 +0.18766 +0.3099 +0.30935 +0.18306 +0.20574 +0.18549 +0.23499 +0.26008 +0.27933 +0.25886 +0.065347 +0.076285 +0.014558 +0.01782 +0.032469 +0.096762 +0.080866 +0.051384 +0.058636 +0.099362 +0.11134 +0.13708 +0.069554 +0.090161 +0.11321 +0.088188 +0.1229 +0.091098 +0.086008 +0.1517 +0.21672 +0.20195 +0.23123 +0.17116 +0.19402 +0.19098 +0.24353 +0.26784 +0.37717 +0.3226 +0.22134 +0.21311 +0.20994 +0.19952 +0.21833 +0.11712 +0.1846 +0.17452 +0.16533 +0.3552 +0.32368 +0.31569 +0.29633 +0.31276 +0.21767 +0.22221 +0.31102 +0.21396 +0.23153 +0.24563 +0.28873 +0.21046 +0.22928 +0.16025 +0.22953 +0.18411 +0.22723 +0.26152 +0.27001 +0.17886 +0.12832 +0.058819 +0.05973 +0.025255 +0.032702 +0.058888 +0.049686 +0.008661 +0.061031 +0.085515 +0.13295 +0.096923 +0.052627 +0.10287 +0.10442 +0.11243 +0.093402 +0.13185 +0.036463 +0.16721 +0.22644 +0.19271 +0.28663 +0.19916 +0.18771 +0.19641 +0.20304 +0.25911 +0.33479 +0.29742 +0.23931 +0.21971 +0.20033 +0.19232 +0.33614 +0.37694 +0.28001 +0.15576 +0.17026 +0.34124 +0.32119 +0.33002 +0.30591 +0.27178 +0.19296 +0.067306 +0.072689 +0.23604 +0.26516 +0.22101 +0.19771 +0.23315 +0.23464 +0.10665 +0.19127 +0.19112 +0.21881 +0.069706 +0.08152 +0.085073 +0.094741 +0.084421 +0.11221 +0.1293 +0.087935 +0.071276 +0.053132 +0.053826 +0.008198 +0.006574 +0.053048 +0.11133 +0.10656 +0.18075 +0.1361 +0.076102 +0.1171 +0.094044 +0.061279 +0.17236 +0.24938 +0.15262 +0.15921 +0.18899 +0.1728 +0.18039 +0.21731 +0.26486 +0.33673 +0.33844 +0.24339 +0.19387 +0.23297 +0.25067 +0.35813 +0.1922 +0.17341 +0.13534 +0.26964 +0.32088 +0.30652 +0.3292 +0.31835 +0.076327 +0.099709 +0.20831 +0.046091 +0.24028 +0.2686 +0.14536 +0.18983 +0.24971 +0.22776 +0.089939 +0.16072 +0.26207 +0.084392 +0.085411 +0.072032 +0.077218 +0.026369 +0.06767 +0.11115 +0.14866 +0.096681 +0.072564 +0.013063 +0.011417 +0.03519 +0.063742 +0.027549 +0.10585 +0.080015 +0.10164 +0.13773 +0.11785 +0.16272 +0.11126 +0.005773 +0.20907 +0.26984 +0.15964 +0.16157 +0.18419 +0.15969 +0.18966 +0.20754 +0.25842 +0.29387 +0.20779 +0.2217 +0.24391 +0.23672 +0.27866 +0.19567 +0.18451 +0.18843 +0.27068 +0.25649 +0.29956 +0.26129 +0.22348 +0.12166 +0.015822 +0.1205 +0.094894 +0.055446 +0.2802 +0.2162 +0.17624 +0.15451 +0.24355 +0.24223 +0.21517 +0.22908 +0.27137 +0.0001 +0.039236 +0.047921 +0.066093 +0.060211 +0.043012 +0.088701 +0.057087 +0.1085 +0.039164 +0.075742 +0.10404 +0.015838 +0.083212 +0.091278 +0.11262 +0.059033 +0.15217 +0.13204 +0.073238 +0.10357 +0.027262 +0.016923 +0.21513 +0.19462 +0.13872 +0.15985 +0.17008 +0.16719 +0.18498 +0.21052 +0.24856 +0.20502 +0.1756 +0.21695 +0.19699 +0.25105 +0.18636 +0.15898 +0.18605 +0.20685 +0.28446 +0.23031 +0.27915 +0.1728 +0.047265 +0.064609 +0.012509 +0.085702 +0.059692 +0.072627 +0.27244 +0.19627 +0.17466 +0.18127 +0.21843 +0.27575 +0.2295 +0.22148 +0.27699 +0.22883 +0.021161 +0.028775 +0.080522 +0.058907 +0.050304 +0.15663 +0.079448 +0.13691 +0.088507 +0.033963 +0.036954 +0.040609 +0.014125 +0.084789 +0.079726 +0.021843 +0.092474 +0.11258 +0.092549 +0.041487 +0.015511 +0.008529 +0.23983 +0.1672 +0.17167 +0.16272 +0.15551 +0.17012 +0.19992 +0.19299 +0.2454 +0.17758 +0.16655 +0.16501 +0.20353 +0.24003 +0.19571 +0.26586 +0.20591 +0.1854 +0.17872 +0.22187 +0.18182 +0.14725 +0.067106 +0.051738 +0.019069 +0.027005 +0.30549 +0.33024 +0.23418 +0.2085 +0.20241 +0.17222 +0.21847 +0.27978 +0.21682 +0.19708 +0.24058 +0.23143 +0.2741 +0.007763 +0.12109 +0.18009 +0.042219 +0.08736 +0.10614 +0.15792 +0.054037 +0.040548 +0.10797 +0.0001 +0.079219 +0.0001 +0.11724 +0.043312 +0.10765 +0.13598 +0.071308 +0.006376 +0.0001 +0.043898 +0.26107 +0.19522 +0.17709 +0.14595 +0.13367 +0.17098 +0.21229 +0.14845 +0.20848 +0.17025 +0.12938 +0.20132 +0.14993 +0.23739 +0.21726 +0.27618 +0.23168 +0.33 +0.13701 +0.18617 +0.1484 +0.16047 +0.061062 +0.32973 +0.30915 +0.19236 +0.27819 +0.35443 +0.23411 +0.19088 +0.18535 +0.28338 +0.19822 +0.27857 +0.27344 +0.18483 +0.24961 +0.2136 +0.22519 +0.13071 +0.12021 +0.10858 +0.058363 +0.060307 +0.1127 +0.095618 +0.16402 +0.096579 +0.086765 +0.052234 +0.076626 +0.041742 +0.0001 +0.11221 +0.12171 +0.10991 +0.068758 +0.004681 +0.019622 +0.018476 +0.23624 +0.16928 +0.22073 +0.13776 +0.10247 +0.23975 +0.24378 +0.15199 +0.16711 +0.14923 +0.14511 +0.20695 +0.20903 +0.24015 +0.24932 +0.26253 +0.29183 +0.28476 +0.14818 +0.20606 +0.2184 +0.21667 +0.21276 +0.19737 +0.35514 +0.20621 +0.26337 +0.33858 +0.26478 +0.17712 +0.19647 +0.26317 +0.16131 +0.2234 +0.28936 +0.2626 +0.037921 +0.23672 +0.215 +0.20642 +0.095662 +0.17376 +0.11033 +0.097703 +0.14696 +0.10252 +0.13368 +0.095617 +0.099976 +0.088867 +0.10526 +0.052448 +0.077499 +0.10601 +0.11874 +0.068252 +0.083539 +0.035654 +0.085234 +0.11511 +0.21479 +0.32965 +0.20667 +0.13632 +0.096436 +0.11004 +0.29652 +0.32966 +0.32843 +0.26598 +0.28065 +0.20312 +0.23817 +0.26184 +0.2168 +0.24321 +0.3088 +0.28782 +0.27063 +0.20802 +0.2359 +0.27034 +0.22731 +0.2176 +0.34918 +0.22008 +0.27595 +0.30302 +0.29024 +0.18209 +0.19242 +0.2554 +0.1769 +0.23314 +0.28499 +0.25371 +0.19601 +0.047522 +0.2434 +0.19885 +0.23162 +0.14851 +0.10103 +0.085971 +0.088985 +0.13315 +0.14276 +0.13568 +0.10009 +0.15771 +0.12314 +0.096886 +0.079332 +0.14813 +0.18277 +0.10365 +0.0477 +0.034497 +0.13871 +0.034394 +0.1898 +0.17629 +0.19374 +0.17482 +0.15501 +0.098631 +0.15382 +0.13142 +0.37291 +0.27296 +0.26173 +0.25979 +0.18116 +0.27075 +0.22756 +0.24135 +0.23308 +0.264 +0.29179 +0.18226 +0.24203 +0.24945 +0.22866 +0.21455 +0.31195 +0.23923 +0.25178 +0.28996 +0.29648 +0.29959 +0.1518 +0.25019 +0.18124 +0.25852 +0.27713 +0.19424 +0.16697 +0.14674 +0.077495 +0.22306 +0.24102 +0.23672 +0.057777 +0.064766 +0.049447 +0.15468 +0.071631 +0.018845 +0.028754 +0.088724 +0.12883 +0.10515 +0.080025 +0.09193 +0.053553 +0.074444 +0.070789 +0.04467 +0.027169 +0.032061 +0.19842 +0.24318 +0.21053 +0.18037 +0.14936 +0.064073 +0.13679 +0.27793 +0.36713 +0.25638 +0.24671 +0.23345 +0.1121 +0.23892 +0.20991 +0.23423 +0.24975 +0.29296 +0.21535 +0.24528 +0.22046 +0.2545 +0.23039 +0.21395 +0.030684 +0.27235 +0.25977 +0.28781 +0.29644 +0.017212 +0.17366 +0.24772 +0.18049 +0.27561 +0.26903 +0.21079 +0.1638 +0.21388 +0.11789 +0.12437 +0.24083 +0.25077 +0.2153 +0.0001 +0.0001 +0.12501 +0.066491 +0.0001 +0.0001 +0.053972 +0.11787 +0.13125 +0.043893 +0.097671 +0.06759 +0.03635 +0.12844 +0.066235 +0.06734 +0.054467 +0.23844 +0.19298 +0.26987 +0.19817 +0.12288 +0.062531 +0.13744 +0.12442 +0.27387 +0.25417 +0.20449 +0.21689 +0.14674 +0.16629 +0.19207 +0.22802 +0.26225 +0.31608 +0.24857 +0.25146 +0.24831 +0.15014 +0.22743 +0.2375 +0.0123 +0.053637 +0.10825 +0.02145 +0.10282 +0.074327 +0.1388 +0.23454 +0.16994 +0.29152 +0.27137 +0.18618 +0.13763 +0.21168 +0.22055 +0.10477 +0.067245 +0.24212 +0.22716 +0.29044 +0.01787 +0.11517 +0.046793 +0.0001 +0.031376 +0.038707 +0.18279 +0.17005 +0.085098 +0.051889 +0.0001 +0.017833 +0.055491 +0.052829 +0.027435 +0.00827 +0.19846 +0.22883 +0.3102 +0.1865 +0.11763 +0.072062 +0.12476 +0.15085 +0.28749 +0.24934 +0.24301 +0.23603 +0.15892 +0.13832 +0.1584 +0.10258 +0.24918 +0.33145 +0.38616 +0.3193 +0.25858 +0.11915 +0.16568 +0.21332 +0.24073 +0.060126 +0.083065 +0.087257 +0.096331 +0.097939 +0.14012 +0.22419 +0.31461 +0.27191 +0.26185 +0.18525 +0.15461 +0.17914 +0.1944 +0.089122 +0.041505 +0.21355 +0.2229 +0.30116 +0.21558 +0.031176 +0.087292 +0.079236 +0.023404 +0.124 +0.14605 +0.17625 +0.11058 +0.094061 +0.035211 +0.10714 +0.072961 +0.092538 +0.036031 +0.030659 +0.20867 +0.25125 +0.25089 +0.24805 +0.22469 +0.28306 +0.10424 +0.1686 +0.19631 +0.27534 +0.26735 +0.26992 +0.26708 +0.15876 +0.13608 +0.083012 +0.11027 +0.32152 +0.35579 +0.32001 +0.31071 +0.18493 +0.17761 +0.20013 +0.19637 +0.084338 +0.10673 +0.12199 +0.055108 +0.21877 +0.16335 +0.22928 +0.30162 +0.26496 +0.25979 +0.20092 +0.19134 +0.21911 +0.18639 +0.10986 +0.10046 +0.22542 +0.2457 +0.28638 +0.24438 +0.10571 +0.050681 +0.073807 +0.10694 +0.097329 +0.086505 +0.078838 +0.068901 +0.07425 +0.081644 +0.078978 +0.036191 +0.11216 +0.053396 +0.091471 +0.23045 +0.29088 +0.25165 +0.23049 +0.24159 +0.27833 +0.24701 +0.18254 +0.20756 +0.16719 +0.23919 +0.26612 +0.16554 +0.18151 +0.15245 +0.083726 +0.1266 +0.20407 +0.16715 +0.339 +0.34044 +0.27082 +0.25254 +0.22517 +0.063215 +0.15014 +0.14429 +0.14278 +0.09979 +0.14578 +0.12629 +0.19109 +0.29572 +0.24168 +0.28918 +0.30378 +0.2068 +0.24132 +0.17822 +0.080675 +0.11259 +0.25007 +0.2488 +0.27451 +0.27539 +0.042443 +0.016766 +0.09199 +0.10933 +0.04299 +0.051997 +0.081517 +0.061012 +0.11511 +0.041892 +0.082412 +0.099453 +0.12981 +0.012128 +0.068989 +0.32485 +0.14985 +0.25978 +0.2347 +0.17776 +0.005407 +0.16353 +0.10165 +0.10131 +0.15603 +0.23376 +0.20979 +0.14537 +0.1944 +0.19272 +0.12056 +0.12026 +0.16588 +0.26152 +0.22308 +0.26558 +0.2528 +0.26891 +0.24546 +0.098383 +0.11786 +0.052875 +0.22546 +0.18987 +0.16519 +0.16107 +0.20119 +0.27052 +0.26024 +0.26713 +0.27831 +0.31563 +0.05787 +0.0001 +0.042245 +0.2096 +0.24482 +0.27982 +0.27266 +0.21504 +0.042196 +0.036125 +0.10157 +0.0001 +0.020023 +0.078056 +0.12279 +0.13394 +0.053694 +0.007788 +0.090215 +0.061275 +0.064585 +0.0001 +0.0001 +0.14694 +0.14977 +0.2542 +0.25745 +0.21989 +0.20944 +0.17432 +0.11782 +0.23345 +0.24368 +0.23741 +0.2161 +0.24829 +0.21813 +0.18301 +0.1183 +0.11577 +0.18417 +0.23875 +0.25105 +0.26378 +0.2359 +0.26032 +0.23612 +0.26806 +0.23604 +0.23056 +0.19498 +0.16295 +0.14052 +0.17485 +0.2641 +0.23557 +0.27786 +0.25051 +0.27671 +0.21878 +0.19108 +0.16977 +0.21237 +0.2125 +0.25225 +0.27077 +0.27108 +0.011331 +0.0001 +0.0001 +0.0001 +0.046179 +0.052484 +0.072372 +0.15752 +0.10338 +0.095268 +0.013588 +0.083847 +0.050649 +0.13759 +0.070023 +0.067402 +0.33873 +0.27508 +0.2607 +0.29553 +0.25646 +0.26273 +0.26782 +0.25628 +0.27231 +0.16027 +0.14218 +0.26893 +0.26307 +0.20386 +0.18825 +0.12237 +0.10185 +0.2672 +0.26051 +0.26993 +0.27043 +0.0001 +0.13664 +0.22319 +0.26523 +0.24403 +0.21065 +0.19148 +0.19906 +0.24715 +0.202 +0.24776 +0.26489 +0.23209 +0.26068 +0.26959 +0.22476 +0.20799 +0.15759 +0.24066 +0.27298 +0.24874 +0.24794 +0.12872 +0.062709 +0.084352 +0.043264 +0.09852 +0.076741 +0.062463 +0.068712 +0.093243 +0.061663 +0.085148 +0.076609 +0.11233 +0.048323 +0.072529 +0.16539 +0.15707 +0.30099 +0.28964 +0.27094 +0.30556 +0.23753 +0.24668 +0.2379 +0.14317 +0.20246 +0.1584 +0.15896 +0.25433 +0.19202 +0.199 +0.17445 +0.15568 +0.18923 +0.25772 +0.25446 +0.27848 +0.28162 +0.031034 +0.18374 +0.21393 +0.27504 +0.25679 +0.21149 +0.28835 +0.32013 +0.2262 +0.2109 +0.29169 +0.086238 +0.085654 +0.078285 +0.23638 +0.065071 +0.13879 +0.074616 +0.058438 +0.00348 +0.030991 +0.10174 +0.15367 +0.14641 +0.087964 +0.11511 +0.083472 +0.097552 +0.030787 +0.054675 +0.082358 +0.023924 +0.10771 +0.082451 +0.19674 +0.098007 +0.16547 +0.1199 +0.17162 +0.29746 +0.2734 +0.30625 +0.29319 +0.25631 +0.22481 +0.23537 +0.10553 +0.20286 +0.1791 +0.20422 +0.25128 +0.17163 +0.16992 +0.20044 +0.16368 +0.15079 +0.13951 +0.26923 +0.30593 +0.031542 +0.011508 +0.17647 +0.17379 +0.2703 +0.28549 +0.23953 +0.24522 +0.2575 +0.22947 +0.23037 +0.32314 +0.32196 +0.04638 +0.038076 +0.080399 +0.036712 +0.14148 +0.0954 +0.071028 +0.038938 +0.12932 +0.11566 +0.1236 +0.074663 +0.13689 +0.01827 +0.033008 +0.063636 +0.07047 +0.009419 +0.000392 +0.067813 +0.064963 +0.070211 +0.20137 +0.1259 +0.12492 +0.10998 +0.12104 +0.31329 +0.295 +0.32631 +0.31719 +0.25293 +0.22572 +0.19381 +0.11069 +0.18922 +0.16267 +0.20239 +0.22065 +0.18269 +0.15304 +0.36693 +0.3644 +0.17073 +0.14156 +0.21955 +0.30526 +0.15349 +0.15826 +0.21503 +0.19762 +0.27394 +0.331 +0.22567 +0.2284 +0.25314 +0.2134 +0.23212 +0.31297 +0.10331 +0.097193 +0.070276 +0.098347 +0.11587 +0.11837 +0.064636 +0.083927 +0.1148 +0.15117 +0.078167 +0.0001 +0.044011 +0.10353 +0.10934 +0.08775 +0.076853 +0.084207 +0.032381 +0.0001 +0.10109 +0.070509 +0.052812 +0.090905 +0.11431 +0.11306 +0.077988 +0.11229 +0.26251 +0.30175 +0.32834 +0.27838 +0.23524 +0.22265 +0.16264 +0.1237 +0.17211 +0.17348 +0.17145 +0.23988 +0.19045 +0.19745 +0.15341 +0.34632 +0.18076 +0.13553 +0.20191 +0.29802 +0.31462 +0.19138 +0.21668 +0.23538 +0.25882 +0.28053 +0.27087 +0.2514 +0.28958 +0.28926 +0.29337 +0.28695 +0.12216 +0.11213 +0.085548 +0.11539 +0.087571 +0.12169 +0.067842 +0.052622 +0.066984 +0.095835 +0.077276 +0.069237 +0.12755 +0.15133 +0.12437 +0.097533 +0.091354 +0.12021 +0.02673 +0.063685 +0.092854 +0.083699 +0.053603 +0.13591 +0.10926 +0.062304 +0.1183 +0.19589 +0.29472 +0.28288 +0.27012 +0.26036 +0.22928 +0.23018 +0.21022 +0.16764 +0.18317 +0.22117 +0.17388 +0.21962 +0.19401 +0.19202 +0.17869 +0.35397 +0.32323 +0.1426 +0.14733 +0.10711 +0.15454 +0.16916 +0.19557 +0.19872 +0.21018 +0.24903 +0.23423 +0.26155 +0.27944 +0.31418 +0.28136 +0.098836 +0.10858 +0.093759 +0.078786 +0.077764 +0.076118 +0.088197 +0.023931 +0.1138 +0.044796 +0.13181 +0.10361 +0.14526 +0.081459 +0.097538 +0.11745 +0.048109 +0.080218 +0.11392 +0.10717 +0.082441 +0.078055 +0.026627 +0.069075 +0.096226 +0.04669 +0.084379 +0.14427 +0.11094 +0.25724 +0.27258 +0.28201 +0.23223 +0.23839 +0.23348 +0.22571 +0.1863 +0.19915 +0.23091 +0.22347 +0.1982 +0.19348 +0.19652 +0.22158 +0.19857 +0.32107 +0.15907 +0.14858 +0.11013 +0.097129 +0.19612 +0.23171 +0.2204 +0.2365 +0.26172 +0.26658 +0.24999 +0.25471 +0.32162 +0.05432 +0.051692 +0.045081 +0.069455 +0.12065 +0.085677 +0.0664 +0.028323 +0.071163 +0.040997 +0.11031 +0.10501 +0.072825 +0.037366 +0.11164 +0.18275 +0.14094 +0.11512 +0.095895 +0.11614 +0.13631 +0.11883 +0.038243 +0.075829 +0.0001 +0.03321 +0.077864 +0.092004 +0.090571 +0.088943 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/pres_pvdo.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/pres_pvdo.txt new file mode 100644 index 00000000000..2681766c979 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/pres_pvdo.txt @@ -0,0 +1,3 @@ +2068000 +5516000 +55160000 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/visc_pvdo.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/visc_pvdo.txt new file mode 100644 index 00000000000..a15f9b49dcf --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/visc_pvdo.txt @@ -0,0 +1,3 @@ +0.00285 +0.00299 +0.003 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/xlin.geos b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/xlin.geos new file mode 100644 index 00000000000..3d99dd84d02 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/xlin.geos @@ -0,0 +1,60 @@ +3.048 +9.144 +15.24 +21.336 +27.432 +33.528 +39.624 +45.72 +51.816 +57.912 +64.008 +70.104 +76.2 +82.296 +88.392 +94.488 +100.58 +106.68 +112.78 +118.87 +124.97 +131.06 +137.16 +143.26 +149.35 +155.45 +161.54 +167.64 +173.74 +179.83 +185.93 +192.02 +198.12 +204.22 +210.31 +216.41 +222.5 +228.6 +234.7 +240.79 +246.89 +252.98 +259.08 +265.18 +271.27 +277.37 +283.46 +289.56 +295.66 +301.75 +307.85 +313.94 +320.04 +326.14 +332.23 +338.33 +344.42 +350.52 +356.62 +362.71 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/ylin.geos b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/ylin.geos new file mode 100644 index 00000000000..99a6fec4924 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/ylin.geos @@ -0,0 +1,220 @@ +1.524 +4.572 +7.62 +10.668 +13.716 +16.764 +19.812 +22.86 +25.908 +28.956 +32.004 +35.052 +38.1 +41.148 +44.196 +47.244 +50.292 +53.34 +56.388 +59.436 +62.484 +65.532 +68.58 +71.628 +74.676 +77.724 +80.772 +83.82 +86.868 +89.916 +92.964 +96.012 +99.06 +102.11 +105.16 +108.2 +111.25 +114.3 +117.35 +120.4 +123.44 +126.49 +129.54 +132.59 +135.64 +138.68 +141.73 +144.78 +147.83 +150.88 +153.92 +156.97 +160.02 +163.07 +166.12 +169.16 +172.21 +175.26 +178.31 +181.36 +184.4 +187.45 +190.5 +193.55 +196.6 +199.64 +202.69 +205.74 +208.79 +211.84 +214.88 +217.93 +220.98 +224.03 +227.08 +230.12 +233.17 +236.22 +239.27 +242.32 +245.36 +248.41 +251.46 +254.51 +257.56 +260.6 +263.65 +266.7 +269.75 +272.8 +275.84 +278.89 +281.94 +284.99 +288.04 +291.08 +294.13 +297.18 +300.23 +303.28 +306.32 +309.37 +312.42 +315.47 +318.52 +321.56 +324.61 +327.66 +330.71 +333.76 +336.8 +339.85 +342.9 +345.95 +349 +352.04 +355.09 +358.14 +361.19 +364.24 +367.28 +370.33 +373.38 +376.43 +379.48 +382.52 +385.57 +388.62 +391.67 +394.72 +397.76 +400.81 +403.86 +406.91 +409.96 +413 +416.05 +419.1 +422.15 +425.2 +428.24 +431.29 +434.34 +437.39 +440.44 +443.48 +446.53 +449.58 +452.63 +455.68 +458.72 +461.77 +464.82 +467.87 +470.92 +473.96 +477.01 +480.06 +483.11 +486.16 +489.2 +492.25 +495.3 +498.35 +501.4 +504.44 +507.49 +510.54 +513.59 +516.64 +519.68 +522.73 +525.78 +528.83 +531.88 +534.92 +537.97 +541.02 +544.07 +547.12 +550.16 +553.21 +556.26 +559.31 +562.36 +565.4 +568.45 +571.5 +574.55 +577.6 +580.64 +583.69 +586.74 +589.79 +592.84 +595.88 +598.93 +601.98 +605.03 +608.08 +611.12 +614.17 +617.22 +620.27 +623.32 +626.36 +629.41 +632.46 +635.51 +638.56 +641.6 +644.65 +647.7 +650.75 +653.8 +656.84 +659.89 +662.94 +665.99 +669.04 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/zlin.geos b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/zlin.geos new file mode 100644 index 00000000000..63ff1592a67 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/zlin.geos @@ -0,0 +1 @@ +0.3048 diff --git a/src/coreComponents/linearAlgebra/interfaces/hypre/mgrStrategies/ImmiscibleMultiphaseFVM.hpp b/src/coreComponents/linearAlgebra/interfaces/hypre/mgrStrategies/ImmiscibleMultiphaseFVM.hpp index 1fe5b33f15d..3f05ac5987a 100644 --- a/src/coreComponents/linearAlgebra/interfaces/hypre/mgrStrategies/ImmiscibleMultiphaseFVM.hpp +++ b/src/coreComponents/linearAlgebra/interfaces/hypre/mgrStrategies/ImmiscibleMultiphaseFVM.hpp @@ -58,7 +58,7 @@ class ImmiscibleMultiphaseFVM : public MGRStrategyBase< 1 > // Level 0: eliminate last density which corresponds to the volume constraint equation // m_labels[0].resize( m_numBlocks - 1 ); // std::iota( m_labels[0].begin(), m_labels[0].end(), 0 ); - + // Level 0: eliminate the phase volume fractions m_labels[0].push_back( 0 ); From 3e698b84f77bae87eeb1121b0f555716f1592b7e Mon Sep 17 00:00:00 2001 From: DENEL Bertrand Date: Wed, 30 Oct 2024 18:42:46 -0500 Subject: [PATCH 055/104] Created an ats test from the gravitySegration example. --- ...mmiscibleTwoPhase_GravitySegregation_1d.ats | 18 ++++++++++++++++++ ...mmiscibleTwoPhase_GravitySegregation_1d.xml | 10 +++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_GravitySegregation_1d/immiscibleTwoPhase_GravitySegregation_1d.ats diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_GravitySegregation_1d/immiscibleTwoPhase_GravitySegregation_1d.ats b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_GravitySegregation_1d/immiscibleTwoPhase_GravitySegregation_1d.ats new file mode 100644 index 00000000000..b7f470b932f --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_GravitySegregation_1d/immiscibleTwoPhase_GravitySegregation_1d.ats @@ -0,0 +1,18 @@ +from geos.ats.test_builder import TestDeck, RestartcheckParameters, generate_geos_tests + +restartcheck_params = {} +restartcheck_params['atol'] = 1.0E-8 +restartcheck_params['rtol'] = 1.0E-8 + +decks = [ + TestDeck( + name="immiscibleTwoPhase_GravitySegregation_1d", + description= + 'Test that 2 fluids can be seperated based on gravity.', + partitions=((1, 1, 1), ), + restart_step=0, + check_step=45, + restartcheck_params=RestartcheckParameters(**restartcheck_params)) +] + +generate_geos_tests(decks) diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_GravitySegregation_1d/immiscibleTwoPhase_GravitySegregation_1d.xml b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_GravitySegregation_1d/immiscibleTwoPhase_GravitySegregation_1d.xml index b4390686079..12e6d52f990 100644 --- a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_GravitySegregation_1d/immiscibleTwoPhase_GravitySegregation_1d.xml +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_GravitySegregation_1d/immiscibleTwoPhase_GravitySegregation_1d.xml @@ -49,6 +49,12 @@ + + @@ -128,7 +134,7 @@ name="rockPorosity" defaultReferencePorosity="1.0" referencePressure="0.0" - compressibility="0.0" /> + compressibility="1e-9" /> + From 98cbe14a81ae3875e5ec6ffa303c1a9d8df6f867 Mon Sep 17 00:00:00 2001 From: DENEL Bertrand Date: Thu, 31 Oct 2024 11:50:39 -0500 Subject: [PATCH 056/104] Updated integrated test ID after first dry run. --- .integrated_tests.yaml | 2 +- BASELINE_NOTES.md | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.integrated_tests.yaml b/.integrated_tests.yaml index 2d289765a28..0d6d65574d0 100644 --- a/.integrated_tests.yaml +++ b/.integrated_tests.yaml @@ -1,6 +1,6 @@ baselines: bucket: geosx - baseline: integratedTests/baseline_integratedTests-pr2878-8188-ed2ded2 + baseline: integratedTests/baseline_integratedTests-pr3251-8367-3e698b8 allow_fail: all: '' diff --git a/BASELINE_NOTES.md b/BASELINE_NOTES.md index 65cd8d82bd9..dddfe377cc9 100644 --- a/BASELINE_NOTES.md +++ b/BASELINE_NOTES.md @@ -6,6 +6,10 @@ This file is designed to track changes to the integrated test baselines. Any developer who updates the baseline ID in the .integrated_tests.yaml file is expected to create an entry in this file with the pull request number, date, and their justification for rebaselining. These notes should be in reverse-chronological order, and use the following time format: (YYYY-MM-DD). +PR #3251 (2024-10-31) +===================== +Added tests for the brand new Immiscible Multiphase solver. + PR #2878 (2024-10-17) ===================== Sorted region cellBlocks names alphabetically. Therefore affected ordering of: faceManager/elemSubRegionList, nodeManager/elemList, nodeManager/elemSubRegionList, SurfaceElementSubRegion::fractureElementsToCellSubRegions, field::perforation::reservoirElementSubregion. From 90e8db37aa83816a83dd373552a58c52c13a219e Mon Sep 17 00:00:00 2001 From: DENEL Bertrand Date: Thu, 31 Oct 2024 16:51:08 -0500 Subject: [PATCH 057/104] Added more ats. --- .../immiscibleTwoPhase_CapillaryPressure.ats | 18 ++++++++++++++++++ .../immiscibleTwoPhase_SPE10_layer84.ats | 18 ++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_CapillaryPressure/immiscibleTwoPhase_CapillaryPressure.ats create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/immiscibleTwoPhase_SPE10_layer84.ats diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_CapillaryPressure/immiscibleTwoPhase_CapillaryPressure.ats b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_CapillaryPressure/immiscibleTwoPhase_CapillaryPressure.ats new file mode 100644 index 00000000000..8d26b61945c --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_CapillaryPressure/immiscibleTwoPhase_CapillaryPressure.ats @@ -0,0 +1,18 @@ +from geos.ats.test_builder import TestDeck, RestartcheckParameters, generate_geos_tests + +restartcheck_params = {} +restartcheck_params['atol'] = 1.0E-8 +restartcheck_params['rtol'] = 1.0E-8 + +decks = [ + TestDeck( + name="immiscibleTwoPhase_CapillaryPressure", + description= + 'Test 2 fluids can mix based on capillary pressure.', + partitions=((1, 1, 1), ), + restart_step=0, + check_step=68, + restartcheck_params=RestartcheckParameters(**restartcheck_params)) +] + +generate_geos_tests(decks) diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/immiscibleTwoPhase_SPE10_layer84.ats b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/immiscibleTwoPhase_SPE10_layer84.ats new file mode 100644 index 00000000000..f45175016bd --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/immiscibleTwoPhase_SPE10_layer84.ats @@ -0,0 +1,18 @@ +from geos.ats.test_builder import TestDeck, RestartcheckParameters, generate_geos_tests + +restartcheck_params = {} +restartcheck_params['atol'] = 1.0E-8 +restartcheck_params['rtol'] = 1.0E-8 + +decks = [ + TestDeck( + name="immiscibleTwoPhase_SPE10_layer84_benchmark_iterative.xml", + description= + 'Two phase immiscible flow on SPE10 layer84 using iterative solver.', + partitions=((1, 1, 1), ), + restart_step=0, + check_step=89, + restartcheck_params=RestartcheckParameters(**restartcheck_params)) +] + +generate_geos_tests(decks) From fd702fc552ff4f105b3e18f471951a33b04c31a8 Mon Sep 17 00:00:00 2001 From: DENEL Bertrand Date: Thu, 31 Oct 2024 16:58:22 -0500 Subject: [PATCH 058/104] Added more ats, part2. --- .../immiscibleTwoPhase_CapillaryPressure.xml | 10 +++++++++- ...immiscibleTwoPhase_SPE10_layer84_base_iterative.xml | 8 ++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_CapillaryPressure/immiscibleTwoPhase_CapillaryPressure.xml b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_CapillaryPressure/immiscibleTwoPhase_CapillaryPressure.xml index 46d250ee052..64169b10c0b 100644 --- a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_CapillaryPressure/immiscibleTwoPhase_CapillaryPressure.xml +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_CapillaryPressure/immiscibleTwoPhase_CapillaryPressure.xml @@ -49,6 +49,12 @@ + + @@ -186,5 +192,7 @@ + - \ No newline at end of file + diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/immiscibleTwoPhase_SPE10_layer84_base_iterative.xml b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/immiscibleTwoPhase_SPE10_layer84_base_iterative.xml index 13264fe80d0..f42872756a0 100644 --- a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/immiscibleTwoPhase_SPE10_layer84_base_iterative.xml +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_SPE10_layer84/immiscibleTwoPhase_SPE10_layer84_base_iterative.xml @@ -34,6 +34,12 @@ name="solverApplications" maxEventDt="1e6" target="/Solvers/FlowSolver"/> + + @@ -233,6 +239,8 @@ + From 41c19e10744657e0e6671379349c3268454d68c8 Mon Sep 17 00:00:00 2001 From: DENEL Bertrand Date: Mon, 4 Nov 2024 22:14:21 -0600 Subject: [PATCH 059/104] Fixed capillaryPressure test. --- .../immiscibleTwoPhase_CapillaryPressure.xml | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_CapillaryPressure/immiscibleTwoPhase_CapillaryPressure.xml b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_CapillaryPressure/immiscibleTwoPhase_CapillaryPressure.xml index 64169b10c0b..8b2c07ec180 100644 --- a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_CapillaryPressure/immiscibleTwoPhase_CapillaryPressure.xml +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_CapillaryPressure/immiscibleTwoPhase_CapillaryPressure.xml @@ -32,13 +32,6 @@ cellBlockNames="{ block1 }" /> - - - - + compressibility="1e-12" /> - From ff37803dabfddcc85c75928491abdbfa31dbdd32 Mon Sep 17 00:00:00 2001 From: DENEL Bertrand Date: Wed, 6 Nov 2024 16:38:11 -0600 Subject: [PATCH 060/104] Removed unused function. --- .../fluidFlow/ImmiscibleMultiphaseFlow.cpp | 62 ------------------- 1 file changed, 62 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index f5dfe772a65..e14deff1295 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -784,68 +784,6 @@ char const bcLogMessage[] = } -void applyAndSpecifyFieldValue( real64 const & time_n, - real64 const & dt, - MeshLevel & mesh, - globalIndex const rankOffset, - string const dofKey, - bool const, - integer const idof, - string const fieldKey, - string const boundaryFieldKey, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) -{ - FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); - - fsManager.apply< ElementSubRegionBase >( time_n + dt, - mesh, - fieldKey, - [&]( FieldSpecificationBase const & fs, - string const &, - SortedArrayView< localIndex const > const & lset, - ElementSubRegionBase & subRegion, - string const & ) - { - // Specify the bc value of the field - fs.applyFieldValue< FieldSpecificationEqual, - parallelDevicePolicy<> >( lset, - time_n + dt, - subRegion, - boundaryFieldKey ); - - arrayView1d< integer const > const ghostRank = subRegion.ghostRank(); - arrayView1d< globalIndex const > const dofNumber = - subRegion.getReference< array1d< globalIndex > >( dofKey ); - arrayView1d< real64 const > const bcField = - subRegion.getReference< array1d< real64 > >( boundaryFieldKey ); - arrayView1d< real64 const > const field = - subRegion.getReference< array1d< real64 > >( fieldKey ); - - forAll< parallelDevicePolicy<> >( lset.size(), [=] GEOS_HOST_DEVICE ( localIndex const a ) - { - localIndex const ei = lset[a]; - if( ghostRank[ei] >= 0 ) - { - return; - } - - globalIndex const dofIndex = dofNumber[ei]; - localIndex const localRow = dofIndex - rankOffset; - real64 rhsValue; - - // Apply field value to the matrix/rhs - FieldSpecificationEqual::SpecifyFieldValue( dofIndex + idof, - rankOffset, - localMatrix, - rhsValue, - bcField[ei], - field[ei] ); - localRhs[localRow + idof] = rhsValue; - } ); - } ); -} - void ImmiscibleMultiphaseFlow::applyDirichletBC( real64 const time_n, real64 const dt, DofManager const & dofManager, From 4453d20fb118b9013490b98b65c7c8a723e04a82 Mon Sep 17 00:00:00 2001 From: DENEL Bertrand Date: Fri, 8 Nov 2024 12:08:52 -0600 Subject: [PATCH 061/104] Added documentation for the two-phase fluid model. --- .../constitutive/docs/FluidModels.rst | 2 + .../constitutive/docs/TwoPhaseFluid.rst | 89 +++++++++++++++++++ .../fluid/twophasefluid/TwoPhaseFluid.cpp | 4 +- 3 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 src/coreComponents/constitutive/docs/TwoPhaseFluid.rst diff --git a/src/coreComponents/constitutive/docs/FluidModels.rst b/src/coreComponents/constitutive/docs/FluidModels.rst index 445f8a82f0b..741a8426e2b 100644 --- a/src/coreComponents/constitutive/docs/FluidModels.rst +++ b/src/coreComponents/constitutive/docs/FluidModels.rst @@ -11,6 +11,8 @@ single fluids and fluid mixtures. CompressibleSinglePhaseFluid + TwoPhaseFluid + BlackOilFluid CompositionalMultiphaseFluid diff --git a/src/coreComponents/constitutive/docs/TwoPhaseFluid.rst b/src/coreComponents/constitutive/docs/TwoPhaseFluid.rst new file mode 100644 index 00000000000..d5e3bd52c51 --- /dev/null +++ b/src/coreComponents/constitutive/docs/TwoPhaseFluid.rst @@ -0,0 +1,89 @@ +.. _TwoPhaseFluid: + +############################################ +Two-phase fluid model +############################################ + +Overview +========================= + +This model represents a two-phase fluid with pressure-dependent density and viscosity. + +For each phase, both density and viscosity are described as tabulated data, either in the form of ``TableFunction`` or text files. + +In the case of text files, one file is expected per phase and should consist of three columns: pressure, density and viscosity. + +Note that currently, there is no temperature dependence in the model. + + +Parameters +========================= + +The model is represented by ```` node in the input. + +The following attributes are supported: + +.. include:: /docs/sphinx/datastructure/TwoPhaseFluid.rst + + +Example using TableFunctions +============================ + +.. code-block:: xml + + + + + + + + + + + + + + + + +Example using text files +========================= + +.. code-block:: xml + + + + + + +with, for example, ``water.txt`` being set as: + +.. code-block:: text + # P(Pa) Dens(kg/m3) Visc(Pa.s) + 2068000 980.683 0.0003 + 5516000 982.07 0.0003 + 30600000 992.233 0.0003 + 55160000 1002.265 0.0003 diff --git a/src/coreComponents/constitutive/fluid/twophasefluid/TwoPhaseFluid.cpp b/src/coreComponents/constitutive/fluid/twophasefluid/TwoPhaseFluid.cpp index 208fe448e35..b0fc13116fa 100644 --- a/src/coreComponents/constitutive/fluid/twophasefluid/TwoPhaseFluid.cpp +++ b/src/coreComponents/constitutive/fluid/twophasefluid/TwoPhaseFluid.cpp @@ -51,13 +51,13 @@ TwoPhaseFluid::TwoPhaseFluid( string const & name, Group * const parent ) setRTTypeName( rtTypes::CustomTypes::groupNameRefArray ). setInputFlag( InputFlags::OPTIONAL ). setDescription( "List of density TableFuncion names from the Function block. \n" - "The user must provide one TableFunction par phase, respecting the order provided in \"phaseNames\"." ); + "The user must provide one TableFunction per phase, respecting the order provided in \"phaseNames\"." ); registerWrapper( viewKeyStruct::viscosityTableNamesString(), &m_viscosityTableNames ). setRTTypeName( rtTypes::CustomTypes::groupNameRefArray ). setInputFlag( InputFlags::OPTIONAL ). setDescription( "List of viscosity TableFuncion names from the Function block. \n" - "The user must provide one TableFunction par phase, respecting the order provided in \"phaseNames\"." ); + "The user must provide one TableFunction per phase, respecting the order provided in \"phaseNames\"." ); registerField( fields::twophasefluid::phaseDensity{}, &m_phaseDensity.value ); registerField( fields::twophasefluid::dPhaseDensity{}, &m_phaseDensity.derivs ); From 316b4b77b4405a00807d676a4b7327962460d69c Mon Sep 17 00:00:00 2001 From: DENEL Bertrand Date: Fri, 8 Nov 2024 15:38:56 -0600 Subject: [PATCH 062/104] Fixed doc. --- src/coreComponents/constitutive/docs/TwoPhaseFluid.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/coreComponents/constitutive/docs/TwoPhaseFluid.rst b/src/coreComponents/constitutive/docs/TwoPhaseFluid.rst index d5e3bd52c51..39b35510c63 100644 --- a/src/coreComponents/constitutive/docs/TwoPhaseFluid.rst +++ b/src/coreComponents/constitutive/docs/TwoPhaseFluid.rst @@ -24,7 +24,7 @@ The model is represented by ```` node in the input. The following attributes are supported: .. include:: /docs/sphinx/datastructure/TwoPhaseFluid.rst - + Example using TableFunctions ============================ @@ -82,6 +82,7 @@ Example using text files with, for example, ``water.txt`` being set as: .. code-block:: text + # P(Pa) Dens(kg/m3) Visc(Pa.s) 2068000 980.683 0.0003 5516000 982.07 0.0003 From 389bfb0ac5a2345ef8780dffc168f2b76d6215bd Mon Sep 17 00:00:00 2001 From: rpiazza87 Date: Mon, 11 Nov 2024 16:19:24 -0800 Subject: [PATCH 063/104] included total mass formulation --- .../fluidFlow/ImmiscibleMultiphaseFlow.cpp | 26 ++++++++++++++----- .../fluidFlow/ImmiscibleMultiphaseFlow.hpp | 1 + .../fluidFlow/ImmiscibleMultiphaseKernels.hpp | 24 ++++++++++++++--- 3 files changed, 41 insertions(+), 10 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index e14deff1295..e08a92f69c1 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -24,8 +24,8 @@ #include "physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp" #include "physicsSolvers/SolverBaseKernels.hpp" -#include "physicsSolvers/fluidFlow/IsothermalCompositionalMultiphaseBaseKernels.hpp" // should be removed eventually -//#include "physicsSolvers/fluidFlow/IsothermalCompositionalMultiphaseFVMKernels.hpp" +#include "physicsSolvers/fluidFlow/IsothermalCompositionalMultiphaseBaseKernels.hpp" +#include "physicsSolvers/fluidFlow/CompositionalMultiphaseUtilities.hpp" #include "constitutive/ConstitutiveManager.hpp" #include "constitutive/capillaryPressure/CapillaryPressureFields.hpp" @@ -34,9 +34,7 @@ #include "fieldSpecification/SourceFluxBoundaryCondition.hpp" - #include "constitutive/ConstitutivePassThru.hpp" - #include "constitutive/fluid/twophasefluid/TwoPhaseFluid.hpp" #include @@ -60,11 +58,17 @@ ImmiscibleMultiphaseFlow::ImmiscibleMultiphaseFlow( const string & name, FlowSolverBase( name, parent ), m_numPhases( 2 ), m_hasCapPressure( 0 ), - m_useTotalMassEquation ( 0 ) + m_useTotalMassEquation ( 1 ) { this->registerWrapper( viewKeyStruct::inputTemperatureString(), &m_inputTemperature ). setInputFlag( InputFlags::REQUIRED ). setDescription( "Temperature" ); + + this->registerWrapper( viewKeyStruct::useTotalMassEquationString(), &m_useTotalMassEquation ). + setSizedFromParent( 0 ). + setInputFlag( InputFlags::OPTIONAL ). + setApplyDefaultValue( 1 ). + setDescription( "Flag indicating whether total mass equation is used" ); } void ImmiscibleMultiphaseFlow::postInputInitialization() @@ -671,6 +675,16 @@ void ImmiscibleMultiphaseFlow::assembleAccumulationTerm( DomainPartition & domai // complete + using namespace compositionalMultiphaseUtilities; + + if( m_useTotalMassEquation ) + { + // apply equation/variable change transformation to the component mass balance equations + real64 work[numofPhases]{}; + shiftRowsAheadByOneAndReplaceFirstRowWithColumnSum( numofPhases, numofPhases, localJacobian, work ); + shiftElementsAheadByOneAndReplaceFirstElementWithSum( numofPhases, localResidual ); + } + integer const numRows = numofPhases; for( integer i = 0; i < numRows; ++i ) @@ -998,7 +1012,7 @@ void ImmiscibleMultiphaseFlow::applySourceFluxBC( real64 const time, real64 const sizeScalingFactor = bcAllSetsSize[bcNameToBcId.at( fs.getName())]; integer const fluidPhaseId = fs.getComponent(); integer const numFluidPhases = m_numPhases; - integer useTotalMassEquation = 0; + integer useTotalMassEquation = m_useTotalMassEquation; forAll< parallelDevicePolicy<> >( targetSet.size(), [sizeScalingFactor, targetSet, rankOffset, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp index 565a2b1a562..d393df265c0 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp @@ -220,6 +220,7 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase static constexpr char const * capPressureNamesString() { return "capPressureNames"; } static constexpr char const * relPermNamesString() { return "relPermNames"; } static constexpr char const * elemDofFieldString() { return "elemDofField"; } + static constexpr char const * useTotalMassEquationString() { return "useTotalMassEquation"; } }; diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp index 0f668592462..27f2bc65d8f 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseKernels.hpp @@ -39,7 +39,7 @@ #include "linearAlgebra/interfaces/InterfaceTypes.hpp" #include "physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp" #include "physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp" -//#include "physicsSolvers/fluidFlow/SinglePhaseBaseKernels.hpp" // check need of multiphase equivalent +#include "physicsSolvers/fluidFlow/CompositionalMultiphaseUtilities.hpp" #include "physicsSolvers/fluidFlow/StencilAccessors.hpp" #include "physicsSolvers/SolverBaseKernels.hpp" @@ -101,11 +101,14 @@ class FaceBasedAssemblyKernelBase * @param[in] rankOffset the offset of my MPI rank * @param[in] dofNumberAccessor accessor for the dof numbers * @param[in] multiPhaseFlowAccessors accessor for wrappers registered by the solver + * @param[in] fluidAccessors accessor for wrappers registered by the fluid model * @param[in] capPressureAccessors accessor for wrappers registered by the capillary pressure model * @param[in] permeabilityAccessors accessor for wrappers registered by the permeability model * @param[in] dt time step size * @param[inout] localMatrix the local CRS matrix * @param[inout] localRhs the local right-hand side vector + * @param[inout] hasCapPressure flag to indicate whether problem includes capillarity + * @param[inout] useTotalMassEquation flag to indicate whether to use the total mass formulation */ FaceBasedAssemblyKernelBase( integer const numPhases, globalIndex const rankOffset, @@ -138,7 +141,7 @@ class FaceBasedAssemblyKernelBase m_localRhs( localRhs ), m_hasCapPressure ( hasCapPressure ), m_useTotalMassEquation ( useTotalMassEquation ) - {GEOS_UNUSED_VAR( m_useTotalMassEquation );} + {} protected: @@ -220,11 +223,12 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase /** * @brief Constructor for the kernel interface + * @param[in] numPhases number of fluid phases * @param[in] rankOffset the offset of my MPI rank * @param[in] stencilWrapper reference to the stencil wrapper * @param[in] dofNumberAccessor - * @param[in] singlePhaseFlowAccessors - * @param[in] singlePhaseFluidAccessors + * @param[in] multiPhaseFlowAccessors + * @param[in] fluidAccessors * @param[in] capPressureAccessors * @param[in] permeabilityAccessors * @param[in] dt time step size @@ -620,6 +624,18 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase StackVariables & stack, FUNC && kernelOp = NoOpFunc{} ) const { + using namespace compositionalMultiphaseUtilities; + + if( m_useTotalMassEquation ) + { + // Apply equation/variable change transformation(s) + stackArray1d< real64, maxStencilSize * numDof > work( stack.stencilSize * numDof ); + shiftBlockRowsAheadByOneAndReplaceFirstRowWithColumnSum( m_numPhases, numEqn, numDof * stack.stencilSize, stack.numFluxElems, + stack.localFluxJacobian, work ); + shiftBlockElementsAheadByOneAndReplaceFirstElementWithSum( m_numPhases, numEqn, stack.numFluxElems, + stack.localFlux ); + } + // add contribution to residual and jacobian into: // - the mass balance equation // note that numDof includes derivatives wrt temperature if this class is derived in ThermalKernels From 73dc82f7e2ee1dc0d6c8476abd0f5803c3a67857 Mon Sep 17 00:00:00 2001 From: Ammara-14 Date: Mon, 18 Nov 2024 11:52:20 -0800 Subject: [PATCH 064/104] updated the assembleAccumulationTerm kernel and added documentation for the immiscible multiphase solver --- .../fluidFlow/ImmiscibleMultiphaseFlow.cpp | 106 +----- .../docs/ImmiscibleMultiphaseFlow.rst | 206 +++++++++++ .../ImmiscibleMultiphaseKernels.hpp | 325 ++++++++++++++++++ 3 files changed, 543 insertions(+), 94 deletions(-) create mode 100644 src/coreComponents/physicsSolvers/fluidFlow/docs/ImmiscibleMultiphaseFlow.rst diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index 506d4f21382..7270185f06f 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -602,100 +602,18 @@ void ImmiscibleMultiphaseFlow::assembleAccumulationTerm( DomainPartition & domai TwoPhaseFluid const & fluid = getConstitutiveModel< TwoPhaseFluid >( subRegion, fluidName ); CoupledSolidBase const & solid = getConstitutiveModel< CoupledSolidBase >( subRegion, solidName ); - //arrayView1d< real64 const > const pres = subRegion.getField< fields::flow::pressure >(); - integer const numofPhases = 2; - globalIndex const rankOffset = dofManager.rankOffset(); - arrayView1d< globalIndex const > const dofNumber = subRegion.getReference< array1d< globalIndex > >( dofKey ); - arrayView1d< integer const > const elemGhostRank= subRegion.ghostRank(); - arrayView1d< real64 const > const volume = subRegion.getElementVolume(); - arrayView2d< real64 const > const porosity = solid.getPorosity(); - arrayView2d< real64 const > const dPoro_dPres = solid.getDporosity_dPressure(); - arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac= subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); - arrayView3d< real64 const, multifluid::USD_PHASE > phaseDens = fluid.phaseDensity(); - arrayView4d< real64 const, multifluid::USD_PHASE_DC > dPhaseDens = fluid.dPhaseDensity(); - arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const PhaseMass_n = subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseMass_n >(); - - // The line below is to be used if we want to use the total mass flux formulation - //BitFlags< ElementBasedAssemblyKernelFlags > m_kernelFlags = kernelFlags; - - - integer const numElems = subRegion.size(); - forAll< parallelDevicePolicy<> >( - numElems, [=] GEOS_HOST_DEVICE ( localIndex const ei ) - { - if( elemGhostRank( ei ) >= 0 ) - { - return; - } - - // setup - globalIndex dofIndices[2]{}; - real64 localResidual[2]{}; - real64 localJacobian[2][2]{}; - - real64 const poreVolume = volume[ei] * porosity[ei][0]; - real64 const dPoreVolume_dPres = volume[ei] * dPoro_dPres[ei][0]; - - localIndex localRow = dofNumber[ei] - rankOffset; - - for( integer idof = 0; idof < 2; ++idof ) - { - dofIndices[idof] = dofNumber[ei] + idof; - } - - // compute accumulation - int signPotDiff[2] = {1, -1}; - - for( integer ip = 0; ip < numofPhases; ++ip ) - { - real64 const phaseMass = poreVolume * phaseVolFrac[ei][ip] * phaseDens[ei][0][ip]; - real64 const phaseMass_n = PhaseMass_n[ei][ip]; - - localResidual[ip] += phaseMass - phaseMass_n; - - real64 const dPhaseMass_dP = dPoreVolume_dPres * phaseVolFrac[ei][ip] * phaseDens[ei][0][ip] - + poreVolume * phaseVolFrac[ei][ip] * dPhaseDens[ei][0][ip][0]; - localJacobian[ip][0] += dPhaseMass_dP; - - real64 const dPhaseMass_dS = poreVolume * phaseDens[ei][0][ip]; - - - // if ( ip == 0) - // { - // localJacobian[ip][1] += dPhaseMass_dS; - // } else { - // localJacobian[ip][1] -= dPhaseMass_dS; - // } - - localJacobian[ip][1] += signPotDiff[ip] * dPhaseMass_dS; - - } - - // complete - - using namespace compositionalMultiphaseUtilities; - - if( m_useTotalMassEquation ) - { - // apply equation/variable change transformation to the component mass balance equations - real64 work[numofPhases]{}; - shiftRowsAheadByOneAndReplaceFirstRowWithColumnSum( numofPhases, numofPhases, localJacobian, work ); - shiftElementsAheadByOneAndReplaceFirstElementWithSum( numofPhases, localResidual ); - } - - integer const numRows = numofPhases; - - for( integer i = 0; i < numRows; ++i ) - { - localRhs[localRow + i] += localResidual[i]; - localMatrix.addToRow< serialAtomic >( localRow + i, - dofIndices, - localJacobian[i], - 2 ); - } - - } ); - + immiscibleMultiphaseKernels:: + AccumulationKernelFactory:: + createAndLaunch< parallelDevicePolicy<> >( m_numPhases, + dofManager.rankOffset(), + m_useTotalMassEquation, + dofKey, + subRegion, + fluid, + solid, + localMatrix, + localRhs ); + } ); } ); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/docs/ImmiscibleMultiphaseFlow.rst b/src/coreComponents/physicsSolvers/fluidFlow/docs/ImmiscibleMultiphaseFlow.rst new file mode 100644 index 00000000000..b7e98af3c76 --- /dev/null +++ b/src/coreComponents/physicsSolvers/fluidFlow/docs/ImmiscibleMultiphaseFlow.rst @@ -0,0 +1,206 @@ +.. _ImmiscibleMultiphaseFlow: + +####################################### +Immiscible Multiphase Flow Solver +####################################### + +Introduction +============= + +This flow solver is used to implement the finite-volume discretization for the problem of modeling multiphase flow in porous media under the influence of viscous, gravity, and capillary forces while neglecting miscibility and taking into account rock and fluid compressibility. + +In here, we go over the governing equations :ref:`equations` that covers two different formulation options, followed by the :ref:`discretization`, and we conclude by providing a list of the solver :ref:`parameters` and an input :ref:`input_example`. + +.. _theory: + +Theory +========================= + +.. _equations: + +Governing Equations +------------------- + +Mass Conservation Equations +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +We consider a two-component system, say gas and water, flow in a compressible porous medium, in which both components can exist only in their corresponding phases of vapor and liquid. The gas and water components are denoted by the subscripts :math:`g` and +:math:`w`, respectively. Moreover, the liquid, which is the wetting phase, and the vapor, the non-wetting phase, are denoted by the subscripts :math:`\ell` and +:math:`v`, respectively. The mass conservation laws are expressed as: + +.. math:: + \frac{\partial}{\partial t} (\phi\rho_v S_v) + \nabla \cdot (\rho_v \boldsymbol{u}_v) = \rho_v q_v, + +and +.. math:: + \frac{\partial}{\partial t} (\phi\rho_\ell S_\ell) + \nabla \cdot (\rho_\ell \boldsymbol{u}_\ell) = \rho_\ell q_\ell, + + + +where :math:`\phi(\bold{x},p)` is the porosity of the medium which is a function of pressure, +:math:`S_\ell(\bold{x},t)` is the saturation of the phase +:math:`\ell` and similarly for the phase :math:`v`, and :math:`t` is the time. The source/sink terms :math:`q_{\ell}` and :math:`q_{v}` are +positive for injection and negative for production. The phase +velocity, :math:`\boldsymbol{u}_\ell`` and :math:`\boldsymbol{u}_v`$`, are defined using +the multiphase extension of Darcy's law (conservation of momentum) as + +.. math:: +\boldsymbol{u}_\ell := -k\lambda_\ell(\nabla p_\ell - \rho_\ell g \nabla z), + +and +.. math:: +\boldsymbol{u}_v := -k\lambda_v(\nabla p_v - \rho_v g \nabla z). + +Here, :math:`k(\bold{x})` is the scalar absolute permeability of the medium, :math:`\lambda_\ell` is the phase mobility of the liquid phase defined as :math:`k_{r\ell}/\mu_\ell`, where :math:`k_{r\ell}(\bold{x},S_\ell)` is the phase relative permeability, :math:`\mu_\ell` is the phase viscosity, and :math:`\rho_{\ell}` is the phase density. +These are also defined similarly for the vapor phase. In both cases we assume that the relative permeabilities are strictly increasing functions of their own saturation. +The gravitational acceleration is denoted by :math:`g`, and the +depth by :math:`z` (positive going downward). +The conservation of mass equations are constrained by the volume contraint equation: +.. math:: +S_{\ell} + S_v = 1, + +Moreover, the capillary pressure constraint relates the two phase pressures with +.. math:: +P_{c}(S_{\ell}) = p_{v} - p_{\ell}. + +We assume that capillary pressure is a strictly decreasing function of the wetting-phase saturation. + +The evaluation of the relative permeabilities, capillary pressures, and +viscosities is reviewed in the section about :doc:`/coreComponents/constitutive/docs/Constitutive`. + +We note that the formulation currently implemented in GEOS is isothermal. + +To summarize, the Immiscible multiphase flow solver assembles a set of :math:`n_p+1` +equations in each element, i.e., :math:`n_p` mass conservation equations and one volume constraint equation. + +==================== =========================== +Number of equations Equation type +==================== =========================== +:math:`n_p` Mass conservation equations +1 Volume constraint +==================== =========================== + +.. _primary_variables: + +Primary Variables +------------------ + +There are two formulations implemented in GEOS for the Immiscible multiphsae solver and both formulations are based on +:math:`n_p+1` primary variables, namely, one pressure, :math:`p`, and +:math:`n_p` phase volume fractions, :math:`S_{p}`. + +=========================== =========================== +Number of primary variables Variable type +=========================== =========================== +1 Pressure +:math:`n_p - 1` Phase volume fractions +=========================== =========================== + +The main formulation is the standard formulation which solves the individual components mass conservation equations. Also, another formulation based on the total mass flux is implemented which is useful for multiple purposes such as hybrid upwinding techniques and sequential finite volume methods. This latter formulation is explained next. + +Flow and Transport Equations +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +To develop this formulation we use a flux approximation as required by the finite-volume numerical solution scheme. +Thus, we choose to construct this approximation in fractional flow form, and with this we will be able to show the coupling between the different physical processes. This formulation is obtained by decomposing the governing equations into a flow problem for both phases and a transport problem for one of the two phases. +To obtain this decomposition, we use a total-mass balance formulation by summing both components mass conversation equations and then using the mass constraint to result in the following elliptic PDE governing the temporal evolution of the pressure field: +.. math:: + \frac{\partial}{\partial t}(\phi \rho_t) + \nabla \cdot (\rho_{\ell} \boldsymbol{u}_{\ell} + \rho_{v} \boldsymbol{u}_{v}) = \rho_{\ell} q_{\ell} + \rho_{v} q_{v}, + +where +.. math:: + \rho_t = \rho_{\ell}S_{\ell}+\rho_{v}S_{v} + +and we defined a total mass flux as +.. math:: +\boldsymbol{U}_T := \rho_{\ell} \boldsymbol{u}_{\ell} + \rho_{v} \boldsymbol{u}_{v}= -k (\rho_{\ell} \lambda_{\ell} + \rho_{v} \lambda_{v}) \nabla p + k ( \lambda_{\ell} \rho^2_{\ell} + \lambda_{v} \rho^2_{v}) g \nabla z + k \rho_{\ell}\lambda_{\ell} \nabla P_{c}. + +Next, the highly nonlinear parabolic transport equation is obtained by using this total mass flux to formally eliminate the pressure variable from the individual components mass conservation equations, yielding +.. math:: +{ +\frac{\partial}{\partial t}(\phi\rho_v S_v) + \nabla \cdot F_v + = + \rho_v q_v,} +and +.. math:: +{ +\frac{\partial}{\partial t}(\phi\rho_\ell S_\ell) + \nabla \cdot F_\ell + = +\rho_\ell q_\ell,} + +where the flow flux for each phase is defined as +.. math:: +{ +F_{\ell} := +\underbrace{\frac{\rho_\ell \lambda_\ell}{\rho_\ell \lambda_\ell+\rho_v \lambda_v}\boldsymbol{U}_T}_{\substack{\text{viscous} \\ \text{term}}} + +\underbrace{k \frac{\rho_\ell \lambda_\ell\rho_v \lambda_v}{\rho_\ell \lambda_\ell+\rho_v \lambda_v}(\rho_\ell - \rho_v) +g\nabla z}_{\substack{\text{buoyancy} \\ \text{term}}} ++ +\underbrace{k \frac{\rho_\ell \lambda_\ell\rho_v \lambda_v}{\rho_\ell \lambda_\ell+\rho_v \lambda_v} ( \nabla P_{c})}_{\substack{\text{capillary} \\ \text{term}}},} + +and +.. math:: +{ +F_{v} := +\underbrace{\frac{\rho_v \lambda_v}{\rho_\ell \lambda_\ell+\rho_v \lambda_v}\boldsymbol{U}_T}_{\substack{\text{viscous} \\ \text{term}}} + +\underbrace{k \frac{\rho_\ell \lambda_\ell\rho_v \lambda_v}{\rho_\ell \lambda_\ell+\rho_v \lambda_v}(\rho_v - \rho_\ell) +g\nabla z}_{\substack{\text{buoyancy} \\ \text{term}}} +- +\underbrace{k \frac{\rho_\ell \lambda_\ell\rho_v \lambda_v}{\rho_\ell \lambda_\ell+\rho_v \lambda_v} (\nabla P_{c})}_{\substack{\text{capillary} \\ \text{term}}},} + + +.. _discretization: + +Discretization +-------------- + +Spatial Discretization +~~~~~~~~~~~~~~~~~~~~~~ + +The governing equations are discretized using standard cell-centered finite-volume +discretization. + +In the approximation of the flux term at the interface between two control volumes, +the calculation of the pressure stencil is general and will ultimately support a +Multi-Point Flux Approximation (MPFA) approach. The current implementation of the +transmissibility calculation is reviewed in the section about +:doc:`/coreComponents/discretizationMethods/docs/NumericalMethodsManager`. + +The approximation of the dynamic transport coefficients multiplying the discrete +potential difference (e.g., the phase mobilities) is performed with a first-order +phase-per-phase single-point upwinding based on the sign of the phase potential difference +at the interface. + +Temporal Discretization +~~~~~~~~~~~~~~~~~~~~~~~ + +The immiscible multiphase solver uses a fully implicit (backward Euler) temporal discretization. + +.. _solution_strategy: + +Solution Strategy +----------------- + +The nonlinear solution strategy is based on Newton's method. +At each Newton iteration, the solver assembles a residual vector, :math:`R`, +collecting the :math:`n_p` discrete mass conservation equations and the volume +constraint for all the control volumes. + +.. _parameters: + +Parameters +=========== + +The following attributes are supported: + +.. include:: /docs/sphinx/datastructure/ImmiscibleMultiphaseFlow.rst + +.. _input_example: + +Example +========================= + +.. literalinclude:: ../../../../../inputFiles/immiscibleMultiphaseFlow/immiscible_2phaseFlow_1d.xml + :language: xml + :start-after: + :end-before: + diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp index e9d714c9096..15f2f019a58 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp @@ -44,6 +44,7 @@ #include "physicsSolvers/fluidFlow/kernels/compositional/RelativePermeabilityUpdateKernel.hpp" #include "physicsSolvers/fluidFlow/kernels/compositional/CapillaryPressureUpdateKernel.hpp" #include "physicsSolvers/PhysicsSolverBaseKernels.hpp" +#include "physicsSolvers/fluidFlow/kernels/compositional/KernelLaunchSelectors.hpp" namespace geos { @@ -763,6 +764,330 @@ class FaceBasedAssemblyKernelFactory } }; + +/******************************** AccumulationKernel ********************************/ + +static constexpr real64 minDensForDivision = 1e-10; + +enum class KernelFlags +{ + // SimpleAccumulation = 1 << 0, // 1 + TotalMassEquation = 1 << 1, // 2 + /// Add more flags like that if needed: + // Flag3 = 1 << 2, // 4 + // Flag4 = 1 << 3, // 8 + // Flag5 = 1 << 4, // 16 + // Flag6 = 1 << 5, // 32 + // Flag7 = 1 << 6, // 64 + // Flag8 = 1 << 7 //128 +}; +/** + * @class AccumulationKernel + * @tparam NUM_COMP number of fluid phases + * @tparam NUM_DOF number of degrees of freedom + * @brief Define the interface for the assembly kernel in charge of accumulation + */ + +template< integer NUM_EQN, integer NUM_DOF > +class AccumulationKernel +{ +public: + + /// Number of fluid phases + integer const m_numPhases; + + /// Compute time value for the number of degrees of freedom + static constexpr integer numDof = NUM_DOF; + + /// Compute time value for the number of equations + static constexpr integer numEqn = NUM_DOF; + + /** + * @brief Constructor + * @param[in] numPhases the number of fluid phases + * @param[in] rankOffset the offset of my MPI rank + * @param[in] dofKey the string key to retrieve the degress of freedom numbers + * @param[in] subRegion the element subregion + * @param[in] fluid the fluid model + * @param[in] solid the solid model + * @param[inout] localMatrix the local CRS matrix + * @param[inout] localRhs the local right-hand side vector + */ + AccumulationKernel( localIndex const numPhases, + globalIndex const rankOffset, + string const dofKey, + ElementSubRegionBase const & subRegion, + constitutive::TwoPhaseFluid const & fluid, + constitutive::CoupledSolidBase const & solid, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs, + BitFlags< KernelFlags > const kernelFlags ) + : m_numPhases( numPhases ), + m_rankOffset( rankOffset ), + m_dofNumber( subRegion.getReference< array1d< globalIndex > >( dofKey ) ), + m_elemGhostRank( subRegion.ghostRank() ), + m_volume( subRegion.getElementVolume() ), + m_porosity( solid.getPorosity() ), + m_dPoro_dPres( solid.getDporosity_dPressure() ), + m_phaseVolFrac( subRegion.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >() ), + m_phaseDens( fluid.phaseDensity() ), + m_dPhaseDens( fluid.dPhaseDensity() ), + m_phaseMass_n( subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseMass_n >() ), + m_localMatrix( localMatrix ), + m_localRhs( localRhs ), + m_kernelFlags( kernelFlags ) + {} + + /** + * @struct StackVariables + * @brief Kernel variables (dof numbers, jacobian and residual) located on the stack + */ + struct StackVariables + { +public: + + // Pore volume information (used by both accumulation and volume balance) + + /// Pore volume at time n+1 + real64 poreVolume = 0.0; + + /// Derivative of pore volume with respect to pressure + real64 dPoreVolume_dPres = 0.0; + + // Residual information + + /// Index of the local row corresponding to this element + localIndex localRow = -1; + + /// Indices of the matrix rows/columns corresponding to the dofs in this element + globalIndex dofIndices[numDof]{}; + + /// C-array storage for the element local residual vector (all equations except volume balance) + real64 localResidual[numEqn]{}; + + /// C-array storage for the element local Jacobian matrix (all equations except volume balance, all dofs) + real64 localJacobian[numEqn][numDof]{}; + + }; + + /** + * @brief Getter for the ghost rank of an element + * @param[in] ei the element index + * @return the ghost rank of the element + */ + GEOS_HOST_DEVICE + integer elemGhostRank( localIndex const ei ) const + { return m_elemGhostRank( ei ); } + + + /** + * @brief Performs the setup phase for the kernel. + * @param[in] ei the element index + * @param[in] stack the stack variables + */ + GEOS_HOST_DEVICE + void setup( localIndex const ei, + StackVariables & stack ) const + { + // initialize the pore volume + stack.poreVolume = m_volume[ei] * m_porosity[ei][0]; + stack.dPoreVolume_dPres = m_volume[ei] * m_dPoro_dPres[ei][0]; + + // set row index and degrees of freedom indices for this element + stack.localRow = m_dofNumber[ei] - m_rankOffset; + for( integer idof = 0; idof < numDof; ++idof ) + { + stack.dofIndices[idof] = m_dofNumber[ei] + idof; + } + } + + /** + * @brief Compute the local accumulation contributions to the residual and Jacobian + * @tparam FUNC the type of the function that can be used to customize the kernel + * @param[in] ei the element index + * @param[inout] stack the stack variables + * @param[in] phaseAmountKernelOp the function used to customize the kernel + */ + template< typename FUNC = NoOpFunc > + GEOS_HOST_DEVICE + void computeAccumulation( localIndex const ei, + StackVariables & stack, + FUNC && phaseAmountKernelOp = NoOpFunc{} ) const + { + int signPotDiff[2] = {1, -1}; + // ic - index of component whose conservation equation is assembled + // (i.e. row number in local matrix) + for( integer ip = 0; ip < m_numPhases; ++ip ) + { + real64 const phaseMass = stack.poreVolume * m_phaseVolFrac[ei][ip] * m_phaseDens[ei][0][ip]; + real64 const phaseMass_n = m_phaseMass_n[ei][ip]; + + stack.localResidual[ip] += phaseMass - phaseMass_n; + + real64 const dPhaseMass_dP = stack.dPoreVolume_dPres * m_phaseVolFrac[ei][ip] * m_phaseDens[ei][0][ip] + + stack.poreVolume * m_phaseVolFrac[ei][ip] * m_dPhaseDens[ei][0][ip][0]; + stack.localJacobian[ip][0] += dPhaseMass_dP; + + real64 const dPhaseMass_dS = stack.poreVolume * m_phaseDens[ei][0][ip]; + stack.localJacobian[ip][1] += signPotDiff[ip] * dPhaseMass_dS; + } + + } + + /** + * @brief Performs the complete phase for the kernel. + * @param[in] ei the element index + * @param[inout] stack the stack variables + */ + GEOS_HOST_DEVICE + void complete( localIndex const GEOS_UNUSED_PARAM( ei ), + StackVariables & stack ) const + { + using namespace compositionalMultiphaseUtilities; + + if( m_kernelFlags.isSet( KernelFlags::TotalMassEquation ) ) + { + // apply equation/variable change transformation to the component mass balance equations + real64 work[numDof]{}; + shiftRowsAheadByOneAndReplaceFirstRowWithColumnSum( m_numPhases, numDof, stack.localJacobian, work ); + shiftElementsAheadByOneAndReplaceFirstElementWithSum( m_numPhases, stack.localResidual ); + } + + // add contribution to residual and jacobian into: + // - the component mass balance equations (i = 0 to i = numComp-1) + // - the volume balance equations (i = numComp) + // note that numDof includes derivatives wrt temperature if this class is derived in ThermalKernels + integer const numRows = m_numPhases; + for( integer i = 0; i < numRows; ++i ) + { + m_localRhs[stack.localRow + i] += stack.localResidual[i]; + m_localMatrix.addToRow< serialAtomic >( stack.localRow + i, + stack.dofIndices, + stack.localJacobian[i], + numDof ); + } + } + + /** + * @brief Performs the kernel launch + * @tparam POLICY the policy used in the RAJA kernels + * @tparam KERNEL_TYPE the kernel type + * @param[in] numElems the number of elements + * @param[inout] kernelComponent the kernel component providing access to setup/compute/complete functions and stack variables + */ + template< typename POLICY, typename KERNEL_TYPE > + static void + launch( localIndex const numElems, + KERNEL_TYPE const & kernelComponent ) + { + GEOS_MARK_FUNCTION; + + forAll< POLICY >( numElems, [=] GEOS_HOST_DEVICE ( localIndex const ei ) + { + if( kernelComponent.elemGhostRank( ei ) >= 0 ) + { + return; + } + + typename KERNEL_TYPE::StackVariables stack; + + kernelComponent.setup( ei, stack ); + kernelComponent.computeAccumulation( ei, stack ); + kernelComponent.complete( ei, stack ); + } ); + } + +protected: + + /// Offset for my MPI rank + globalIndex const m_rankOffset; + + /// View on the dof numbers + arrayView1d< globalIndex const > const m_dofNumber; + + /// View on the ghost ranks + arrayView1d< integer const > const m_elemGhostRank; + + /// View on the element volumes + arrayView1d< real64 const > const m_volume; + + /// Views on the porosity + arrayView2d< real64 const > const m_porosity; + arrayView2d< real64 const > const m_dPoro_dPres; + + /// Views on the phase volume fractions + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const m_phaseVolFrac; + + /// Views on the phase densities + arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > const m_phaseDens; + arrayView4d< real64 const, constitutive::multifluid::USD_PHASE_DC > const m_dPhaseDens; + + // View on component amount (mass) from previous time step + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > m_phaseMass_n; + + /// View on the local CRS matrix + CRSMatrixView< real64, globalIndex const > const m_localMatrix; + /// View on the local RHS + arrayView1d< real64 > const m_localRhs; + + BitFlags< KernelFlags > const m_kernelFlags; +}; + +/** + * @class AccumulationKernelFactory + */ +class AccumulationKernelFactory +{ +public: + + /** + * @brief Create a new kernel and launch + * @tparam POLICY the policy used in the RAJA kernel + * @param[in] numPhases the number of fluid phases + * @param[in] rankOffset the offset of my MPI rank + * @param[in] dofKey the string key to retrieve the degress of freedom numbers + * @param[in] subRegion the element subregion + * @param[in] fluid the fluid model + * @param[in] solid the solid model + * @param[inout] localMatrix the local CRS matrix + * @param[inout] localRhs the local right-hand side vector + */ + template< typename POLICY > + static void + createAndLaunch( integer const numPhases, + globalIndex const rankOffset, + integer const useTotalMassEquation, + string const dofKey, + ElementSubRegionBase const & subRegion, + constitutive::TwoPhaseFluid const & fluid, + constitutive::CoupledSolidBase const & solid, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) + { + + using namespace isothermalCompositionalMultiphaseBaseKernels::internal; + + kernelLaunchSelectorCompSwitch( numPhases, [&] ( auto NP ) + { + integer constexpr NUM_EQN = NP(); + integer constexpr NUM_DOF = NP(); + + BitFlags< KernelFlags > kernelFlags; + if( useTotalMassEquation ) + kernelFlags.set( KernelFlags::TotalMassEquation ); + // if( useSimpleAccumulation ) + // kernelFlags.set( KernelFlags::SimpleAccumulation ); + + AccumulationKernel< NUM_EQN, NUM_DOF > kernel( numPhases, rankOffset, dofKey, subRegion, + fluid, solid, localMatrix, localRhs, kernelFlags ); + AccumulationKernel< NUM_EQN, NUM_DOF >::template launch< POLICY >( subRegion.size(), kernel ); + } ); + } + +}; + + + /******************************** PhaseMobilityKernel ********************************/ /** From fa42877311d6764b4161c99b58693186170dced2 Mon Sep 17 00:00:00 2001 From: Ammara-14 Date: Thu, 21 Nov 2024 12:28:23 -0800 Subject: [PATCH 065/104] fixed code style and added a dedicated Kernel selector switch --- .../fluidFlow/ImmiscibleMultiphaseFlow.cpp | 22 ++--- .../docs/ImmiscibleMultiphaseFlow.rst | 86 ++++++++++++------- .../ImmiscibleMultiphaseKernels.hpp | 64 +++++++------- .../KernelLaunchSelectors.hpp | 57 ++++++++++++ 4 files changed, 152 insertions(+), 77 deletions(-) create mode 100644 src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/KernelLaunchSelectors.hpp diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index 7270185f06f..e44069772f7 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -603,17 +603,17 @@ void ImmiscibleMultiphaseFlow::assembleAccumulationTerm( DomainPartition & domai CoupledSolidBase const & solid = getConstitutiveModel< CoupledSolidBase >( subRegion, solidName ); immiscibleMultiphaseKernels:: - AccumulationKernelFactory:: - createAndLaunch< parallelDevicePolicy<> >( m_numPhases, - dofManager.rankOffset(), - m_useTotalMassEquation, - dofKey, - subRegion, - fluid, - solid, - localMatrix, - localRhs ); - + AccumulationKernelFactory:: + createAndLaunch< parallelDevicePolicy<> >( m_numPhases, + dofManager.rankOffset(), + m_useTotalMassEquation, + dofKey, + subRegion, + fluid, + solid, + localMatrix, + localRhs ); + } ); } ); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/docs/ImmiscibleMultiphaseFlow.rst b/src/coreComponents/physicsSolvers/fluidFlow/docs/ImmiscibleMultiphaseFlow.rst index b7e98af3c76..429acffd551 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/docs/ImmiscibleMultiphaseFlow.rst +++ b/src/coreComponents/physicsSolvers/fluidFlow/docs/ImmiscibleMultiphaseFlow.rst @@ -29,39 +29,45 @@ We consider a two-component system, say gas and water, flow in a compressible po :math:`v`, respectively. The mass conservation laws are expressed as: .. math:: - \frac{\partial}{\partial t} (\phi\rho_v S_v) + \nabla \cdot (\rho_v \boldsymbol{u}_v) = \rho_v q_v, + \frac{\partial}{\partial t} (\phi\rho_v S_v) + \nabla \cdot (\rho_v \boldsymbol{u}_v) = + \rho_v q_v, and + .. math:: - \frac{\partial}{\partial t} (\phi\rho_\ell S_\ell) + \nabla \cdot (\rho_\ell \boldsymbol{u}_\ell) = \rho_\ell q_\ell, + \frac{\partial}{\partial t} (\phi\rho_\ell S_\ell) + \nabla \cdot (\rho_\ell + \boldsymbol{u}_\ell) = \rho_\ell q_\ell, -where :math:`\phi(\bold{x},p)` is the porosity of the medium which is a function of pressure, -:math:`S_\ell(\bold{x},t)` is the saturation of the phase +where :math:`\phi(\mathbf{x})` is the porosity of the medium which is a function of pressure, +:math:`S_\ell(\mathbf{x},t)` is the saturation of the phase :math:`\ell` and similarly for the phase :math:`v`, and :math:`t` is the time. The source/sink terms :math:`q_{\ell}` and :math:`q_{v}` are positive for injection and negative for production. The phase velocity, :math:`\boldsymbol{u}_\ell`` and :math:`\boldsymbol{u}_v`$`, are defined using the multiphase extension of Darcy's law (conservation of momentum) as -.. math:: -\boldsymbol{u}_\ell := -k\lambda_\ell(\nabla p_\ell - \rho_\ell g \nabla z), + .. math:: + \boldsymbol{u}_\ell := -k\lambda_\ell(\nabla p_\ell - \rho_\ell g \nabla z), and -.. math:: -\boldsymbol{u}_v := -k\lambda_v(\nabla p_v - \rho_v g \nabla z). -Here, :math:`k(\bold{x})` is the scalar absolute permeability of the medium, :math:`\lambda_\ell` is the phase mobility of the liquid phase defined as :math:`k_{r\ell}/\mu_\ell`, where :math:`k_{r\ell}(\bold{x},S_\ell)` is the phase relative permeability, :math:`\mu_\ell` is the phase viscosity, and :math:`\rho_{\ell}` is the phase density. + .. math:: + \boldsymbol{u}_v := -k\lambda_v(\nabla p_v - \rho_v g \nabla z). + +Here, :math:`k(\mathbf{x})` is the scalar absolute permeability of the medium, :math:`\lambda_\ell` is the phase mobility of the liquid phase defined as :math:`k_{r\ell}/\mu_\ell`, where :math:`k_{r\ell}(\mathbf{x},S_\ell)` is the phase relative permeability, :math:`\mu_\ell` is the phase viscosity, and :math:`\rho_{\ell}` is the phase density. These are also defined similarly for the vapor phase. In both cases we assume that the relative permeabilities are strictly increasing functions of their own saturation. The gravitational acceleration is denoted by :math:`g`, and the depth by :math:`z` (positive going downward). The conservation of mass equations are constrained by the volume contraint equation: + .. math:: -S_{\ell} + S_v = 1, + S_{\ell} + S_v = 1, Moreover, the capillary pressure constraint relates the two phase pressures with + .. math:: -P_{c}(S_{\ell}) = p_{v} - p_{\ell}. + P_{c}(S_{\ell}) = p_{v} - p_{\ell}. We assume that capillary pressure is a strictly decreasing function of the wetting-phase saturation. @@ -89,6 +95,7 @@ There are two formulations implemented in GEOS for the Immiscible multiphsae sol :math:`n_p+1` primary variables, namely, one pressure, :math:`p`, and :math:`n_p` phase volume fractions, :math:`S_{p}`. + =========================== =========================== Number of primary variables Variable type =========================== =========================== @@ -103,49 +110,64 @@ Flow and Transport Equations To develop this formulation we use a flux approximation as required by the finite-volume numerical solution scheme. Thus, we choose to construct this approximation in fractional flow form, and with this we will be able to show the coupling between the different physical processes. This formulation is obtained by decomposing the governing equations into a flow problem for both phases and a transport problem for one of the two phases. To obtain this decomposition, we use a total-mass balance formulation by summing both components mass conversation equations and then using the mass constraint to result in the following elliptic PDE governing the temporal evolution of the pressure field: + .. math:: \frac{\partial}{\partial t}(\phi \rho_t) + \nabla \cdot (\rho_{\ell} \boldsymbol{u}_{\ell} + \rho_{v} \boldsymbol{u}_{v}) = \rho_{\ell} q_{\ell} + \rho_{v} q_{v}, where + .. math:: \rho_t = \rho_{\ell}S_{\ell}+\rho_{v}S_{v} and we defined a total mass flux as + .. math:: -\boldsymbol{U}_T := \rho_{\ell} \boldsymbol{u}_{\ell} + \rho_{v} \boldsymbol{u}_{v}= -k (\rho_{\ell} \lambda_{\ell} + \rho_{v} \lambda_{v}) \nabla p + k ( \lambda_{\ell} \rho^2_{\ell} + \lambda_{v} \rho^2_{v}) g \nabla z + k \rho_{\ell}\lambda_{\ell} \nabla P_{c}. + \boldsymbol{U}_T := \rho_{\ell} \boldsymbol{u}_{\ell} + \rho_{v} \boldsymbol{u}_{v}= -k (\rho_{\ell} \lambda_{\ell} + \rho_{v} \lambda_{v}) \nabla p + k ( \lambda_{\ell} \rho^2_{\ell} + \lambda_{v} \rho^2_{v}) g \nabla z + k \rho_{\ell}\lambda_{\ell} \nabla P_{c}. Next, the highly nonlinear parabolic transport equation is obtained by using this total mass flux to formally eliminate the pressure variable from the individual components mass conservation equations, yielding + .. math:: -{ -\frac{\partial}{\partial t}(\phi\rho_v S_v) + \nabla \cdot F_v + \frac{\partial}{\partial t}(\phi\rho_v S_v) + \nabla \cdot F_v = - \rho_v q_v,} + \rho_v q_v, + and + .. math:: -{ -\frac{\partial}{\partial t}(\phi\rho_\ell S_\ell) + \nabla \cdot F_\ell + + \frac{\partial}{\partial t}(\phi\rho_\ell S_\ell) + \nabla \cdot F_\ell = -\rho_\ell q_\ell,} + \rho_\ell q_\ell, where the flow flux for each phase is defined as + .. math:: -{ -F_{\ell} := -\underbrace{\frac{\rho_\ell \lambda_\ell}{\rho_\ell \lambda_\ell+\rho_v \lambda_v}\boldsymbol{U}_T}_{\substack{\text{viscous} \\ \text{term}}} + -\underbrace{k \frac{\rho_\ell \lambda_\ell\rho_v \lambda_v}{\rho_\ell \lambda_\ell+\rho_v \lambda_v}(\rho_\ell - \rho_v) -g\nabla z}_{\substack{\text{buoyancy} \\ \text{term}}} -+ -\underbrace{k \frac{\rho_\ell \lambda_\ell\rho_v \lambda_v}{\rho_\ell \lambda_\ell+\rho_v \lambda_v} ( \nabla P_{c})}_{\substack{\text{capillary} \\ \text{term}}},} + { + F_{\ell} := + \frac{\rho_\ell \lambda_\ell}{\rho_\ell \lambda_\ell+\rho_v + \lambda_v}\boldsymbol{U}_T} + + k \frac{\rho_\ell \lambda_\ell\rho_v \lambda_v}{\rho_\ell \lambda_\ell+\rho_v + \lambda_v}(\rho_\ell - \rho_v) + g\nabla z + + + k \frac{\rho_\ell \lambda_\ell\rho_v \lambda_v}{\rho_\ell \lambda_\ell+\rho_v + \lambda_v} ( \nabla P_{c}) and + .. math:: -{ -F_{v} := -\underbrace{\frac{\rho_v \lambda_v}{\rho_\ell \lambda_\ell+\rho_v \lambda_v}\boldsymbol{U}_T}_{\substack{\text{viscous} \\ \text{term}}} + -\underbrace{k \frac{\rho_\ell \lambda_\ell\rho_v \lambda_v}{\rho_\ell \lambda_\ell+\rho_v \lambda_v}(\rho_v - \rho_\ell) -g\nabla z}_{\substack{\text{buoyancy} \\ \text{term}}} -- -\underbrace{k \frac{\rho_\ell \lambda_\ell\rho_v \lambda_v}{\rho_\ell \lambda_\ell+\rho_v \lambda_v} (\nabla P_{c})}_{\substack{\text{capillary} \\ \text{term}}},} + { + F_{v} := + \frac{\rho_v \lambda_v}{\rho_\ell \lambda_\ell+\rho_v + \lambda_v}\boldsymbol{U}_T} + + k \frac{\rho_\ell \lambda_\ell\rho_v \lambda_v}{\rho_\ell \lambda_\ell+\rho_v + \lambda_v}(\rho_v - \rho_\ell) + g\nabla z + - + k \frac{\rho_\ell \lambda_\ell\rho_v \lambda_v}{\rho_\ell \lambda_\ell+\rho_v + \lambda_v} ( \nabla P_{c}) + + .. _discretization: diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp index 15f2f019a58..30ccd2bafee 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp @@ -44,7 +44,7 @@ #include "physicsSolvers/fluidFlow/kernels/compositional/RelativePermeabilityUpdateKernel.hpp" #include "physicsSolvers/fluidFlow/kernels/compositional/CapillaryPressureUpdateKernel.hpp" #include "physicsSolvers/PhysicsSolverBaseKernels.hpp" -#include "physicsSolvers/fluidFlow/kernels/compositional/KernelLaunchSelectors.hpp" +#include "physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/KernelLaunchSelectors.hpp" namespace geos { @@ -226,7 +226,7 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase /** * @brief Constructor for the kernel interface - * @param[in] numPhases number of fluid phases + * @param[in] numPhases number of fluid phases * @param[in] rankOffset the offset of my MPI rank * @param[in] stencilWrapper reference to the stencil wrapper * @param[in] dofNumberAccessor @@ -638,7 +638,7 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase shiftBlockElementsAheadByOneAndReplaceFirstElementWithSum( m_numPhases, numEqn, stack.numFluxElems, stack.localFlux ); } - + // add contribution to residual and jacobian into: // - the mass balance equation // note that numDof includes derivatives wrt temperature if this class is derived in ThermalKernels @@ -767,13 +767,12 @@ class FaceBasedAssemblyKernelFactory /******************************** AccumulationKernel ********************************/ -static constexpr real64 minDensForDivision = 1e-10; - enum class KernelFlags { - // SimpleAccumulation = 1 << 0, // 1 - TotalMassEquation = 1 << 1, // 2 + TotalMassEquation = 1 << 0, // 1 + /// Add more flags like that if needed: + // Flag2 = 1 << 1, // 2 // Flag3 = 1 << 2, // 4 // Flag4 = 1 << 3, // 8 // Flag5 = 1 << 4, // 16 @@ -783,7 +782,7 @@ enum class KernelFlags }; /** * @class AccumulationKernel - * @tparam NUM_COMP number of fluid phases + * @tparam NUM_EQN number of fluid phases * @tparam NUM_DOF number of degrees of freedom * @brief Define the interface for the assembly kernel in charge of accumulation */ @@ -800,7 +799,7 @@ class AccumulationKernel static constexpr integer numDof = NUM_DOF; /// Compute time value for the number of equations - static constexpr integer numEqn = NUM_DOF; + static constexpr integer numEqn = NUM_EQN; /** * @brief Constructor @@ -812,6 +811,7 @@ class AccumulationKernel * @param[in] solid the solid model * @param[inout] localMatrix the local CRS matrix * @param[inout] localRhs the local right-hand side vector + * @param[inout] kernelFlags the kernel options */ AccumulationKernel( localIndex const numPhases, globalIndex const rankOffset, @@ -846,7 +846,7 @@ class AccumulationKernel { public: - // Pore volume information (used by both accumulation and volume balance) + // Pore volume information (used by both accumulation) /// Pore volume at time n+1 real64 poreVolume = 0.0; @@ -906,31 +906,30 @@ class AccumulationKernel * @tparam FUNC the type of the function that can be used to customize the kernel * @param[in] ei the element index * @param[inout] stack the stack variables - * @param[in] phaseAmountKernelOp the function used to customize the kernel */ template< typename FUNC = NoOpFunc > GEOS_HOST_DEVICE void computeAccumulation( localIndex const ei, StackVariables & stack, - FUNC && phaseAmountKernelOp = NoOpFunc{} ) const + FUNC = NoOpFunc{} ) const { - int signPotDiff[2] = {1, -1}; - // ic - index of component whose conservation equation is assembled - // (i.e. row number in local matrix) - for( integer ip = 0; ip < m_numPhases; ++ip ) - { - real64 const phaseMass = stack.poreVolume * m_phaseVolFrac[ei][ip] * m_phaseDens[ei][0][ip]; - real64 const phaseMass_n = m_phaseMass_n[ei][ip]; + int signPotDiff[2] = {1, -1}; + // ip - index of phase/component whose conservation equation is assembled + // (i.e. row number in local matrix) + for( integer ip = 0; ip < m_numPhases; ++ip ) + { + real64 const phaseMass = stack.poreVolume * m_phaseVolFrac[ei][ip] * m_phaseDens[ei][0][ip]; + real64 const phaseMass_n = m_phaseMass_n[ei][ip]; - stack.localResidual[ip] += phaseMass - phaseMass_n; + stack.localResidual[ip] += phaseMass - phaseMass_n; - real64 const dPhaseMass_dP = stack.dPoreVolume_dPres * m_phaseVolFrac[ei][ip] * m_phaseDens[ei][0][ip] - + stack.poreVolume * m_phaseVolFrac[ei][ip] * m_dPhaseDens[ei][0][ip][0]; - stack.localJacobian[ip][0] += dPhaseMass_dP; + real64 const dPhaseMass_dP = stack.dPoreVolume_dPres * m_phaseVolFrac[ei][ip] * m_phaseDens[ei][0][ip] + + stack.poreVolume * m_phaseVolFrac[ei][ip] * m_dPhaseDens[ei][0][ip][0]; + stack.localJacobian[ip][0] += dPhaseMass_dP; - real64 const dPhaseMass_dS = stack.poreVolume * m_phaseDens[ei][0][ip]; - stack.localJacobian[ip][1] += signPotDiff[ip] * dPhaseMass_dS; - } + real64 const dPhaseMass_dS = stack.poreVolume * m_phaseDens[ei][0][ip]; + stack.localJacobian[ip][1] += signPotDiff[ip] * dPhaseMass_dS; + } } @@ -954,8 +953,7 @@ class AccumulationKernel } // add contribution to residual and jacobian into: - // - the component mass balance equations (i = 0 to i = numComp-1) - // - the volume balance equations (i = numComp) + // - the component mass balance equations (i = 0 to i = numPhase - 1) // note that numDof includes derivatives wrt temperature if this class is derived in ThermalKernels integer const numRows = m_numPhases; for( integer i = 0; i < numRows; ++i ) @@ -1045,6 +1043,7 @@ class AccumulationKernelFactory * @tparam POLICY the policy used in the RAJA kernel * @param[in] numPhases the number of fluid phases * @param[in] rankOffset the offset of my MPI rank + * @param[inout] useTotalMassEquation option for using total mass equation * @param[in] dofKey the string key to retrieve the degress of freedom numbers * @param[in] subRegion the element subregion * @param[in] fluid the fluid model @@ -1064,10 +1063,8 @@ class AccumulationKernelFactory CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) { - - using namespace isothermalCompositionalMultiphaseBaseKernels::internal; - kernelLaunchSelectorCompSwitch( numPhases, [&] ( auto NP ) + geos::immiscibleMultiphaseKernels::kernelLaunchSelectorPhaseSwitch( numPhases, [&] ( auto NP ) { integer constexpr NUM_EQN = NP(); integer constexpr NUM_DOF = NP(); @@ -1075,11 +1072,9 @@ class AccumulationKernelFactory BitFlags< KernelFlags > kernelFlags; if( useTotalMassEquation ) kernelFlags.set( KernelFlags::TotalMassEquation ); - // if( useSimpleAccumulation ) - // kernelFlags.set( KernelFlags::SimpleAccumulation ); AccumulationKernel< NUM_EQN, NUM_DOF > kernel( numPhases, rankOffset, dofKey, subRegion, - fluid, solid, localMatrix, localRhs, kernelFlags ); + fluid, solid, localMatrix, localRhs, kernelFlags ); AccumulationKernel< NUM_EQN, NUM_DOF >::template launch< POLICY >( subRegion.size(), kernel ); } ); } @@ -1180,6 +1175,7 @@ class PhaseMobilityKernel dPhaseMob[ip][Deriv::dS] = dRelPerm_dS * density / viscosity; // } + // call the lambda in the phase loop to allow the reuse of the relperm, density, viscosity, and mobility // possible use: assemble the derivatives wrt temperature phaseMobilityKernelOp( ip, phaseMob[ip], dPhaseMob[ip] ); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/KernelLaunchSelectors.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/KernelLaunchSelectors.hpp new file mode 100644 index 00000000000..f1548bb2c7e --- /dev/null +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/KernelLaunchSelectors.hpp @@ -0,0 +1,57 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 Total, S.A + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2023-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/** + * @file KernelLaunchSelector.hpp + */ + +#ifndef GEOS_PHYSICSSOLVERS_FLUIDFLOW_IMMISCIBLE_KERNELLAUNCHSELECTOR_HPP +#define GEOS_PHYSICSSOLVERS_FLUIDFLOW_IMMISCIBLE_KERNELLAUNCHSELECTOR_HPP + +//#include "codingUtilities/Utilities.hpp" +//#include "common/DataLayouts.hpp" +//#include "common/DataTypes.hpp" +//#include "common/GEOS_RAJA_Interface.hpp" + +namespace geos +{ + +namespace immiscibleMultiphaseKernels +{ + +/******************************** Kernel launch machinery ********************************/ + + +template< typename T, typename LAMBDA > +void kernelLaunchSelectorPhaseSwitch( T value, LAMBDA && lambda ) +{ + static_assert( std::is_integral< T >::value, "kernelLaunchSelectorPhaseSwitch: type should be integral" ); + + switch( value ) + { + case 2: + { lambda( std::integral_constant< T, 2 >() ); return; } + default: + { GEOS_ERROR( "Unsupported number of phases: " << value ); } + } + +} + +} // namespace immiscibleMultiphaseKernels + +} // namespace geos + + +#endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_IMMISCIBLE_KERNELLAUNCHSELECTOR_HPP From 83783e6aedfe1e27675999508bdb468215b77e81 Mon Sep 17 00:00:00 2001 From: DENEL Bertrand Date: Thu, 21 Nov 2024 18:46:17 -0600 Subject: [PATCH 066/104] Fixed doc references. --- .../immiscible_2phaseFlow_1d.xml | 3 ++- .../physicsSolvers/PhysicsSolvers.rst | 2 ++ .../fluidFlow/docs/ImmiscibleMultiphaseFlow.rst | 16 ++++++++-------- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscible_2phaseFlow_1d.xml b/inputFiles/immiscibleMultiphaseFlow/immiscible_2phaseFlow_1d.xml index 8247d534a28..18ccf6272eb 100644 --- a/inputFiles/immiscibleMultiphaseFlow/immiscible_2phaseFlow_1d.xml +++ b/inputFiles/immiscibleMultiphaseFlow/immiscible_2phaseFlow_1d.xml @@ -1,6 +1,7 @@ + - + Date: Thu, 21 Nov 2024 19:25:34 -0600 Subject: [PATCH 067/104] Used pre-existing Geos readTable function. --- .../fluid/twophasefluid/TwoPhaseFluid.cpp | 47 +------------------ .../fluid/twophasefluid/TwoPhaseFluid.hpp | 12 ----- 2 files changed, 2 insertions(+), 57 deletions(-) diff --git a/src/coreComponents/constitutive/fluid/twophasefluid/TwoPhaseFluid.cpp b/src/coreComponents/constitutive/fluid/twophasefluid/TwoPhaseFluid.cpp index b0fc13116fa..3b119e393d8 100644 --- a/src/coreComponents/constitutive/fluid/twophasefluid/TwoPhaseFluid.cpp +++ b/src/coreComponents/constitutive/fluid/twophasefluid/TwoPhaseFluid.cpp @@ -17,6 +17,7 @@ * @file TwoPhaseFluid.cpp */ +#include "constitutive/fluid/multifluid/CO2Brine/functions/PVTFunctionHelpers.hpp" // for readTable #include "TwoPhaseFluid.hpp" #include "TwoPhaseFluidFields.hpp" @@ -114,50 +115,6 @@ void TwoPhaseFluid::postInputInitialization() } -void -TwoPhaseFluid::readTable( string const & fileName, - integer minRowLength, - array1d< array1d< real64 > > & data ) -{ - std::ifstream is( fileName ); - GEOS_THROW_IF( !is.is_open(), - GEOS_FMT( "{}: could not open file: {}", getFullName(), fileName ), - InputError ); - - // Read line-by-line until eof - string str; - while( std::getline( is, str ) ) - { - // Remove whitespace and end-of-line characters, if any - str = stringutilities::trim( str, " \r" ); - - // Remove # and -- (Eclipse-style) comments - str = stringutilities::removeStringAndFollowingContent( str, "#" ); - str = stringutilities::removeStringAndFollowingContent( str, "--" ); - - // Skip empty or comment-only strings - if( str.empty() ) - continue; - - // Add and read a new line entry - array1d< real64 > newLine = stringutilities::fromStringToArray< real64 >( str ); - if( !newLine.empty() ) - { - data.emplace_back( std::move( newLine ) ); - } - } - - is.close(); - - for( localIndex i = 0; i < data.size(); ++i ) - { - GEOS_THROW_IF( data[i].size() < minRowLength, - GEOS_FMT( "{}: too few entries in row {} of table {}, minimum {} required", getFullName(), i, fileName, minRowLength ), - InputError ); - } -} - - void TwoPhaseFluid::fillData( integer const ip, array1d< array1d< real64 > > const & tableValues ) { @@ -215,7 +172,7 @@ void TwoPhaseFluid::readInputDataFromFileTableFunctions() for( integer ip = 0; ip < 2; ++ip ) { tableValues.clear(); - readTable( m_tableFiles[ip], 3, tableValues ); + geos::constitutive::PVTProps::BlackOilTables::readTable( m_tableFiles[ip], 3, tableValues ); fillData( ip, tableValues ); } } diff --git a/src/coreComponents/constitutive/fluid/twophasefluid/TwoPhaseFluid.hpp b/src/coreComponents/constitutive/fluid/twophasefluid/TwoPhaseFluid.hpp index 9de6a4bfee4..d1da2681a25 100644 --- a/src/coreComponents/constitutive/fluid/twophasefluid/TwoPhaseFluid.hpp +++ b/src/coreComponents/constitutive/fluid/twophasefluid/TwoPhaseFluid.hpp @@ -246,18 +246,6 @@ class TwoPhaseFluid : public ConstitutiveBase void fillData( integer const ip, array1d< array1d< real64 > > const & tableValues ); - /** - * @brief Read a table from file and check its row length - * @param[in] fileName the name of the file - * @param[in] minRowLength the expected minimum row length (typically 3: pressure, density, viscosity) - * @param[out] data the data from the table - */ - void - readTable( string const & fileName, - integer minRowLength, - array1d< array1d< real64 > > & data ); - - /** * @brief Check the monotonicity of the PVT relationship */ From b23c33de97d519c1cb890510ac095da82b49d38e Mon Sep 17 00:00:00 2001 From: DENEL Bertrand Date: Fri, 6 Dec 2024 12:53:26 -0600 Subject: [PATCH 068/104] Addressed Pavel's comments. --- .../fluidFlow/ImmiscibleMultiphaseFlow.cpp | 102 +++++++++++++++++- .../fluidFlow/ImmiscibleMultiphaseFlow.hpp | 27 ++++- .../ImmiscibleMultiphaseKernels.hpp | 44 +++++--- 3 files changed, 152 insertions(+), 21 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index e44069772f7..bc667776612 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -67,6 +67,22 @@ ImmiscibleMultiphaseFlow::ImmiscibleMultiphaseFlow( const string & name, setInputFlag( InputFlags::OPTIONAL ). setApplyDefaultValue( 1 ). setDescription( "Flag indicating whether total mass equation is used" ); + + this->registerWrapper( viewKeyStruct::solutionChangeScalingFactorString(), &m_solutionChangeScalingFactor ). + setSizedFromParent( 0 ). + setInputFlag( InputFlags::OPTIONAL ). + setApplyDefaultValue( 0.5 ). + setDescription( "Damping factor for solution change targets" ); + this->registerWrapper( viewKeyStruct::targetRelativePresChangeString(), &m_targetRelativePresChange ). + setSizedFromParent( 0 ). + setInputFlag( InputFlags::OPTIONAL ). + setApplyDefaultValue( 0.2 ). + setDescription( "Target (relative) change in pressure in a time step (expected value between 0 and 1)" ); + this->registerWrapper( viewKeyStruct::targetPhaseVolFracChangeString(), &m_targetPhaseVolFracChange ). + setSizedFromParent( 0 ). + setInputFlag( InputFlags::OPTIONAL ). + setApplyDefaultValue( 0.2 ). + setDescription( "Target (absolute) change in phase volume fraction in a time step" ); } void ImmiscibleMultiphaseFlow::postInputInitialization() @@ -288,7 +304,7 @@ void ImmiscibleMultiphaseFlow::updateFluidState( ElementSubRegionBase & subRegio GEOS_MARK_FUNCTION; updateFluidModel( subRegion ); - updatePhaseVolumeFraction( subRegion ); + updateVolumeConstraint( subRegion ); updatePhaseMass( subRegion ); updateRelPermModel( subRegion ); updatePhaseMobility( subRegion ); @@ -401,7 +417,7 @@ void ImmiscibleMultiphaseFlow::initializeFluidState( MeshLevel & mesh, // Also, initialize the fluid model // // Note: - // - This must be called after updatePhaseVolumeFraction + // - This must be called after updateVolumeConstraint // - This step depends on phaseVolFraction // initialized phase volume fraction @@ -533,7 +549,7 @@ ImmiscibleMultiphaseFlow::implicitStepSetup( real64 const & GEOS_UNUSED_PARAM( t // update porosity, permeability updatePorosityAndPermeability( subRegion ); // update all fluid properties - updatePhaseVolumeFraction( subRegion ); + updateVolumeConstraint( subRegion ); updateFluidState( subRegion ); // after the update, save the new saturation @@ -1107,7 +1123,7 @@ void ImmiscibleMultiphaseFlow::applySystemSolution( DofManager const & dofManage } -void ImmiscibleMultiphaseFlow::updatePhaseVolumeFraction( ElementSubRegionBase & subRegion ) const +void ImmiscibleMultiphaseFlow::updateVolumeConstraint( ElementSubRegionBase & subRegion ) const { GEOS_MARK_FUNCTION; @@ -1261,12 +1277,88 @@ void ImmiscibleMultiphaseFlow::updateState( DomainPartition & domain ) // update porosity, permeability, and solid internal energy updatePorosityAndPermeability( subRegion ); // update all fluid properties - updatePhaseVolumeFraction( subRegion ); + updateVolumeConstraint( subRegion ); updateFluidState( subRegion ); } ); } ); } +real64 ImmiscibleMultiphaseFlow::setNextDtBasedOnStateChange( real64 const & currentDt, + DomainPartition & domain ) +{ + if( m_targetRelativePresChange >= 1.0 && + m_targetPhaseVolFracChange >= 1.0 ) + { + return LvArray::NumericLimits< real64 >::max; + } + + real64 maxRelativePresChange = 0.0; + real64 maxAbsolutePhaseVolFracChange = 0.0; + + integer const numPhase = m_numPhases; + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + arrayView1d< string const > const & regionNames ) + { + mesh.getElemManager().forElementSubRegions( regionNames, + [&]( localIndex const, + ElementSubRegionBase & subRegion ) + { + arrayView1d< integer const > const ghostRank = subRegion.ghostRank(); + + arrayView1d< real64 const > const pres = subRegion.getField< fields::flow::pressure >(); + arrayView1d< real64 const > const pres_n = subRegion.getField< fields::flow::pressure_n >(); + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac = + subRegion.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); + arrayView2d< real64, immiscibleFlow::USD_PHASE > const phaseVolFrac_n = + subRegion.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction_n >(); + + RAJA::ReduceMax< parallelDeviceReduce, real64 > subRegionMaxPresChange( 0.0 ); + RAJA::ReduceMax< parallelDeviceReduce, real64 > subRegionMaxPhaseVolFracChange( 0.0 ); + + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const ei ) + { + if( ghostRank[ei] < 0 ) + { + // switch from relative to absolute when values less than 1 + subRegionMaxPresChange.max( LvArray::math::abs( pres[ei] - pres_n[ei] ) / LvArray::math::max( LvArray::math::abs( pres_n[ei] ), 1.0 ) ); + for( integer ip = 0; ip < numPhase; ++ip ) + { + subRegionMaxPhaseVolFracChange.max( LvArray::math::abs( phaseVolFrac[ei][ip] - phaseVolFrac_n[ei][ip] ) ); + } + } + } ); + + maxRelativePresChange = LvArray::math::max( maxRelativePresChange, subRegionMaxPresChange.get() ); + maxAbsolutePhaseVolFracChange = LvArray::math::max( maxAbsolutePhaseVolFracChange, subRegionMaxPhaseVolFracChange.get() ); + + } ); + } ); + + maxRelativePresChange = MpiWrapper::max( maxRelativePresChange ); + maxAbsolutePhaseVolFracChange = MpiWrapper::max( maxAbsolutePhaseVolFracChange ); + + GEOS_LOG_LEVEL_INFO_RANK_0( logInfo::TimeStep, GEOS_FMT( "{}: max relative pressure change during time step = {} %", + getName(), GEOS_FMT( "{:.{}f}", 100*maxRelativePresChange, 3 ) ) ); + GEOS_LOG_LEVEL_INFO_RANK_0( logInfo::TimeStep, GEOS_FMT( "{}: max absolute phase volume fraction change during time step = {}", + getName(), GEOS_FMT( "{:.{}f}", maxAbsolutePhaseVolFracChange, 3 ) ) ); + + real64 const eps = LvArray::NumericLimits< real64 >::epsilon; + + real64 const nextDtPressure = currentDt * ( 1.0 + m_solutionChangeScalingFactor ) * m_targetRelativePresChange + / std::max( eps, maxRelativePresChange + m_solutionChangeScalingFactor * m_targetRelativePresChange ); + if( m_nonlinearSolverParameters.getLogLevel() > 0 ) + GEOS_LOG_RANK_0( GEOS_FMT( "{}: next time step based on pressure change = {}", getName(), nextDtPressure )); + real64 const nextDtPhaseVolFrac = currentDt * ( 1.0 + m_solutionChangeScalingFactor ) * m_targetPhaseVolFracChange + / std::max( eps, maxAbsolutePhaseVolFracChange + m_solutionChangeScalingFactor * m_targetPhaseVolFracChange ); + if( m_nonlinearSolverParameters.getLogLevel() > 0 ) + GEOS_LOG_RANK_0( GEOS_FMT( "{}: next time step based on phase volume fraction change = {}", getName(), nextDtPhaseVolFrac )); + + return std::min( nextDtPressure, nextDtPhaseVolFrac ); + +} + real64 ImmiscibleMultiphaseFlow::setNextDt( const geos::real64 & currentDt, geos::DomainPartition & domain ) { return PhysicsSolverBase::setNextDt( currentDt, domain ); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp index 142c7e9cdf9..c8a072eb58b 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp @@ -125,7 +125,7 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase void updateFluidState( ElementSubRegionBase & subRegion ) const; - void updatePhaseVolumeFraction( ElementSubRegionBase & subRegion ) const; + void updateVolumeConstraint( ElementSubRegionBase & subRegion ) const; virtual void saveConvergedState( ElementSubRegionBase & subRegion ) const override final; @@ -204,8 +204,12 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase * @param[in] domain the domain object * @return the prescribed time step size */ - real64 setNextDt( real64 const & currentDt, - DomainPartition & domain ) override; + + virtual real64 setNextDtBasedOnStateChange( real64 const & currentDt, + DomainPartition & domain ) override; + + real64 setNextDt( real64 const & currentDt, + DomainPartition & domain ) override; virtual void initializePostInitialConditionsPreSubGroups() override; @@ -217,9 +221,18 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase struct viewKeyStruct : public FlowSolverBase::viewKeyStruct { + // inputs static constexpr char const * capPressureNamesString() { return "capPressureNames"; } static constexpr char const * relPermNamesString() { return "relPermNames"; } static constexpr char const * elemDofFieldString() { return "elemDofField"; } + + // time stepping controls + static constexpr char const * solutionChangeScalingFactorString() { return "solutionChangeScalingFactor"; } + static constexpr char const * targetRelativePresChangeString() { return "targetRelativePressureChangeInTimeStep"; } + static constexpr char const * targetPhaseVolFracChangeString() { return "targetPhaseVolFractionChangeInTimeStep"; } + + // nonlinear solver parameters + static constexpr char const * maxRelativePresChangeString() { return "maxRelativePressureChange"; } static constexpr char const * useTotalMassEquationString() { return "useTotalMassEquation"; } }; @@ -280,6 +293,14 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase /// flag to determine whether or not to use total velocity formulation integer m_useTotalMassEquation; + /// target (relative) change in pressure in a time step + real64 m_targetRelativePresChange; + + /// target (absolute) change in phase volume fraction in a time step + real64 m_targetPhaseVolFracChange; + + /// damping factor for solution change targets + real64 m_solutionChangeScalingFactor; private: diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp index 30ccd2bafee..582cb139ef0 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp @@ -78,6 +78,7 @@ class FaceBasedAssemblyKernelBase StencilAccessors< fields::ghostRank, fields::flow::pressure, fields::flow::gravityCoefficient, + fields::immiscibleMultiphaseFlow::phaseVolumeFraction, fields::immiscibleMultiphaseFlow::phaseMobility, fields::immiscibleMultiphaseFlow::dPhaseMobility >; @@ -134,6 +135,7 @@ class FaceBasedAssemblyKernelBase m_ghostRank( multiPhaseFlowAccessors.get( fields::ghostRank {} ) ), m_gravCoef( multiPhaseFlowAccessors.get( fields::flow::gravityCoefficient {} ) ), m_pres( multiPhaseFlowAccessors.get( fields::flow::pressure {} ) ), + m_phaseVolFrac( multiPhaseFlowAccessors.get( fields::immiscibleMultiphaseFlow::phaseVolumeFraction {} ) ), m_mob( multiPhaseFlowAccessors.get( fields::immiscibleMultiphaseFlow::phaseMobility {} ) ), m_dMob( multiPhaseFlowAccessors.get( fields::immiscibleMultiphaseFlow::dPhaseMobility {} ) ), m_dens( fluidAccessors.get( fields::twophasefluid::phaseDensity {} ) ), @@ -169,8 +171,9 @@ class FaceBasedAssemblyKernelBase ElementViewConst< arrayView1d< real64 const > > const m_gravCoef; // Primary and secondary variables - /// Views on pressure + /// Views on pressure and phase volume fraction ElementViewConst< arrayView1d< real64 const > > const m_pres; + ElementViewConst< arrayView2d< real64 const, immiscibleFlow::USD_PHASE > > const m_phaseVolFrac; /// Views on fluid mobility ElementViewConst< arrayView2d< real64 const, immiscibleFlow::USD_PHASE > > const m_mob; @@ -421,15 +424,33 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase for( integer ip = 0; ip < m_numPhases; ++ip ) { // calculate quantities on primary connected cells + integer denom = 0; for( integer ke = 0; ke < 2; ++ke ) { // density - real64 const density = m_dens[seri[ke]][sesri[ke]][sei[ke]][0][ip]; // r = rho1 || rho2 + bool const phaseExists = (m_phaseVolFrac[seri[ke]][sesri[ke]][sei[ke]][ip] > 0); + if( !phaseExists ) + { + continue; + } + + real64 const density = m_dens[seri[ke]][sesri[ke]][sei[ke]][0][ip]; // r = rho1 || rho2 real64 const dDens_dP = m_dDens_dPres[seri[ke]][sesri[ke]][sei[ke]][0][ip][Deriv::dP]; // dr/dP = dr1/dP1 || dr2/dP // average density and derivatives - densMean[ip] += 0.5 * density; // rho = (rho1 + rho2) / 2 - dDensMean_dP[ip][ke] = 0.5 * dDens_dP; // drho/dP = { (dr1/dP1)/2 , (dr2/dP2)/2 } + densMean[ip] += density; // rho = (rho1 + rho2) + dDensMean_dP[ip][ke] = dDens_dP; // drho/dP = { (dr1/dP1) , (dr2/dP2) } + + denom++; + } + + if( denom > 1 ) + { + densMean[ip] /= denom; // rho = (rho1 + rho2) / denom + for( integer ke = 0; ke < 2; ++ke ) + { + dDensMean_dP[ip][ke] /= denom; // drho/dP = { (dr1/dP1) / denom , (dr2/dP2) / denom } + } } //***** calculation of flux ***** @@ -439,7 +460,7 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase real64 dPresGrad_dTrans = 0.0; real64 dGravHead_dTrans = 0.0; real64 dCapGrad_dTrans = 0.0; - int signPotDiff[2] = {1, -1}; + constexpr int signPotDiff[2] = {1, -1}; for( integer ke = 0; ke < 2; ++ke ) { @@ -903,17 +924,14 @@ class AccumulationKernel /** * @brief Compute the local accumulation contributions to the residual and Jacobian - * @tparam FUNC the type of the function that can be used to customize the kernel * @param[in] ei the element index * @param[inout] stack the stack variables */ - template< typename FUNC = NoOpFunc > GEOS_HOST_DEVICE void computeAccumulation( localIndex const ei, - StackVariables & stack, - FUNC = NoOpFunc{} ) const + StackVariables & stack ) const { - int signPotDiff[2] = {1, -1}; + constexpr int sign[2] = {1, -1}; // ip - index of phase/component whose conservation equation is assembled // (i.e. row number in local matrix) for( integer ip = 0; ip < m_numPhases; ++ip ) @@ -928,9 +946,8 @@ class AccumulationKernel stack.localJacobian[ip][0] += dPhaseMass_dP; real64 const dPhaseMass_dS = stack.poreVolume * m_phaseDens[ei][0][ip]; - stack.localJacobian[ip][1] += signPotDiff[ip] * dPhaseMass_dS; + stack.localJacobian[ip][1] += sign[ip] * dPhaseMass_dS; } - } /** @@ -1153,7 +1170,7 @@ class PhaseMobilityKernel arraySlice1d< real64, immiscibleFlow::USD_PHASE - 1 > const phaseMob = m_phaseMob[ei]; arraySlice2d< real64, immiscibleFlow::USD_PHASE_DS - 1 > const dPhaseMob = m_dPhaseMob[ei]; - int sign[2] = {1, -1}; + constexpr int sign[2] = {1, -1}; for( integer ip = 0; ip < numPhase; ++ip ) { @@ -1171,6 +1188,7 @@ class PhaseMobilityKernel // for( integer jp = 0; jp < numPhase-1; ++jp ) // { + // Derivative matrix is currently diagonal. Implementation below handles missing off-diagonal entry. real64 const dRelPerm_dS = sign[ip] * m_dPhaseRelPerm_dPhaseVolFrac[ei][0][ip][ip]; dPhaseMob[ip][Deriv::dS] = dRelPerm_dS * density / viscosity; // } From 557b179d093f1e876471fb8c27dc69735132d956 Mon Sep 17 00:00:00 2001 From: Pavel Tomin Date: Sat, 7 Dec 2024 10:51:41 -0600 Subject: [PATCH 069/104] code style --- .../physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp index c8a072eb58b..3698fc0a904 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp @@ -206,10 +206,10 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase */ virtual real64 setNextDtBasedOnStateChange( real64 const & currentDt, - DomainPartition & domain ) override; + DomainPartition & domain ) override; - real64 setNextDt( real64 const & currentDt, - DomainPartition & domain ) override; + real64 setNextDt( real64 const & currentDt, + DomainPartition & domain ) override; virtual void initializePostInitialConditionsPreSubGroups() override; From 3cef9abfc03f0edb53f9a1f7b5e71e225c3ca1b9 Mon Sep 17 00:00:00 2001 From: DENEL Bertrand Date: Mon, 9 Dec 2024 19:06:34 -0600 Subject: [PATCH 070/104] Used the newly introduced initializeState from FlowSolverBase. --- .../mgrStrategies/ImmiscibleMultiphaseFVM.hpp | 5 --- .../fluidFlow/ImmiscibleMultiphaseFlow.cpp | 37 ++----------------- .../fluidFlow/ImmiscibleMultiphaseFlow.hpp | 16 +++----- 3 files changed, 8 insertions(+), 50 deletions(-) diff --git a/src/coreComponents/linearAlgebra/interfaces/hypre/mgrStrategies/ImmiscibleMultiphaseFVM.hpp b/src/coreComponents/linearAlgebra/interfaces/hypre/mgrStrategies/ImmiscibleMultiphaseFVM.hpp index 3f05ac5987a..21239def26e 100644 --- a/src/coreComponents/linearAlgebra/interfaces/hypre/mgrStrategies/ImmiscibleMultiphaseFVM.hpp +++ b/src/coreComponents/linearAlgebra/interfaces/hypre/mgrStrategies/ImmiscibleMultiphaseFVM.hpp @@ -55,11 +55,6 @@ class ImmiscibleMultiphaseFVM : public MGRStrategyBase< 1 > explicit ImmiscibleMultiphaseFVM( arrayView1d< int const > const & numComponentsPerField ) : MGRStrategyBase( LvArray::integerConversion< HYPRE_Int >( numComponentsPerField[0] ) ) { - // Level 0: eliminate last density which corresponds to the volume constraint equation - // m_labels[0].resize( m_numBlocks - 1 ); - // std::iota( m_labels[0].begin(), m_labels[0].end(), 0 ); - - // Level 0: eliminate the phase volume fractions m_labels[0].push_back( 0 ); setupLabels(); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index bc667776612..d610b2e39fb 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -363,7 +363,6 @@ void ImmiscibleMultiphaseFlow::updatePhaseMobility( ObjectManagerBase & dataGrou } void ImmiscibleMultiphaseFlow::initializeFluidState( MeshLevel & mesh, - DomainPartition & GEOS_UNUSED_PARAM( domain ), arrayView1d< string const > const & regionNames ) { GEOS_MARK_FUNCTION; @@ -477,6 +476,7 @@ void ImmiscibleMultiphaseFlow::initializeFluidState( MeshLevel & mesh, } ); } + void ImmiscibleMultiphaseFlow::initializePostInitialConditionsPreSubGroups() { GEOS_MARK_FUNCTION; @@ -495,41 +495,12 @@ void ImmiscibleMultiphaseFlow::initializePostInitialConditionsPreSubGroups() regionNames ); CommunicationTools::getInstance().synchronizeFields( fieldsToBeSync, mesh, domain.getNeighbors(), false ); - - mesh.getElemManager().forElementSubRegions< CellElementSubRegion, SurfaceElementSubRegion >( regionNames, - [&]( localIndex const, - auto & subRegion ) - { - saveConvergedState( subRegion ); // necessary for a meaningful porosity update in sequential schemes - updatePorosityAndPermeability( subRegion ); - - CoupledSolidBase const & porousSolid = - getConstitutiveModel< CoupledSolidBase >( subRegion, - subRegion.template getReference< string >( viewKeyStruct::solidNamesString() ) ); - porousSolid.initializeState(); - } ); - - // Initialize primary variables from applied initial conditions - initializeFluidState( mesh, domain, regionNames ); - - mesh.getElemManager().forElementRegions< SurfaceElementRegion >( regionNames, - [&]( localIndex const, - SurfaceElementRegion & region ) - { - region.forElementSubRegions< FaceElementSubRegion >( [&]( FaceElementSubRegion & subRegion ) - { - subRegion.getWrapper< real64_array >( fields::flow::hydraulicAperture::key() ). - setApplyDefaultValue( region.getDefaultAperture() ); - } ); - } ); - } ); - // report to the user if some pore volumes are very small - // note: this function is here because: 1) porosity has been initialized and 2) NTG has been applied - validatePoreVolumes( domain ); + initializeState( domain ); } + void ImmiscibleMultiphaseFlow::implicitStepSetup( real64 const & GEOS_UNUSED_PARAM( time_n ), real64 const & GEOS_UNUSED_PARAM( dt ), @@ -632,8 +603,6 @@ void ImmiscibleMultiphaseFlow::assembleAccumulationTerm( DomainPartition & domai } ); } ); - - } void ImmiscibleMultiphaseFlow::assembleFluxTerms( real64 const dt, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp index 3698fc0a904..054388fb35c 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp @@ -166,15 +166,6 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase DofManager const & dofManager, CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) const; - /** - * @brief Initialize all variables from initial conditions - * @param domain the domain containing the mesh and fields - * - * Initialize all variables from initial conditions. This calculating primary variable values - * from prescribed intermediate values (i.e. global densities from global fractions) - * and any applicable hydrostatic equilibration of the domain - */ - void initializeFluidState( MeshLevel & mesh, DomainPartition & domain, arrayView1d< string const > const & regionNames ); /** * @brief Function to perform the Application of Dirichlet type BC's @@ -211,8 +202,13 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase real64 setNextDt( real64 const & currentDt, DomainPartition & domain ) override; + virtual void initializePreSubGroups() override; + virtual void initializePostInitialConditionsPreSubGroups() override; + virtual void initializeFluidState( MeshLevel & mesh, arrayView1d< string const > const & regionNames ) override; + + /** * @brief Function to update fluid mass * @param subRegion subregion that contains the fields @@ -241,8 +237,6 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase virtual void postInputInitialization() override; - virtual void initializePreSubGroups() override; - /** * @brief Update all relevant fluid models using current values of pressure and phase volume fraction * @param dataGroup the group storing the required fields From 8bb5ba63d0b656ff8d68f0b1d8a478c9bd979d46 Mon Sep 17 00:00:00 2001 From: DENEL Bertrand Date: Mon, 9 Dec 2024 19:09:18 -0600 Subject: [PATCH 071/104] Fixed style. --- .../physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index d610b2e39fb..c80d31ea74d 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -497,7 +497,7 @@ void ImmiscibleMultiphaseFlow::initializePostInitialConditionsPreSubGroups() CommunicationTools::getInstance().synchronizeFields( fieldsToBeSync, mesh, domain.getNeighbors(), false ); } ); - initializeState( domain ); + initializeState( domain ); } From 3ddd347c31a13942031952ada2f5c64aa3b7a7be Mon Sep 17 00:00:00 2001 From: DENEL Bertrand Date: Tue, 10 Dec 2024 12:29:04 -0600 Subject: [PATCH 072/104] Changed Total S.A. --- .../hypre/mgrStrategies/ImmiscibleMultiphaseFVM.hpp | 2 +- .../physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp | 2 +- .../physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp | 2 +- .../fluidFlow/ImmiscibleMultiphaseFlowFields.hpp | 2 +- .../immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp | 2 +- .../kernels/immiscibleMultiphase/KernelLaunchSelectors.hpp | 6 +----- .../unitTests/constitutiveTests/testTwoPhaseFluid.cpp | 2 +- .../fluidFlowTests/testImmiscibleMultiphaseFlow.cpp | 2 +- 8 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/coreComponents/linearAlgebra/interfaces/hypre/mgrStrategies/ImmiscibleMultiphaseFVM.hpp b/src/coreComponents/linearAlgebra/interfaces/hypre/mgrStrategies/ImmiscibleMultiphaseFVM.hpp index 21239def26e..da7ef1409f9 100644 --- a/src/coreComponents/linearAlgebra/interfaces/hypre/mgrStrategies/ImmiscibleMultiphaseFVM.hpp +++ b/src/coreComponents/linearAlgebra/interfaces/hypre/mgrStrategies/ImmiscibleMultiphaseFVM.hpp @@ -3,7 +3,7 @@ * SPDX-License-Identifier: LGPL-2.1-only * * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC - * Copyright (c) 2018-2024 Total, S.A + * Copyright (c) 2018-2024 TotalEnergies * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University * Copyright (c) 2023-2024 Chevron * Copyright (c) 2019- GEOS/GEOSX Contributors diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index c80d31ea74d..fb68e47ef0b 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -3,7 +3,7 @@ * SPDX-License-Identifier: LGPL-2.1-only * * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC - * Copyright (c) 2018-2024 Total, S.A + * Copyright (c) 2018-2024 TotalEnergies * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University * Copyright (c) 2023-2024 Chevron * Copyright (c) 2019- GEOS/GEOSX Contributors diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp index 054388fb35c..c1037070526 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp @@ -3,7 +3,7 @@ * SPDX-License-Identifier: LGPL-2.1-only * * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC - * Copyright (c) 2018-2024 Total, S.A + * Copyright (c) 2018-2024 TotalEnergies * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University * Copyright (c) 2023-2024 Chevron * Copyright (c) 2019- GEOS/GEOSX Contributors diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp index 48d560815d9..17fdb8f04ee 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp @@ -3,7 +3,7 @@ * SPDX-License-Identifier: LGPL-2.1-only * * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC - * Copyright (c) 2018-2024 Total, S.A + * Copyright (c) 2018-2024 TotalEnergies * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University * Copyright (c) 2023-2024 Chevron * Copyright (c) 2019- GEOS/GEOSX Contributors diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp index 582cb139ef0..a1b1bcd56b1 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp @@ -3,7 +3,7 @@ * SPDX-License-Identifier: LGPL-2.1-only * * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC - * Copyright (c) 2018-2024 Total, S.A + * Copyright (c) 2018-2024 TotalEnergies * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University * Copyright (c) 2023-2024 Chevron * Copyright (c) 2019- GEOS/GEOSX Contributors diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/KernelLaunchSelectors.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/KernelLaunchSelectors.hpp index f1548bb2c7e..f219c31382a 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/KernelLaunchSelectors.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/KernelLaunchSelectors.hpp @@ -3,7 +3,7 @@ * SPDX-License-Identifier: LGPL-2.1-only * * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC - * Copyright (c) 2018-2024 Total, S.A + * Copyright (c) 2018-2024 TotalEnergies * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University * Copyright (c) 2023-2024 Chevron * Copyright (c) 2019- GEOS/GEOSX Contributors @@ -20,10 +20,6 @@ #ifndef GEOS_PHYSICSSOLVERS_FLUIDFLOW_IMMISCIBLE_KERNELLAUNCHSELECTOR_HPP #define GEOS_PHYSICSSOLVERS_FLUIDFLOW_IMMISCIBLE_KERNELLAUNCHSELECTOR_HPP -//#include "codingUtilities/Utilities.hpp" -//#include "common/DataLayouts.hpp" -//#include "common/DataTypes.hpp" -//#include "common/GEOS_RAJA_Interface.hpp" namespace geos { diff --git a/src/coreComponents/unitTests/constitutiveTests/testTwoPhaseFluid.cpp b/src/coreComponents/unitTests/constitutiveTests/testTwoPhaseFluid.cpp index b37fc732a55..b456b3468bb 100644 --- a/src/coreComponents/unitTests/constitutiveTests/testTwoPhaseFluid.cpp +++ b/src/coreComponents/unitTests/constitutiveTests/testTwoPhaseFluid.cpp @@ -3,7 +3,7 @@ * SPDX-License-Identifier: LGPL-2.1-only * * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC - * Copyright (c) 2018-2024 Total, S.A + * Copyright (c) 2018-2024 TotalEnergies * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University * Copyright (c) 2023-2024 Chevron * Copyright (c) 2019- GEOS/GEOSX Contributors diff --git a/src/coreComponents/unitTests/fluidFlowTests/testImmiscibleMultiphaseFlow.cpp b/src/coreComponents/unitTests/fluidFlowTests/testImmiscibleMultiphaseFlow.cpp index a1fc731b321..d86be36ea17 100644 --- a/src/coreComponents/unitTests/fluidFlowTests/testImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/unitTests/fluidFlowTests/testImmiscibleMultiphaseFlow.cpp @@ -3,7 +3,7 @@ * SPDX-License-Identifier: LGPL-2.1-only * * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC - * Copyright (c) 2018-2024 Total, S.A + * Copyright (c) 2018-2024 TotalEnergies * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University * Copyright (c) 2023-2024 Chevron * Copyright (c) 2019- GEOS/GEOSX Contributors From 8d0cd414fd934fc79fcf078cc6e804600118e1b1 Mon Sep 17 00:00:00 2001 From: DENEL Bertrand Date: Tue, 10 Dec 2024 16:41:30 -0600 Subject: [PATCH 073/104] Made density averaging optional (need gpu validation). --- .../fluidFlow/ImmiscibleMultiphaseFlow.cpp | 7 +++++ .../fluidFlow/ImmiscibleMultiphaseFlow.hpp | 27 +++++++++++++++++++ .../ImmiscibleMultiphaseKernels.hpp | 19 ++++++++----- 3 files changed, 47 insertions(+), 6 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index fb68e47ef0b..8a43a9218ce 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -68,6 +68,12 @@ ImmiscibleMultiphaseFlow::ImmiscibleMultiphaseFlow( const string & name, setApplyDefaultValue( 1 ). setDescription( "Flag indicating whether total mass equation is used" ); + this->registerWrapper( viewKeyStruct::gravityDensitySchemeString(), &m_gravityDensityScheme ). + setSizedFromParent( 0 ). + setInputFlag( InputFlags::OPTIONAL ). + setApplyDefaultValue( GravityDensityScheme::ArithmeticAverage ). + setDescription( "Scheme for density treatment in gravity" ); + this->registerWrapper( viewKeyStruct::solutionChangeScalingFactorString(), &m_solutionChangeScalingFactor ). setSizedFromParent( 0 ). setInputFlag( InputFlags::OPTIONAL ). @@ -632,6 +638,7 @@ void ImmiscibleMultiphaseFlow::assembleFluxTerms( real64 const dt, dofKey, m_hasCapPressure, m_useTotalMassEquation, + m_gravityDensityScheme == GravityDensityScheme::PhasePresence, getName(), mesh.getElemManager(), stencilWrapper, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp index c1037070526..4d6ccbd8b21 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp @@ -27,6 +27,27 @@ namespace geos { +/** + * @brief Options for density treatment in gravity + */ +enum class GravityDensityScheme : integer +{ + ArithmeticAverage, ///< average phase density is computed using simple arithmetic average: + /// rho_ave = 0.5 * (rho_i + rho_j) + PhasePresence, ///< average phase density is computed using checking for phase presence: + /// rho_ave = 0.5 * (rho_i + rho_j) if phase is present in both cells i and j + /// = rho_i if phase is present in only cell i + /// = rho_j if phase is present in only cell j +}; + +/** + * @brief Strings for options for density treatment in gravity + */ +ENUM_STRINGS( GravityDensityScheme, + "ArithmeticAverage", + "PhasePresence" ); + + //START_SPHINX_INCLUDE_00 /** * @class ImmiscibleMultiphaseFlow @@ -222,6 +243,9 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase static constexpr char const * relPermNamesString() { return "relPermNames"; } static constexpr char const * elemDofFieldString() { return "elemDofField"; } + // density averaging scheme + static constexpr char const * gravityDensitySchemeString() { return "gravityDensityScheme"; } + // time stepping controls static constexpr char const * solutionChangeScalingFactorString() { return "solutionChangeScalingFactor"; } static constexpr char const * targetRelativePresChangeString() { return "targetRelativePressureChangeInTimeStep"; } @@ -287,6 +311,9 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase /// flag to determine whether or not to use total velocity formulation integer m_useTotalMassEquation; + /// scheme for density treatment in gravity + GravityDensityScheme m_gravityDensityScheme; + /// target (relative) change in pressure in a time step real64 m_targetRelativePresChange; diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp index a1b1bcd56b1..0f2e4045be4 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp @@ -125,7 +125,8 @@ class FaceBasedAssemblyKernelBase CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs, integer const hasCapPressure, - integer const useTotalMassEquation ) + integer const useTotalMassEquation, + integer const checkPhasePresenceInGravity ) : m_numPhases ( numPhases ), m_rankOffset( rankOffset ), m_dt( dt ), @@ -145,7 +146,8 @@ class FaceBasedAssemblyKernelBase m_localMatrix( localMatrix ), m_localRhs( localRhs ), m_hasCapPressure ( hasCapPressure ), - m_useTotalMassEquation ( useTotalMassEquation ) + m_useTotalMassEquation ( useTotalMassEquation ), + m_checkPhasePresenceInGravity ( checkPhasePresenceInGravity ) {} protected: @@ -197,6 +199,7 @@ class FaceBasedAssemblyKernelBase // Flags integer const m_hasCapPressure; integer const m_useTotalMassEquation; + integer const m_checkPhasePresenceInGravity; }; /***************************************** */ @@ -255,7 +258,8 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs, integer const hasCapPressure, - integer const useTotalMassEquation ) + integer const useTotalMassEquation, + integer const checkPhasePresenceInGravity ) : FaceBasedAssemblyKernelBase( numPhases, rankOffset, dofNumberAccessor, @@ -267,7 +271,8 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase localMatrix, localRhs, hasCapPressure, - useTotalMassEquation ), + useTotalMassEquation, + checkPhasePresenceInGravity ), m_stencilWrapper( stencilWrapper ), m_seri( stencilWrapper.getElementRegionIndices() ), m_sesri( stencilWrapper.getElementSubRegionIndices() ), @@ -429,7 +434,7 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase { // density bool const phaseExists = (m_phaseVolFrac[seri[ke]][sesri[ke]][sei[ke]][ip] > 0); - if( !phaseExists ) + if( m_checkPhasePresenceInGravity && !phaseExists ) { continue; } @@ -758,6 +763,7 @@ class FaceBasedAssemblyKernelFactory string const & dofKey, integer const hasCapPressure, integer const useTotalMassEquation, + integer const checkPhasePresenceInGravity, string const & solverName, ElementRegionManager const & elemManager, STENCILWRAPPER const & stencilWrapper, @@ -780,7 +786,8 @@ class FaceBasedAssemblyKernelFactory kernelType kernel( numPhases, rankOffset, stencilWrapper, dofNumberAccessor, flowAccessors, fluidAccessors, capPressureAccessors, permAccessors, - dt, localMatrix, localRhs, hasCapPressure, useTotalMassEquation ); + dt, localMatrix, localRhs, hasCapPressure, useTotalMassEquation, + checkPhasePresenceInGravity ); kernelType::template launch< POLICY >( stencilWrapper.size(), kernel ); } }; From f39620c1354b6ef37020b887cc08018a74137e33 Mon Sep 17 00:00:00 2001 From: DENEL Bertrand Date: Wed, 11 Dec 2024 19:32:12 -0600 Subject: [PATCH 074/104] Added schema. --- src/coreComponents/schema/schema.xsd | 86 ++++++++++- src/coreComponents/schema/schema.xsd.other | 163 ++++++++++++--------- 2 files changed, 178 insertions(+), 71 deletions(-) diff --git a/src/coreComponents/schema/schema.xsd b/src/coreComponents/schema/schema.xsd index e130b1e56d4..101588f0552 100644 --- a/src/coreComponents/schema/schema.xsd +++ b/src/coreComponents/schema/schema.xsd @@ -371,6 +371,10 @@ + + + + @@ -887,6 +891,10 @@ + + + + @@ -2284,6 +2292,7 @@ Level 0 outputs no specific information for this solver. Higher levels require m + @@ -3245,7 +3254,7 @@ Level 0 outputs no specific information for this solver. Higher levels require m - + @@ -3268,11 +3277,69 @@ Local- Add jump stabilization on interior of macro elements--> - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -5065,6 +5132,7 @@ Level 0 outputs no specific information for this solver. Higher levels require m + @@ -6524,6 +6592,20 @@ To neglect hysteresis on this phase, just use the same table name for the draina + + + + + + + + + + + + diff --git a/src/coreComponents/schema/schema.xsd.other b/src/coreComponents/schema/schema.xsd.other index 3abf5b863f0..15de6269856 100644 --- a/src/coreComponents/schema/schema.xsd.other +++ b/src/coreComponents/schema/schema.xsd.other @@ -486,7 +486,7 @@ - + @@ -531,6 +531,7 @@ + @@ -572,7 +573,7 @@ - + @@ -609,7 +610,7 @@ - + @@ -660,7 +661,7 @@ - + @@ -701,7 +702,7 @@ - + @@ -734,7 +735,7 @@ - + @@ -745,7 +746,7 @@ - + @@ -758,7 +759,7 @@ - + @@ -771,7 +772,7 @@ - + @@ -787,7 +788,7 @@ - + @@ -821,7 +822,7 @@ - + @@ -884,7 +885,7 @@ - + @@ -915,7 +916,7 @@ - + @@ -928,7 +929,7 @@ - + @@ -941,10 +942,21 @@ - + + + + + + + + + + + + @@ -954,7 +966,7 @@ - + @@ -967,7 +979,7 @@ - + @@ -982,7 +994,7 @@ - + @@ -993,7 +1005,7 @@ - + @@ -1006,7 +1018,7 @@ - + @@ -1017,7 +1029,7 @@ - + @@ -1028,7 +1040,7 @@ - + @@ -1039,7 +1051,7 @@ - + @@ -1050,7 +1062,7 @@ - + @@ -1063,7 +1075,7 @@ - + @@ -1074,7 +1086,7 @@ - + @@ -1085,7 +1097,7 @@ - + @@ -1098,7 +1110,7 @@ - + @@ -1113,7 +1125,7 @@ - + @@ -1128,7 +1140,7 @@ - + @@ -1141,7 +1153,7 @@ - + @@ -1156,7 +1168,7 @@ - + @@ -1167,7 +1179,7 @@ - + @@ -1180,7 +1192,7 @@ - + @@ -1193,7 +1205,7 @@ - + @@ -1208,7 +1220,7 @@ - + @@ -1224,7 +1236,7 @@ - + @@ -1239,7 +1251,7 @@ - + @@ -1256,7 +1268,7 @@ - + @@ -1273,7 +1285,7 @@ - + @@ -1290,7 +1302,7 @@ - + @@ -1305,7 +1317,7 @@ - + @@ -1318,7 +1330,7 @@ - + @@ -1357,7 +1369,7 @@ - + @@ -1386,7 +1398,7 @@ - + @@ -1479,7 +1491,7 @@ - + @@ -1564,6 +1576,7 @@ + @@ -2931,6 +2944,18 @@ + + + + + + + + + + + + @@ -3103,7 +3128,7 @@ - + @@ -3131,7 +3156,7 @@ - + @@ -3150,11 +3175,11 @@ - + - + @@ -3164,7 +3189,7 @@ - + @@ -3174,11 +3199,11 @@ - + - + @@ -3188,7 +3213,7 @@ - + @@ -3198,7 +3223,7 @@ - + @@ -3208,7 +3233,7 @@ - + @@ -3232,7 +3257,7 @@ - + @@ -3250,7 +3275,7 @@ - + @@ -3262,7 +3287,7 @@ - + @@ -3274,7 +3299,7 @@ - + @@ -3282,11 +3307,11 @@ - + - + @@ -3309,7 +3334,7 @@ - + @@ -3335,7 +3360,7 @@ - + @@ -3356,7 +3381,7 @@ - + @@ -3386,7 +3411,7 @@ - + @@ -3400,7 +3425,7 @@ - + @@ -3427,7 +3452,7 @@ - + @@ -3466,7 +3491,7 @@ - + From 16715ceee677e3f375e96d35bc1b721c785cff83 Mon Sep 17 00:00:00 2001 From: DENEL Bertrand Date: Wed, 11 Dec 2024 20:10:59 -0600 Subject: [PATCH 075/104] Fixed doc. --- .../physicsSolvers/fluidFlow/docs/ImmiscibleMultiphaseFlow.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/docs/ImmiscibleMultiphaseFlow.rst b/src/coreComponents/physicsSolvers/fluidFlow/docs/ImmiscibleMultiphaseFlow.rst index 4eeb96c1578..8e6d35adfa2 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/docs/ImmiscibleMultiphaseFlow.rst +++ b/src/coreComponents/physicsSolvers/fluidFlow/docs/ImmiscibleMultiphaseFlow.rst @@ -44,7 +44,7 @@ where :math:`\phi(\mathbf{x})` is the porosity of the medium which is a function :math:`S_\ell(\mathbf{x},t)` is the saturation of the phase :math:`\ell` and similarly for the phase :math:`v`, and :math:`t` is the time. The source/sink terms :math:`q_{\ell}` and :math:`q_{v}` are positive for injection and negative for production. The phase -velocity, :math:`\boldsymbol{u}_\ell`` and :math:`\boldsymbol{u}_v`$`, are defined using +velocity, :math:`\boldsymbol{u}_\ell` and :math:`\boldsymbol{u}_v`, are defined using the multiphase extension of Darcy's law (conservation of momentum) as .. math:: From 9e32fe532966e8013463e7dbc3300b1266bc063f Mon Sep 17 00:00:00 2001 From: DENEL Bertrand Date: Thu, 12 Dec 2024 13:14:28 -0600 Subject: [PATCH 076/104] Added rebaseline infos. --- .integrated_tests.yaml | 2 +- BASELINE_NOTES.md | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.integrated_tests.yaml b/.integrated_tests.yaml index 31ce96119a9..bf17778ea48 100644 --- a/.integrated_tests.yaml +++ b/.integrated_tests.yaml @@ -1,6 +1,6 @@ baselines: bucket: geosx - baseline: integratedTests/baseline_integratedTests-pr3450-9221-37d940c + baseline: integratedTests/baseline_integratedTests-pr3251-9308-16715ce allow_fail: all: '' streak: '' diff --git a/BASELINE_NOTES.md b/BASELINE_NOTES.md index 3b097223255..b682d87860d 100644 --- a/BASELINE_NOTES.md +++ b/BASELINE_NOTES.md @@ -6,6 +6,10 @@ This file is designed to track changes to the integrated test baselines. Any developer who updates the baseline ID in the .integrated_tests.yaml file is expected to create an entry in this file with the pull request number, date, and their justification for rebaselining. These notes should be in reverse-chronological order, and use the following time format: (YYYY-MM-DD). +PR #3251 (2024 12 12) +===================== +Added tests for the newly introduced immiscible fluild solver + PR #3450 (2024-12-08) ===================== Added test for explicit runge kutta sprinslider. From 33950730985a1cc298ee02097b854567c3419763 Mon Sep 17 00:00:00 2001 From: DENEL Bertrand Date: Tue, 17 Dec 2024 16:33:04 -0600 Subject: [PATCH 077/104] Added back HYPRE_BoomerAMGSetAggNumLevels. --- src/coreComponents/linearAlgebra/interfaces/hypre/HypreMGR.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/coreComponents/linearAlgebra/interfaces/hypre/HypreMGR.hpp b/src/coreComponents/linearAlgebra/interfaces/hypre/HypreMGR.hpp index 8bacdf8b978..aae4b181579 100644 --- a/src/coreComponents/linearAlgebra/interfaces/hypre/HypreMGR.hpp +++ b/src/coreComponents/linearAlgebra/interfaces/hypre/HypreMGR.hpp @@ -213,6 +213,7 @@ class MGRStrategyBase #if GEOS_USE_HYPRE_DEVICE == GEOS_USE_HYPRE_CUDA || GEOS_USE_HYPRE_DEVICE == GEOS_USE_HYPRE_HIP GEOS_LAI_CHECK_ERROR( HYPRE_BoomerAMGSetAggInterpType( solver.ptr, hypre::getAMGAggressiveInterpolationType( LinearSolverParameters::AMG::AggInterpType::modifiedExtendedE ) ) ); GEOS_LAI_CHECK_ERROR( HYPRE_BoomerAMGSetCoarsenType( solver.ptr, hypre::getAMGCoarseningType( LinearSolverParameters::AMG::CoarseningType::PMIS ) ) ); + GEOS_LAI_CHECK_ERROR( HYPRE_BoomerAMGSetAggNumLevels( solver.ptr, 0 ) ); GEOS_LAI_CHECK_ERROR( HYPRE_BoomerAMGSetRelaxType( solver.ptr, getAMGRelaxationType( LinearSolverParameters::AMG::SmootherType::l1jacobi ) ) ); GEOS_LAI_CHECK_ERROR( HYPRE_BoomerAMGSetNumSweeps( solver.ptr, 2 ) ); GEOS_LAI_CHECK_ERROR( HYPRE_BoomerAMGSetMaxRowSum( solver.ptr, 1.0 ) ); From 84613c53830789ce1fd6ed3ef249755acf38f6d0 Mon Sep 17 00:00:00 2001 From: DENEL Bertrand Date: Tue, 17 Dec 2024 19:22:57 -0600 Subject: [PATCH 078/104] Removed ubuntu config file. --- host-configs/Stanford/ubuntu22.cmake | 44 ---------------------------- 1 file changed, 44 deletions(-) delete mode 100644 host-configs/Stanford/ubuntu22.cmake diff --git a/host-configs/Stanford/ubuntu22.cmake b/host-configs/Stanford/ubuntu22.cmake deleted file mode 100644 index 39bca094e3e..00000000000 --- a/host-configs/Stanford/ubuntu22.cmake +++ /dev/null @@ -1,44 +0,0 @@ -# file: your-platform.cmake - -# detect host and name the configuration file -site_name(HOST_NAME) -set(CONFIG_NAME "ubuntu22" CACHE PATH "") -message("CONFIG_NAME = ${CONFIG_NAME}") - -# set paths to C, C++, and Fortran compilers. Note that while GEOS does not contain any Fortran code, -# some of the third-party libraries do contain Fortran code. Thus a Fortran compiler must be specified. -set(CMAKE_C_COMPILER "/usr/bin/gcc" CACHE PATH "") -set(CMAKE_CXX_COMPILER "/usr/bin/g++" CACHE PATH "") -set(CMAKE_Fortran_COMPILER "/usr/bin/gfortran" CACHE PATH "") -set(ENABLE_FORTRAN OFF CACHE BOOL "" FORCE) - -# enable MPI and set paths to compilers and executable. -# Note that the MPI compilers are wrappers around standard serial compilers. -# Therefore, the MPI compilers must wrap the appropriate serial compilers specified -# in CMAKE_C_COMPILER, CMAKE_CXX_COMPILER, and CMAKE_Fortran_COMPILER. -set(ENABLE_MPI ON CACHE BOOL "") -set(MPI_C_COMPILER "/usr/bin/mpicc" CACHE PATH "") -set(MPI_CXX_COMPILER "/usr/bin/mpicxx" CACHE PATH "") -set(MPI_Fortran_COMPILER "/usr/bin/mpifort" CACHE PATH "") -set(MPIEXEC "/usr/bin/mpirun" CACHE PATH "") - -# define the path to blas and lapack -#set( BLAS_LIBRARIES /home/rpiazza/lib/lapack-3.11.0-linux-x86_64/libblas.so CACHE PATH "" FORCE ) -#set( LAPACK_LIBRARIES /home/rpiazza/lib/lapack-3.11.0-linux-x86_64/liblapack.so CACHE PATH "" FORCE ) - -# disable CUDA and OpenMP -set(ENABLE_CUDA OFF CACHE BOOL "" FORCE) -set(ENABLE_OPENMP OFF CACHE BOOL "" FORCE) - -# enable PVTPackage -set(ENABLE_PVTPackage ON CACHE BOOL "" FORCE) - -# enable tests -set(ENABLE_GTEST_DEATH_TESTS ON CACHE BOOL "" FORCE ) - -# define the path to your compiled installation directory -set(GEOS_TPL_DIR "/home/rpiazza/two-phase/thirdPartyLibs/install-ubuntu22-debug" CACHE PATH "") -#set(GEOSX_TPL_DIR "${GEOSX_TPL_DIR}" CACHE PATH "" FORCE) -# let GEOS define some third party libraries information for you -#include(${CMAKE_CURRENT_LIST_DIR}/tpls.cmake) -include(${CMAKE_CURRENT_LIST_DIR}/../tpls.cmake) From 04764f4c9cfbf8fe9415d70be72e0c9a46fc3f2b Mon Sep 17 00:00:00 2001 From: DENEL Bertrand Date: Tue, 28 Jan 2025 16:18:54 -0600 Subject: [PATCH 079/104] Merged with develop. --- .../fluidFlow/ImmiscibleMultiphaseFlow.hpp | 23 +------------------ 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp index 4d6ccbd8b21..329ecb3db32 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp @@ -23,31 +23,10 @@ #include "physicsSolvers/fluidFlow/FlowSolverBase.hpp" #include "fieldSpecification/FieldSpecificationManager.hpp" #include "physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp" - +#include "physicsSolvers/fluidFlow/CompositionalMultiphaseFVM.hpp" // For GravityDensityScheme namespace geos { -/** - * @brief Options for density treatment in gravity - */ -enum class GravityDensityScheme : integer -{ - ArithmeticAverage, ///< average phase density is computed using simple arithmetic average: - /// rho_ave = 0.5 * (rho_i + rho_j) - PhasePresence, ///< average phase density is computed using checking for phase presence: - /// rho_ave = 0.5 * (rho_i + rho_j) if phase is present in both cells i and j - /// = rho_i if phase is present in only cell i - /// = rho_j if phase is present in only cell j -}; - -/** - * @brief Strings for options for density treatment in gravity - */ -ENUM_STRINGS( GravityDensityScheme, - "ArithmeticAverage", - "PhasePresence" ); - - //START_SPHINX_INCLUDE_00 /** * @class ImmiscibleMultiphaseFlow From 770e4c9bb0ffc92b211aedf9888b697b4617bb6f Mon Sep 17 00:00:00 2001 From: DENEL Bertrand Date: Tue, 28 Jan 2025 17:00:51 -0600 Subject: [PATCH 080/104] Moved TwoPhaseFluid unit test. --- src/coreComponents/constitutive/unitTests/CMakeLists.txt | 3 ++- .../unitTests}/testTwoPhaseFluid.cpp | 0 src/coreComponents/unitTests/constitutiveTests/CMakeLists.txt | 3 +-- 3 files changed, 3 insertions(+), 3 deletions(-) rename src/coreComponents/{unitTests/constitutiveTests => constitutive/unitTests}/testTwoPhaseFluid.cpp (100%) diff --git a/src/coreComponents/constitutive/unitTests/CMakeLists.txt b/src/coreComponents/constitutive/unitTests/CMakeLists.txt index aa095d493c8..d7cdc296795 100644 --- a/src/coreComponents/constitutive/unitTests/CMakeLists.txt +++ b/src/coreComponents/constitutive/unitTests/CMakeLists.txt @@ -18,7 +18,8 @@ set( gtest_geosx_tests testPropertyConversions.cpp testStabilityTest2Comp.cpp testStabilityTest9Comp.cpp - testRachfordRice.cpp ) + testRachfordRice.cpp + testTwoPhaseFluid.cpp ) set( dependencyList gtest blas lapack constitutive ${parallelDeps} ) diff --git a/src/coreComponents/unitTests/constitutiveTests/testTwoPhaseFluid.cpp b/src/coreComponents/constitutive/unitTests/testTwoPhaseFluid.cpp similarity index 100% rename from src/coreComponents/unitTests/constitutiveTests/testTwoPhaseFluid.cpp rename to src/coreComponents/constitutive/unitTests/testTwoPhaseFluid.cpp diff --git a/src/coreComponents/unitTests/constitutiveTests/CMakeLists.txt b/src/coreComponents/unitTests/constitutiveTests/CMakeLists.txt index 6f9608fadf6..0d13b0ef63a 100644 --- a/src/coreComponents/unitTests/constitutiveTests/CMakeLists.txt +++ b/src/coreComponents/unitTests/constitutiveTests/CMakeLists.txt @@ -9,8 +9,7 @@ set( gtest_geosx_tests testMultiFluidDeadOil.cpp testMultiFluidLiveOil.cpp testRelPerm.cpp - testRelPermHysteresis.cpp - testTwoPhaseFluid.cpp ) + testRelPermHysteresis.cpp ) set( gtest_triaxial_xmls testTriaxial_druckerPragerExtended.xml From 254d4df4a0fca165405e35aed8a6f3478bff3082 Mon Sep 17 00:00:00 2001 From: DENEL Bertrand Date: Tue, 28 Jan 2025 17:11:59 -0600 Subject: [PATCH 081/104] Removed HYPRE_BoomerAMGSetAggNumLevels. Hypre setup to be addressed in a seperate PR. --- src/coreComponents/linearAlgebra/interfaces/hypre/HypreMGR.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/coreComponents/linearAlgebra/interfaces/hypre/HypreMGR.hpp b/src/coreComponents/linearAlgebra/interfaces/hypre/HypreMGR.hpp index d9b76cf096d..c45bc4fe873 100644 --- a/src/coreComponents/linearAlgebra/interfaces/hypre/HypreMGR.hpp +++ b/src/coreComponents/linearAlgebra/interfaces/hypre/HypreMGR.hpp @@ -213,7 +213,6 @@ class MGRStrategyBase #if GEOS_USE_HYPRE_DEVICE == GEOS_USE_HYPRE_CUDA || GEOS_USE_HYPRE_DEVICE == GEOS_USE_HYPRE_HIP GEOS_LAI_CHECK_ERROR( HYPRE_BoomerAMGSetAggInterpType( solver.ptr, hypre::getAMGAggressiveInterpolationType( LinearSolverParameters::AMG::AggInterpType::modifiedExtendedE ) ) ); GEOS_LAI_CHECK_ERROR( HYPRE_BoomerAMGSetCoarsenType( solver.ptr, hypre::getAMGCoarseningType( LinearSolverParameters::AMG::CoarseningType::PMIS ) ) ); - GEOS_LAI_CHECK_ERROR( HYPRE_BoomerAMGSetAggNumLevels( solver.ptr, 0 ) ); GEOS_LAI_CHECK_ERROR( HYPRE_BoomerAMGSetRelaxType( solver.ptr, getAMGRelaxationType( LinearSolverParameters::AMG::SmootherType::l1jacobi ) ) ); GEOS_LAI_CHECK_ERROR( HYPRE_BoomerAMGSetNumSweeps( solver.ptr, 2 ) ); GEOS_LAI_CHECK_ERROR( HYPRE_BoomerAMGSetMaxRowSum( solver.ptr, 1.0 ) ); From bb6b0afbcfbceb4d5c2a7c4d642011e3e33bf5cb Mon Sep 17 00:00:00 2001 From: DENEL Bertrand Date: Tue, 28 Jan 2025 17:53:08 -0600 Subject: [PATCH 082/104] Removed commented sections. --- .../fluid/twophasefluid/TwoPhaseFluid.cpp | 7 ----- .../fluidFlow/ImmiscibleMultiphaseFlow.cpp | 29 ++----------------- 2 files changed, 2 insertions(+), 34 deletions(-) diff --git a/src/coreComponents/constitutive/fluid/twophasefluid/TwoPhaseFluid.cpp b/src/coreComponents/constitutive/fluid/twophasefluid/TwoPhaseFluid.cpp index 3b119e393d8..ad6379ea129 100644 --- a/src/coreComponents/constitutive/fluid/twophasefluid/TwoPhaseFluid.cpp +++ b/src/coreComponents/constitutive/fluid/twophasefluid/TwoPhaseFluid.cpp @@ -105,13 +105,6 @@ void TwoPhaseFluid::postInputInitialization() m_tableFiles.empty() ? readInputDataFromTableFunctions() : readInputDataFromFileTableFunctions(); checkTableConsistency(); - /* TODO - // call to correctly set member array tertiary sizes on the 'main' material object - resizeFields( 0, 0 ); - - // set labels on array wrappers for plottable fields - setLabels(); - */ } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index 8a43a9218ce..87969dc05aa 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -100,9 +100,6 @@ void ImmiscibleMultiphaseFlow::registerDataOnMesh( Group & meshBodies ) { FlowSolverBase::registerDataOnMesh( meshBodies ); - // DomainPartition const & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" ); - // ConstitutiveManager const & cm = domain.getConstitutiveManager(); - // 0. Find a "reference" fluid model name (at this point, models are already attached to subregions) forDiscretizationOnMeshTargets( meshBodies, [&]( string const &, MeshLevel & mesh, @@ -174,10 +171,6 @@ void ImmiscibleMultiphaseFlow::registerDataOnMesh( Group & meshBodies ) } ); - // FaceManager & faceManager = mesh.getFaceManager(); - // { - // faceManager.registerField< totalMassFlux >( getName() ); - // } } ); } @@ -213,16 +206,10 @@ void ImmiscibleMultiphaseFlow::initializePreSubGroups() FlowSolverBase::initializePreSubGroups(); DomainPartition & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" ); - // ConstitutiveManager const & cm = domain.getConstitutiveManager(); - - // // 1. Validate various models against each other (must have same phases and components) - // validateConstitutiveModels( domain ); - // 2. Set the value of temperature forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, MeshLevel & mesh, arrayView1d< string const > const & regionNames ) - { mesh.getElemManager().forElementSubRegions( regionNames, [&]( localIndex const, @@ -253,7 +240,6 @@ void ImmiscibleMultiphaseFlow::updateFluidModel( ObjectManagerBase & dataGroup ) } - void ImmiscibleMultiphaseFlow::updateRelPermModel( ObjectManagerBase & dataGroup ) const { GEOS_MARK_FUNCTION; @@ -683,18 +669,11 @@ void ImmiscibleMultiphaseFlow::applyBoundaryConditions( real64 const time_n, // apply pressure boundary conditions. applyDirichletBC( time_n, dt, dofManager, domain, localMatrix.toViewConstSizes(), localRhs.toView() ); -// apply flux boundary conditions + // apply flux boundary conditions applySourceFluxBC( time_n, dt, dofManager, domain, localMatrix.toViewConstSizes(), localRhs.toView() ); - - // for( localIndex row = 0; row < localMatrix.toViewConstSizes().numRows(); ++row ) - // { - // std::cout << "row " << row << std::endl; - // std::cout << "\tcolumns: " << localMatrix.toViewConstSizes().getColumns( row ) << std::endl; - // std::cout << "\tvalues: " << localMatrix.toViewConstSizes().getEntries( row ) << std::endl; - // } - } + namespace { char const bcLogMessage[] = @@ -1065,10 +1044,8 @@ void ImmiscibleMultiphaseFlow::applySystemSolution( DofManager const & dofManage GEOS_UNUSED_VAR( dt ); DofManager::CompMask pressureMask( m_numDofPerCell, 0, 1 ); - //DofManager::CompMask PhaseMask( m_numDofPerCell, 1, m_numPhases ); // 1. apply the pressure update - dofManager.addVectorToField( localSolution, viewKeyStruct::elemDofFieldString(), fields::flow::pressure::key(), @@ -1076,7 +1053,6 @@ void ImmiscibleMultiphaseFlow::applySystemSolution( DofManager const & dofManage pressureMask ); // 2. apply the phaseVolumeFraction update - dofManager.addVectorToField( localSolution, viewKeyStruct::elemDofFieldString(), fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key(), @@ -1095,7 +1071,6 @@ void ImmiscibleMultiphaseFlow::applySystemSolution( DofManager const & dofManage CommunicationTools::getInstance().synchronizeFields( fieldsToBeSync, mesh, domain.getNeighbors(), true ); } ); - } From 23c52401b6bb88fe19f132eb2e94b670dfb76ed3 Mon Sep 17 00:00:00 2001 From: Ammara-14 Date: Fri, 31 Jan 2025 16:09:51 -0800 Subject: [PATCH 083/104] Additing validateDirichletBC and SourceFluxStats wrapper --- .../fluidFlow/ImmiscibleMultiphaseFlow.cpp | 148 ++++++++++++++++-- .../fluidFlow/ImmiscibleMultiphaseFlow.hpp | 8 + 2 files changed, 139 insertions(+), 17 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index 87969dc05aa..13962c2d973 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -30,7 +30,9 @@ #include "constitutive/capillaryPressure/capillaryPressureSelector.hpp" #include "constitutive/relativePermeability/RelativePermeabilitySelector.hpp" +#include "fieldSpecification/EquilibriumInitialCondition.hpp" #include "fieldSpecification/SourceFluxBoundaryCondition.hpp" +#include "physicsSolvers/fluidFlow/SourceFluxStatistics.hpp" #include "constitutive/ConstitutivePassThru.hpp" #include "constitutive/fluid/twophasefluid/TwoPhaseFluid.hpp" @@ -677,13 +679,126 @@ void ImmiscibleMultiphaseFlow::applyBoundaryConditions( real64 const time_n, namespace { char const bcLogMessage[] = - "CompositionalMultiphaseBase {}: at time {}s, " + "ImmiscibleMultiphaseFlow {}: at time {}s, " "the <{}> boundary condition '{}' is applied to the element set '{}' in subRegion '{}'. " "\nThe scale of this boundary condition is {} and multiplies the value of the provided function (if any). " "\nThe total number of target elements (including ghost elements) is {}. " "\nNote that if this number is equal to zero for all subRegions, the boundary condition will not be applied on this element set."; } +bool ImmiscibleMultiphaseFlow::validateDirichletBC( DomainPartition & domain, + real64 const time ) const +{ + constexpr integer MAX_NP = 2; + FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); + + bool bcConsistent = true; + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + arrayView1d< string const > const & ) + { + // map: regionName -> subRegionName -> setName -> numPhases to check pressure/phase are present consistent + map< string, map< string, map< string, ComponentMask< MAX_NP > > > > bcPresCompStatusMap; + + // 1. Check pressure Dirichlet BCs + fsManager.apply< ElementSubRegionBase >( time, + mesh, + fields::flow::pressure::key(), + [&]( FieldSpecificationBase const &, + string const & setName, + SortedArrayView< localIndex const > const &, + ElementSubRegionBase & subRegion, + string const & ) + { + // Check whether pressure has already been applied to this set + string const & subRegionName = subRegion.getName(); + string const & regionName = subRegion.getParent().getParent().getName(); + + auto & subRegionSetMap = bcPresCompStatusMap[regionName][subRegionName]; + if( subRegionSetMap.count( setName ) > 0 ) + { + bcConsistent = false; + GEOS_WARNING( BCMessage::pressureConflict( regionName, subRegionName, setName, + fields::flow::pressure::key() ) ); + } + subRegionSetMap[setName].setNumComp( m_numPhases ); + } ); + // 2. Check saturation Dirichlet BCs + fsManager.apply< ElementSubRegionBase >( time, + mesh, + fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key(), + [&] ( FieldSpecificationBase const & fs, + string const & setName, + SortedArrayView< localIndex const > const &, + ElementSubRegionBase & subRegion, + string const & ) + { + string const & subRegionName = subRegion.getName( ); + string const & regionName = subRegion.getParent().getParent().getName(); + integer const comp = fs.getComponent(); + + auto & subRegionSetMap = bcPresCompStatusMap[regionName][subRegionName]; + if( subRegionSetMap.count( setName ) == 0 ) + { + bcConsistent = false; + GEOS_WARNING( BCMessage::missingPressure( regionName, subRegionName, setName, + fields::flow::pressure::key() ) ); + } + if( comp < 0 || comp >= m_numPhases ) + { + bcConsistent = false; + GEOS_WARNING( BCMessage::invalidComponentIndex( comp, fs.getName(), + fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key() ) ); + return; // can't check next part with invalid component id + } + + ComponentMask< MAX_NP > & compMask = subRegionSetMap[setName]; + if( compMask[comp] ) + { + bcConsistent = false; + fsManager.forSubGroups< EquilibriumInitialCondition >( [&] ( EquilibriumInitialCondition const & bc ) + { + arrayView1d< string const > componentNames = bc.getComponentNames(); + GEOS_WARNING( BCMessage::conflictingComposition( comp, componentNames[comp], + regionName, subRegionName, setName, + fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key() ) ); + } ); + } + compMask.set( comp ); + } ); + + // 3.2 Check consistency between composition BC applied to sets + // Note: for a temperature-only boundary condition, this loop does not do anything + for( auto const & regionEntry : bcPresCompStatusMap ) + { + for( auto const & subRegionEntry : regionEntry.second ) + { + for( auto const & setEntry : subRegionEntry.second ) + { + ComponentMask< MAX_NP > const & compMask = setEntry.second; + + fsManager.forSubGroups< EquilibriumInitialCondition >( [&] ( EquilibriumInitialCondition const & fs ) + { + arrayView1d< string const > componentNames = fs.getComponentNames(); + for( int ic = 0; ic < componentNames.size(); ic++ ) + { + if( !compMask[ic] ) + { + bcConsistent = false; + GEOS_WARNING( BCMessage::notAppliedOnRegion( ic, componentNames[ic], + regionEntry.first, subRegionEntry.first, setEntry.first, + fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key() ) ); + } + } + } ); + } + } + } + } ); + + return bcConsistent; +} void ImmiscibleMultiphaseFlow::applyDirichletBC( real64 const time_n, real64 const dt, @@ -694,12 +809,12 @@ void ImmiscibleMultiphaseFlow::applyDirichletBC( real64 const time_n, { GEOS_MARK_FUNCTION; - // // Only validate BC at the beginning of Newton loop - // if( m_nonlinearSolverParameters.m_numNewtonIterations == 0 ) - // { - // bool const bcConsistent = validateDirichletBC( domain, time_n + dt ); - // GEOS_ERROR_IF( !bcConsistent, GEOS_FMT( "CompositionalMultiphaseBase {}: inconsistent boundary conditions", getDataContext() ) ); - // } + // Only validate BC at the beginning of Newton loop + if( m_nonlinearSolverParameters.m_numNewtonIterations == 0 ) + { + bool const bcConsistent = validateDirichletBC( domain, time_n + dt ); + GEOS_ERROR_IF( !bcConsistent, GEOS_FMT( "ImmiscibleMultiphaseFlow {}: inconsistent boundary conditions", getDataContext() ) ); + } FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); @@ -719,7 +834,7 @@ void ImmiscibleMultiphaseFlow::applyDirichletBC( real64 const time_n, globalIndex const rankOffset = dofManager.rankOffset(); string const dofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); - // 3. Call constitutive update, back-calculate target global component densities and apply to the system + // 3. Call constitutive update fsManager.apply< ElementSubRegionBase >( time_n + dt, mesh, fields::flow::pressure::key(), @@ -939,19 +1054,18 @@ void ImmiscibleMultiphaseFlow::applySourceFluxBC( real64 const time, } } ); - // SourceFluxStatsAggregator::forAllFluxStatWrappers( subRegion, fs.getName(), - // [&]( SourceFluxStatsAggregator::WrappedStats & wrapper ) - // { - // // set the new sub-region statistics for this timestep - // array1d< real64 > massProdArr{ m_numPhases }; - // massProdArr[fluidPhaseId] = massProd.get(); - // wrapper.gatherTimeStepStats( time, dt, massProdArr.toViewConst(), targetSet.size() ); - // } ); + SourceFluxStatsAggregator::forAllFluxStatWrappers( subRegion, fs.getName(), + [&]( SourceFluxStatsAggregator::WrappedStats & wrapper ) + { + // set the new sub-region statistics for this timestep + array1d< real64 > massProdArr{ m_numPhases }; + massProdArr[fluidPhaseId] = massProd.get(); + wrapper.gatherTimeStepStats( time, dt, massProdArr.toViewConst(), targetSet.size() ); + } ); } ); } ); } - real64 ImmiscibleMultiphaseFlow::calculateResidualNorm( real64 const & GEOS_UNUSED_PARAM( time_n ), real64 const & GEOS_UNUSED_PARAM( dt ), DomainPartition const & domain, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp index 329ecb3db32..8d5230aa557 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp @@ -305,6 +305,14 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase private: + /** + * @brief Utility function to validate the consistency of Dirichlet BC input + * @param[in] domain the domain partition + * @param[in] time the time at the end of the time step (time_n + dt) + */ + bool validateDirichletBC( DomainPartition & domain, + real64 const time ) const; + virtual void setConstitutiveNames( ElementSubRegionBase & subRegion ) const override; }; From 510ed8c4340a280d557493996fe2375278039d31 Mon Sep 17 00:00:00 2001 From: Pavel Tomin Date: Wed, 26 Feb 2025 09:54:17 -0600 Subject: [PATCH 084/104] code style --- .../physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index 13962c2d973..c8ff3335f22 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -687,7 +687,7 @@ char const bcLogMessage[] = } bool ImmiscibleMultiphaseFlow::validateDirichletBC( DomainPartition & domain, - real64 const time ) const + real64 const time ) const { constexpr integer MAX_NP = 2; FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); @@ -723,9 +723,9 @@ bool ImmiscibleMultiphaseFlow::validateDirichletBC( DomainPartition & domain, fields::flow::pressure::key() ) ); } subRegionSetMap[setName].setNumComp( m_numPhases ); - } ); + } ); // 2. Check saturation Dirichlet BCs - fsManager.apply< ElementSubRegionBase >( time, + fsManager.apply< ElementSubRegionBase >( time, mesh, fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key(), [&] ( FieldSpecificationBase const & fs, @@ -795,7 +795,7 @@ bool ImmiscibleMultiphaseFlow::validateDirichletBC( DomainPartition & domain, } } } - } ); + } ); return bcConsistent; } From 66a166598ba085fcbf583e757bbaad17249faed0 Mon Sep 17 00:00:00 2001 From: Pavel Tomin Date: Wed, 26 Feb 2025 11:39:08 -0600 Subject: [PATCH 085/104] build fix --- .../fluid/twophasefluid/TwoPhaseFluid.hpp | 4 +- .../fluidFlow/ImmiscibleMultiphaseFlow.cpp | 40 +++++++++---------- .../fluidFlow/ImmiscibleMultiphaseFlow.hpp | 2 +- .../testImmiscibleMultiphaseFlow.cpp | 2 +- 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/coreComponents/constitutive/fluid/twophasefluid/TwoPhaseFluid.hpp b/src/coreComponents/constitutive/fluid/twophasefluid/TwoPhaseFluid.hpp index d1da2681a25..6c236a433a0 100644 --- a/src/coreComponents/constitutive/fluid/twophasefluid/TwoPhaseFluid.hpp +++ b/src/coreComponents/constitutive/fluid/twophasefluid/TwoPhaseFluid.hpp @@ -74,7 +74,7 @@ class TwoPhaseFluid : public ConstitutiveBase * @brief Getter for the fluid phase names * @return an array storing the phase names */ - arrayView1d< string const > phaseNames() const { return m_phaseNames; } + string_array const & phaseNames() const { return m_phaseNames; } struct viewKeyStruct : ConstitutiveBase::viewKeyStruct { @@ -197,7 +197,7 @@ class TwoPhaseFluid : public ConstitutiveBase }; //class KernelWrapper - array1d< string > m_phaseNames; + string_array m_phaseNames; path_array m_tableFiles; diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index c8ff3335f22..a8019424283 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -105,7 +105,7 @@ void ImmiscibleMultiphaseFlow::registerDataOnMesh( Group & meshBodies ) // 0. Find a "reference" fluid model name (at this point, models are already attached to subregions) forDiscretizationOnMeshTargets( meshBodies, [&]( string const &, MeshLevel & mesh, - arrayView1d< string const > const & regionNames ) + string_array const & regionNames ) { mesh.getElemManager().forElementSubRegions( regionNames, [&]( localIndex const, @@ -125,7 +125,7 @@ void ImmiscibleMultiphaseFlow::registerDataOnMesh( Group & meshBodies ) // 2. Register and resize all fields as necessary forDiscretizationOnMeshTargets( meshBodies, [&]( string const &, MeshLevel & mesh, - arrayView1d< string const > const & regionNames ) + string_array const & regionNames ) { mesh.getElemManager().forElementSubRegions( regionNames, [&]( localIndex const, @@ -211,7 +211,7 @@ void ImmiscibleMultiphaseFlow::initializePreSubGroups() forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, MeshLevel & mesh, - arrayView1d< string const > const & regionNames ) + string_array const & regionNames ) { mesh.getElemManager().forElementSubRegions( regionNames, [&]( localIndex const, @@ -357,7 +357,7 @@ void ImmiscibleMultiphaseFlow::updatePhaseMobility( ObjectManagerBase & dataGrou } void ImmiscibleMultiphaseFlow::initializeFluidState( MeshLevel & mesh, - arrayView1d< string const > const & regionNames ) + string_array const & regionNames ) { GEOS_MARK_FUNCTION; @@ -481,7 +481,7 @@ void ImmiscibleMultiphaseFlow::initializePostInitialConditionsPreSubGroups() forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, MeshLevel & mesh, - arrayView1d< string const > const & regionNames ) + string_array const & regionNames ) { FieldIdentifiers fieldsToBeSync; fieldsToBeSync.addElementFields( { fields::flow::pressure::key(), @@ -502,7 +502,7 @@ ImmiscibleMultiphaseFlow::implicitStepSetup( real64 const & GEOS_UNUSED_PARAM( t { forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, MeshLevel & mesh, - arrayView1d< string const > const & regionNames ) + string_array const & regionNames ) { mesh.getElemManager().forElementSubRegions< CellElementSubRegion, SurfaceElementSubRegion >( regionNames, @@ -570,7 +570,7 @@ void ImmiscibleMultiphaseFlow::assembleAccumulationTerm( DomainPartition & domai forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, MeshLevel const & mesh, - arrayView1d< string const > const & regionNames ) + string_array const & regionNames ) { mesh.getElemManager().forElementSubRegions( regionNames, [&]( localIndex const, @@ -615,7 +615,7 @@ void ImmiscibleMultiphaseFlow::assembleFluxTerms( real64 const dt, forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, MeshLevel const & mesh, - arrayView1d< string const > const & ) + string_array const & ) { fluxApprox.forAllStencils( mesh, [&]( auto & stencil ) { @@ -696,7 +696,7 @@ bool ImmiscibleMultiphaseFlow::validateDirichletBC( DomainPartition & domain, forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, MeshLevel & mesh, - arrayView1d< string const > const & ) + string_array const & ) { // map: regionName -> subRegionName -> setName -> numPhases to check pressure/phase are present consistent map< string, map< string, map< string, ComponentMask< MAX_NP > > > > bcPresCompStatusMap; @@ -759,7 +759,7 @@ bool ImmiscibleMultiphaseFlow::validateDirichletBC( DomainPartition & domain, bcConsistent = false; fsManager.forSubGroups< EquilibriumInitialCondition >( [&] ( EquilibriumInitialCondition const & bc ) { - arrayView1d< string const > componentNames = bc.getComponentNames(); + string_array const & componentNames = bc.getComponentNames(); GEOS_WARNING( BCMessage::conflictingComposition( comp, componentNames[comp], regionName, subRegionName, setName, fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key() ) ); @@ -780,8 +780,8 @@ bool ImmiscibleMultiphaseFlow::validateDirichletBC( DomainPartition & domain, fsManager.forSubGroups< EquilibriumInitialCondition >( [&] ( EquilibriumInitialCondition const & fs ) { - arrayView1d< string const > componentNames = fs.getComponentNames(); - for( int ic = 0; ic < componentNames.size(); ic++ ) + string_array const & componentNames = fs.getComponentNames(); + for( size_t ic = 0; ic < componentNames.size(); ic++ ) { if( !compMask[ic] ) { @@ -820,7 +820,7 @@ void ImmiscibleMultiphaseFlow::applyDirichletBC( real64 const time_n, forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, MeshLevel & mesh, - arrayView1d< string const > const & ) + string_array const & ) { // 1. Apply pressure Dirichlet BCs, store in a separate field @@ -945,7 +945,7 @@ void ImmiscibleMultiphaseFlow::applySourceFluxBC( real64 const time, forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, MeshLevel & mesh, - arrayView1d< string const > const & ) + string_array const & ) { fsManager.apply< ElementSubRegionBase, @@ -1085,7 +1085,7 @@ real64 ImmiscibleMultiphaseFlow::calculateResidualNorm( real64 const & GEOS_UNUS forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, MeshLevel const & mesh, - arrayView1d< string const > const & regionNames ) + string_array const & regionNames ) { mesh.getElemManager().forElementSubRegions( regionNames, [&]( localIndex const, @@ -1176,7 +1176,7 @@ void ImmiscibleMultiphaseFlow::applySystemSolution( DofManager const & dofManage // 3. synchronize forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, MeshLevel & mesh, - arrayView1d< string const > const & regionNames ) + string_array const & regionNames ) { std::vector< string > fields{ fields::flow::pressure::key(), fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key() }; @@ -1207,7 +1207,7 @@ void ImmiscibleMultiphaseFlow::resetStateToBeginningOfStep( DomainPartition & do forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, MeshLevel & mesh, - arrayView1d< string const > const & regionNames ) + string_array const & regionNames ) { mesh.getElemManager().forElementSubRegions< CellElementSubRegion, SurfaceElementSubRegion >( regionNames, @@ -1263,7 +1263,7 @@ void ImmiscibleMultiphaseFlow::implicitStepComplete( real64 const & time, forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, MeshLevel & mesh, - arrayView1d< string const > const & regionNames ) + string_array const & regionNames ) { mesh.getElemManager().forElementSubRegions( regionNames, [&]( localIndex const, @@ -1333,7 +1333,7 @@ void ImmiscibleMultiphaseFlow::updateState( DomainPartition & domain ) forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, MeshLevel & mesh, - arrayView1d< string const > const & regionNames ) + string_array const & regionNames ) { mesh.getElemManager().forElementSubRegions< CellElementSubRegion, SurfaceElementSubRegion >( regionNames, [&]( localIndex const, @@ -1364,7 +1364,7 @@ real64 ImmiscibleMultiphaseFlow::setNextDtBasedOnStateChange( real64 const & cur forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, MeshLevel & mesh, - arrayView1d< string const > const & regionNames ) + string_array const & regionNames ) { mesh.getElemManager().forElementSubRegions( regionNames, [&]( localIndex const, diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp index 8d5230aa557..5d876f9cfd7 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp @@ -206,7 +206,7 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase virtual void initializePostInitialConditionsPreSubGroups() override; - virtual void initializeFluidState( MeshLevel & mesh, arrayView1d< string const > const & regionNames ) override; + virtual void initializeFluidState( MeshLevel & mesh, string_array const & regionNames ) override; /** diff --git a/src/coreComponents/unitTests/fluidFlowTests/testImmiscibleMultiphaseFlow.cpp b/src/coreComponents/unitTests/fluidFlowTests/testImmiscibleMultiphaseFlow.cpp index d86be36ea17..175b5197e13 100644 --- a/src/coreComponents/unitTests/fluidFlowTests/testImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/unitTests/fluidFlowTests/testImmiscibleMultiphaseFlow.cpp @@ -256,7 +256,7 @@ void fillCellCenteredNumericalJacobian( ImmiscibleMultiphaseFlow & solver, solver.forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, MeshLevel & mesh, - arrayView1d< string const > const & regionNames ) + string_array const & regionNames ) { mesh.getElemManager().forElementSubRegions( regionNames, [&]( localIndex const, From ab3cd3b32cfd1657452708bc1b364b768a2c9a97 Mon Sep 17 00:00:00 2001 From: Pavel Tomin Date: Wed, 26 Feb 2025 11:49:54 -0600 Subject: [PATCH 086/104] test build fix --- .../constitutive/unitTests/testTwoPhaseFluid.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/coreComponents/constitutive/unitTests/testTwoPhaseFluid.cpp b/src/coreComponents/constitutive/unitTests/testTwoPhaseFluid.cpp index b456b3468bb..39cc87395a6 100644 --- a/src/coreComponents/constitutive/unitTests/testTwoPhaseFluid.cpp +++ b/src/coreComponents/constitutive/unitTests/testTwoPhaseFluid.cpp @@ -207,13 +207,16 @@ TwoPhaseFluid * TwoPhaseFluidTest< true >::makeTwoPhaseFluid( string const & nam TwoPhaseFluid & fluid = parent.registerGroup< TwoPhaseFluid >( name ); string_array & phaseNames = fluid.getReference< string_array >( TwoPhaseFluid::viewKeyStruct::phaseNamesString() ); - fill< 2 >( phaseNames, {"oil", "water"} ); + phaseNames[0] = "oil"; + phaseNames[1] = "water"; string_array & densityTableNames = fluid.getReference< string_array >( TwoPhaseFluid::viewKeyStruct::densityTableNamesString() ); - fill< 2 >( densityTableNames, {"densityTablePhase0", "densityTablePhase1"} ); + densityTableNames[0] = "densityTablePhase0"; + densityTableNames[1] = "densityTablePhase1"; string_array & viscosityTableNames = fluid.getReference< string_array >( TwoPhaseFluid::viewKeyStruct::viscosityTableNamesString() ); - fill< 2 >( viscosityTableNames, {"viscosityTablePhase0", "viscosityTablePhase1"} ); + viscosityTableNames[0] = "viscosityTablePhase0"; + viscosityTableNames[1] = "viscosityTablePhase1"; fluid.postInputInitializationRecursive(); return &fluid; From 79b9ff568ac75f8fd4967fa2d5081f7733d98241 Mon Sep 17 00:00:00 2001 From: Pavel Tomin Date: Wed, 26 Feb 2025 13:29:42 -0600 Subject: [PATCH 087/104] test fix again --- .../fluid/twophasefluid/TwoPhaseFluid.hpp | 4 ++-- .../constitutive/unitTests/testTwoPhaseFluid.cpp | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/coreComponents/constitutive/fluid/twophasefluid/TwoPhaseFluid.hpp b/src/coreComponents/constitutive/fluid/twophasefluid/TwoPhaseFluid.hpp index 6c236a433a0..18cdc357bb0 100644 --- a/src/coreComponents/constitutive/fluid/twophasefluid/TwoPhaseFluid.hpp +++ b/src/coreComponents/constitutive/fluid/twophasefluid/TwoPhaseFluid.hpp @@ -203,10 +203,10 @@ class TwoPhaseFluid : public ConstitutiveBase path_array m_tableFiles; /// Names of the density tables (one per phase) - array1d< string > m_densityTableNames; + string_array m_densityTableNames; /// Names of the viscosity tables (one per phase) - array1d< string > m_viscosityTableNames; + string_array m_viscosityTableNames; PhaseProp m_phaseDensity; PhaseProp m_phaseViscosity; diff --git a/src/coreComponents/constitutive/unitTests/testTwoPhaseFluid.cpp b/src/coreComponents/constitutive/unitTests/testTwoPhaseFluid.cpp index 39cc87395a6..207668e29cb 100644 --- a/src/coreComponents/constitutive/unitTests/testTwoPhaseFluid.cpp +++ b/src/coreComponents/constitutive/unitTests/testTwoPhaseFluid.cpp @@ -207,16 +207,16 @@ TwoPhaseFluid * TwoPhaseFluidTest< true >::makeTwoPhaseFluid( string const & nam TwoPhaseFluid & fluid = parent.registerGroup< TwoPhaseFluid >( name ); string_array & phaseNames = fluid.getReference< string_array >( TwoPhaseFluid::viewKeyStruct::phaseNamesString() ); - phaseNames[0] = "oil"; - phaseNames[1] = "water"; + phaseNames.emplace_back( "oil" ); + phaseNames.emplace_back( "water" ); string_array & densityTableNames = fluid.getReference< string_array >( TwoPhaseFluid::viewKeyStruct::densityTableNamesString() ); - densityTableNames[0] = "densityTablePhase0"; - densityTableNames[1] = "densityTablePhase1"; + densityTableNames.emplace_back( "densityTablePhase0" ); + densityTableNames.emplace_back( "densityTablePhase1" ); string_array & viscosityTableNames = fluid.getReference< string_array >( TwoPhaseFluid::viewKeyStruct::viscosityTableNamesString() ); - viscosityTableNames[0] = "viscosityTablePhase0"; - viscosityTableNames[1] = "viscosityTablePhase1"; + viscosityTableNames.emplace_back( "viscosityTablePhase0" ); + viscosityTableNames.emplace_back( "viscosityTablePhase1" ); fluid.postInputInitializationRecursive(); return &fluid; From cfbddf83d1d7778b0778fae498dadf5376b59deb Mon Sep 17 00:00:00 2001 From: Ammara-14 Date: Thu, 27 Feb 2025 12:46:15 -0800 Subject: [PATCH 088/104] Initial implementation - trying to pass the capillary pressure model to the compute flux --- .../fluidFlow/ImmiscibleMultiphaseFlow.cpp | 22 ++++- .../ImmiscibleMultiphaseKernels.hpp | 89 ++++++++++++++++++- 2 files changed, 108 insertions(+), 3 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index 13962c2d973..08472eb47e6 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -613,18 +613,37 @@ void ImmiscibleMultiphaseFlow::assembleFluxTerms( real64 const dt, string const & dofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, MeshLevel const & mesh, - arrayView1d< string const > const & ) + arrayView1d< string const > const & regionNames ) { + + + fluxApprox.forAllStencils( mesh, [&]( auto & stencil ) { + mesh.getElemManager().forElementSubRegions( regionNames, + [&]( localIndex const, + ElementSubRegionBase const & subRegion ) + { + // if( m_hasCapPressure ) + // { + string const & cappresName = subRegion.getReference< string >( viewKeyStruct::capPressureNamesString() ); + CapillaryPressureBase const & capPressure = getConstitutiveModel< CapillaryPressureBase >( subRegion, cappresName ); + // constitutive::constitutiveUpdatePassThru( capPressure, [&] ( auto & castedCapPres ) + // { + // typename TYPEOFREF( castedCapPres ) ::KernelWrapper capPresWrapper = castedCapPres.createKernelWrapper(); + // } ); + // } + typename TYPEOFREF( stencil ) ::KernelWrapper stencilWrapper = stencil.createKernelWrapper(); immiscibleMultiphaseKernels:: FaceBasedAssemblyKernelFactory::createAndLaunch< parallelDevicePolicy<> >( m_numPhases, dofManager.rankOffset(), dofKey, m_hasCapPressure, + capPressure, m_useTotalMassEquation, m_gravityDensityScheme == GravityDensityScheme::PhasePresence, getName(), @@ -633,6 +652,7 @@ void ImmiscibleMultiphaseFlow::assembleFluxTerms( real64 const dt, dt, localMatrix.toViewConstSizes(), localRhs.toView() ); + } ); } ); } ); } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp index 0f2e4045be4..160f806d48d 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp @@ -17,8 +17,10 @@ * @file ImmiscibleMultiphaseKernels.hpp */ + #ifndef GEOS_PHYSICSSOLVERS_FLUIDFLOW_MULTIPHASEKERNELS_HPP #define GEOS_PHYSICSSOLVERS_FLUIDFLOW_MULTIPHASEKERNELS_HPP +#define Pe_max 5000000.0 #include "codingUtilities/Utilities.hpp" #include "common/DataLayouts.hpp" @@ -26,6 +28,7 @@ #include "common/GEOS_RAJA_Interface.hpp" #include "constitutive/fluid/twophasefluid/TwoPhaseFluid.hpp" #include "constitutive/solid/CoupledSolidBase.hpp" +#include "constitutive/ConstitutivePassThru.hpp" #include "constitutive/fluid/twophasefluid/TwoPhaseFluidFields.hpp" #include "constitutive/capillaryPressure/CapillaryPressureFields.hpp" #include "constitutive/capillaryPressure/CapillaryPressureBase.hpp" @@ -50,6 +53,19 @@ namespace geos { namespace immiscibleMultiphaseKernels { + + template< typename VIEWTYPE > +real64 computePCalpha ( real64 S ) { + real64 Pe = Pe_max; + return (Pe * (1.0 - S)); +} + +template< typename VIEWTYPE > +real64 computePCalphaInv ( real64 Pc ) { + real64 Pe = Pe_max; + return (1.0 - Pc / Pe); +} + using namespace constitutive; @@ -406,6 +422,7 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase real64 dGravHead_dP[numEqn][2]{}; real64 capGrad[numEqn]{}; + real64 capPresIC[numEqn][2]{}; real64 dCapGrad_dP[numEqn][2]{}; real64 dCapGrad_dS[numEqn][2]{}; @@ -417,6 +434,13 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase real64 dMob_dP[numEqn][2]{}; real64 dMob_dS[numEqn][2]{}; + real64 density2[numEqn]{}; + real64 dDens_dP2[numEqn][2]{}; + + real64 uT = 0; + real64 duT_dP[numEqn]{}; + real64 duT_dS[numEqn]{}; + real64 const trans[2] = { stack.transmissibility[connectionIndex][0], stack.transmissibility[connectionIndex][1] }; real64 const dTrans_dP[2] = { stack.dTrans_dPres[connectionIndex][0], stack.dTrans_dPres[connectionIndex][1] }; @@ -492,6 +516,7 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase if( m_hasCapPressure ) // check sign convention { real64 const capPres = m_phaseCapPressure[er][esr][ei][0][ip]; // Pc = Pc1 || Pc2 + capPresIC[ip][ke] = capPres; dCapGrad_dTrans -= signPotDiff[ke] * capPres; // dDPc/dT = (-Pc1 + Pc2) pot -= trans[ke] * capPres; // Phi = T P1 - rho T g z1 - T Pc1 || -T P2 + rho T g z2 + T // Pc2 @@ -543,6 +568,8 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase localIndex const k_up = 1 - localIndex( fmax( fmin( alpha, 1.0 ), 0.0 ) ); // 1 upwind -> k_up = 0 || 2 upwind -> k_up = 1 mobility[ip] = m_mob[seri[k_up]][sesri[k_up]][sei[k_up]][ip]; // M = Mupstream + density2[ip] = m_dens[seri[k_up]][sesri[k_up]][sei[k_up]][0][ip]; // r = rho1 || rho2 + dDens_dP2[ip][k_up] = m_dDens_dPres[seri[k_up]][sesri[k_up]][sei[k_up]][0][ip][Deriv::dP]; // dr/dP = dr1/dP1 || dr2/dP dMob_dP[ip][k_up] = m_dMob[seri[k_up]][sesri[k_up]][sei[k_up]][ip][Deriv::dP]; // dM/dP = {dM/dP1 , 0} OR {0 , dM/dP2} dMob_dS[ip][k_up] = m_dMob[seri[k_up]][sesri[k_up]][sei[k_up]][ip][Deriv::dS]; // dM/dS = {dM/dS1 , 0} OR {0 , dM/dS2} } @@ -552,6 +579,8 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase for( integer ke = 0; ke < 2; ++ke ) { mobility[ip] += mobWeights[ke] * m_mob[seri[ke]][sesri[ke]][sei[ke]][ip]; // M = alpha * M1 + (1 - alpha) * M2 + density2[ip] += mobWeights[ke] * m_dens[seri[ke]][sesri[ke]][sei[ke]][0][ip]; // r = rho1 || rho2 + dDens_dP2[ip][ke] = mobWeights[ke] * m_dDens_dPres[seri[ke]][sesri[ke]][sei[ke]][0][ip][Deriv::dP]; // dr/dP = dr1/dP1 || dr2/dP dMob_dP[ip][ke] = mobWeights[ke] * m_dMob[seri[ke]][sesri[ke]][sei[ke]][ip][Deriv::dP]; // dM/dP = {alpha * dM1/dP1 , (1 - // alpha) * dM2/dP2} dMob_dS[ip][ke] = mobWeights[ke] * m_dMob[seri[ke]][sesri[ke]][sei[ke]][ip][Deriv::dS]; // dM/dP = {alpha * dM1/dS1 , (1 - @@ -609,11 +638,23 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase // rho g (z1 - z2) + dT/dP1 * (-Pc1 + Pc2)] + dM/dP1 * DPhi , // M [-T + dT/dP2 * (P1 - P2) - drho2/dP * T g (z1 - z2) - dT/dP2 * // rho g (z1 - z2) + dT/dP2 * (-Pc1 + Pc2)] + dM/dP2 * DPhi } - dFlux_dS[ip][ke] += dMob_dS[ip][ke] * potGrad; // dF/dS = { M [T * -dPc/dS1] + dM/dS1 * DPhi , M [T * dPc/dS2] + dM/dS2 * DPhi // } } + uT += fluxVal[ip] / density2[ip]; + + // add contribution from upstream cell mobility derivatives + for( integer ke = 0; ke < 2; ++ke ) + { + duT_dP[ke] += dFlux_dP[ip][ke] - fluxVal[ip] * dDens_dP2[ip][ke] / density2[ip]; // dF/dP = { M [ T + dT/dP1 * (P1 - P2) - drho1/dP * T g (z1 - z2) - dT/dP1 * + duT_dP[ke] /= density2[ip]; // rho g (z1 - z2) + dT/dP1 * (-Pc1 + Pc2)] + dM/dP1 * DPhi , + // M [-T + dT/dP2 * (P1 - P2) - drho2/dP * T g (z1 - z2) - dT/dP2 * + // rho g (z1 - z2) + dT/dP2 * (-Pc1 + Pc2)] + dM/dP2 * DPhi } + duT_dS[ke] += dFlux_dS[ip][ke] / density2[ip]; // dF/dS = { M [T * -dPc/dS1] + dM/dS1 * DPhi , M [T * dPc/dS2] + dM/dS2 * DPhi + // } + } + // populate local flux vector and derivatives stack.localFlux[k[0]*numEqn + ip] += m_dt * fluxVal[ip]; stack.localFlux[k[1]*numEqn + ip] -= m_dt * fluxVal[ip]; @@ -633,9 +674,43 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase // Customize the kernel with this lambda kernelOp( k, seri, sesri, sei, connectionIndex, alpha, mobility, potGrad, fluxVal, dFlux_dP, dFlux_dS ); // Not sure what this - // does + + // does } // loop over phases + + if( m_hasCapPressure ) + { + // std::cout << GEOS_FMT( " uT = ( {:4.2e} )", uT ); + // std::cout << GEOS_FMT( " duTdP = ( {:4.2e} )", duT_dP[0] ); + // std::cout << GEOS_FMT( " duTdS = ( {:4.2e} )", duT_dS[0] ); + std::cout << GEOS_FMT( " Pc1 = ( {:4.2e} )", capPresIC[0][0] ); + std::cout << GEOS_FMT( " Pc2 = ( {:4.2e} )", capPresIC[0][1] ); + + + + // -------------------- Here I implement the interface conditions local solver --------------------- // + // initial guess: + real64 S_int[numEqn]{}; + real64 const Pc1 = capPresIC[0][0]; + real64 const Pc2 = capPresIC[0][1]; + + real64 const Pc_int = ( Pc1 + Pc2 ) / 2; + + // Local newton loop: + + // compute S_alpha and S_beta: + S_int[0] = computePCalphaInv > ( Pc_int ); + S_int[1] = computePCalphaInv > ( Pc_int ); + + real64 S_avg = S_int[0] + S_int[1]; + + // real64 PC_int1 = computePCalphaInv > ( S_int[0] ); + // real64 PC_int2 = computePCalphaInv > ( S_int[1] ); + GEOS_UNUSED_PARAM( S_avg ); + + } + connectionIndex++; } @@ -762,6 +837,7 @@ class FaceBasedAssemblyKernelFactory globalIndex const rankOffset, string const & dofKey, integer const hasCapPressure, + CapillaryPressureBase const & capPressure, integer const useTotalMassEquation, integer const checkPhasePresenceInGravity, string const & solverName, @@ -771,6 +847,14 @@ class FaceBasedAssemblyKernelFactory CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) { + // constitutiveUpdatePassThru( capPressure, [&] ( auto & castedCapPres ) + // { + // typename TYPEOFREF( castedCapPres ) ::KernelWrapper const & capPresWrapper = castedCapPres.createKernelWrapper(); + // isothermalCompositionalMultiphaseBaseKernels:: + // CapillaryPressureUpdateKernel:: + // launch< parallelDevicePolicy<> >( dataGroup.size(), + // capPresWrapper, + // phaseVolFrac ); integer constexpr NUM_EQN = 2; integer constexpr NUM_DOF = 2; @@ -789,6 +873,7 @@ class FaceBasedAssemblyKernelFactory dt, localMatrix, localRhs, hasCapPressure, useTotalMassEquation, checkPhasePresenceInGravity ); kernelType::template launch< POLICY >( stencilWrapper.size(), kernel ); + // } ); } }; From 9ff577e7f5dfaa2be418a0139e54aac83d98e6b0 Mon Sep 17 00:00:00 2001 From: Pavel Tomin Date: Fri, 28 Feb 2025 10:12:28 -0600 Subject: [PATCH 089/104] code style --- .../fluidFlow/ImmiscibleMultiphaseFlow.cpp | 63 +++++++-------- .../ImmiscibleMultiphaseKernels.hpp | 78 ++++++++++--------- 2 files changed, 71 insertions(+), 70 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index 8b70e4bba44..1e34d659d6c 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -618,41 +618,38 @@ void ImmiscibleMultiphaseFlow::assembleFluxTerms( real64 const dt, MeshLevel const & mesh, string_array const & regionNames ) { - - - fluxApprox.forAllStencils( mesh, [&]( auto & stencil ) { - mesh.getElemManager().forElementSubRegions( regionNames, - [&]( localIndex const, - ElementSubRegionBase const & subRegion ) - { - // if( m_hasCapPressure ) - // { - string const & cappresName = subRegion.getReference< string >( viewKeyStruct::capPressureNamesString() ); - CapillaryPressureBase const & capPressure = getConstitutiveModel< CapillaryPressureBase >( subRegion, cappresName ); - // constitutive::constitutiveUpdatePassThru( capPressure, [&] ( auto & castedCapPres ) - // { - // typename TYPEOFREF( castedCapPres ) ::KernelWrapper capPresWrapper = castedCapPres.createKernelWrapper(); - // } ); - // } - - typename TYPEOFREF( stencil ) ::KernelWrapper stencilWrapper = stencil.createKernelWrapper(); - immiscibleMultiphaseKernels:: - FaceBasedAssemblyKernelFactory::createAndLaunch< parallelDevicePolicy<> >( m_numPhases, - dofManager.rankOffset(), - dofKey, - m_hasCapPressure, - capPressure, - m_useTotalMassEquation, - m_gravityDensityScheme == GravityDensityScheme::PhasePresence, - getName(), - mesh.getElemManager(), - stencilWrapper, - dt, - localMatrix.toViewConstSizes(), - localRhs.toView() ); - } ); + mesh.getElemManager().forElementSubRegions( regionNames, + [&]( localIndex const, + ElementSubRegionBase const & subRegion ) + { + // if( m_hasCapPressure ) + // { + string const & cappresName = subRegion.getReference< string >( viewKeyStruct::capPressureNamesString() ); + CapillaryPressureBase const & capPressure = getConstitutiveModel< CapillaryPressureBase >( subRegion, cappresName ); + // constitutive::constitutiveUpdatePassThru( capPressure, [&] ( auto & castedCapPres ) + // { + // typename TYPEOFREF( castedCapPres ) ::KernelWrapper capPresWrapper = castedCapPres.createKernelWrapper(); + // } ); + // } + + typename TYPEOFREF( stencil ) ::KernelWrapper stencilWrapper = stencil.createKernelWrapper(); + immiscibleMultiphaseKernels:: + FaceBasedAssemblyKernelFactory::createAndLaunch< parallelDevicePolicy<> >( m_numPhases, + dofManager.rankOffset(), + dofKey, + m_hasCapPressure, + capPressure, + m_useTotalMassEquation, + m_gravityDensityScheme == GravityDensityScheme::PhasePresence, + getName(), + mesh.getElemManager(), + stencilWrapper, + dt, + localMatrix.toViewConstSizes(), + localRhs.toView() ); + } ); } ); } ); } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp index 160f806d48d..1318f869e75 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp @@ -54,14 +54,16 @@ namespace geos namespace immiscibleMultiphaseKernels { - template< typename VIEWTYPE > -real64 computePCalpha ( real64 S ) { +template< typename VIEWTYPE > +real64 computePCalpha ( real64 S ) +{ real64 Pe = Pe_max; return (Pe * (1.0 - S)); } template< typename VIEWTYPE > -real64 computePCalphaInv ( real64 Pc ) { +real64 computePCalphaInv ( real64 Pc ) +{ real64 Pe = Pe_max; return (1.0 - Pc / Pe); } @@ -580,7 +582,8 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase { mobility[ip] += mobWeights[ke] * m_mob[seri[ke]][sesri[ke]][sei[ke]][ip]; // M = alpha * M1 + (1 - alpha) * M2 density2[ip] += mobWeights[ke] * m_dens[seri[ke]][sesri[ke]][sei[ke]][0][ip]; // r = rho1 || rho2 - dDens_dP2[ip][ke] = mobWeights[ke] * m_dDens_dPres[seri[ke]][sesri[ke]][sei[ke]][0][ip][Deriv::dP]; // dr/dP = dr1/dP1 || dr2/dP + dDens_dP2[ip][ke] = mobWeights[ke] * m_dDens_dPres[seri[ke]][sesri[ke]][sei[ke]][0][ip][Deriv::dP]; // dr/dP = dr1/dP1 || + // dr2/dP dMob_dP[ip][ke] = mobWeights[ke] * m_dMob[seri[ke]][sesri[ke]][sei[ke]][ip][Deriv::dP]; // dM/dP = {alpha * dM1/dP1 , (1 - // alpha) * dM2/dP2} dMob_dS[ip][ke] = mobWeights[ke] * m_dMob[seri[ke]][sesri[ke]][sei[ke]][ip][Deriv::dS]; // dM/dP = {alpha * dM1/dS1 , (1 - @@ -642,15 +645,16 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase // } } - uT += fluxVal[ip] / density2[ip]; + uT += fluxVal[ip] / density2[ip]; // add contribution from upstream cell mobility derivatives for( integer ke = 0; ke < 2; ++ke ) { - duT_dP[ke] += dFlux_dP[ip][ke] - fluxVal[ip] * dDens_dP2[ip][ke] / density2[ip]; // dF/dP = { M [ T + dT/dP1 * (P1 - P2) - drho1/dP * T g (z1 - z2) - dT/dP1 * + duT_dP[ke] += dFlux_dP[ip][ke] - fluxVal[ip] * dDens_dP2[ip][ke] / density2[ip]; // dF/dP = { M [ T + dT/dP1 * (P1 - P2) - + // drho1/dP * T g (z1 - z2) - dT/dP1 * duT_dP[ke] /= density2[ip]; // rho g (z1 - z2) + dT/dP1 * (-Pc1 + Pc2)] + dM/dP1 * DPhi , - // M [-T + dT/dP2 * (P1 - P2) - drho2/dP * T g (z1 - z2) - dT/dP2 * - // rho g (z1 - z2) + dT/dP2 * (-Pc1 + Pc2)] + dM/dP2 * DPhi } + // M [-T + dT/dP2 * (P1 - P2) - drho2/dP * T g (z1 - z2) - dT/dP2 * + // rho g (z1 - z2) + dT/dP2 * (-Pc1 + Pc2)] + dM/dP2 * DPhi } duT_dS[ke] += dFlux_dS[ip][ke] / density2[ip]; // dF/dS = { M [T * -dPc/dS1] + dM/dS1 * DPhi , M [T * dPc/dS2] + dM/dS2 * DPhi // } } @@ -674,42 +678,42 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase // Customize the kernel with this lambda kernelOp( k, seri, sesri, sei, connectionIndex, alpha, mobility, potGrad, fluxVal, dFlux_dP, dFlux_dS ); // Not sure what this - - // does + + // does } // loop over phases - + if( m_hasCapPressure ) - { - // std::cout << GEOS_FMT( " uT = ( {:4.2e} )", uT ); - // std::cout << GEOS_FMT( " duTdP = ( {:4.2e} )", duT_dP[0] ); - // std::cout << GEOS_FMT( " duTdS = ( {:4.2e} )", duT_dS[0] ); - std::cout << GEOS_FMT( " Pc1 = ( {:4.2e} )", capPresIC[0][0] ); - std::cout << GEOS_FMT( " Pc2 = ( {:4.2e} )", capPresIC[0][1] ); + { + // std::cout << GEOS_FMT( " uT = ( {:4.2e} )", uT ); + // std::cout << GEOS_FMT( " duTdP = ( {:4.2e} )", duT_dP[0] ); + // std::cout << GEOS_FMT( " duTdS = ( {:4.2e} )", duT_dS[0] ); + std::cout << GEOS_FMT( " Pc1 = ( {:4.2e} )", capPresIC[0][0] ); + std::cout << GEOS_FMT( " Pc2 = ( {:4.2e} )", capPresIC[0][1] ); - // -------------------- Here I implement the interface conditions local solver --------------------- // - // initial guess: - real64 S_int[numEqn]{}; - real64 const Pc1 = capPresIC[0][0]; - real64 const Pc2 = capPresIC[0][1]; + // -------------------- Here I implement the interface conditions local solver --------------------- // + // initial guess: + real64 S_int[numEqn]{}; + real64 const Pc1 = capPresIC[0][0]; + real64 const Pc2 = capPresIC[0][1]; - real64 const Pc_int = ( Pc1 + Pc2 ) / 2; + real64 const Pc_int = ( Pc1 + Pc2 ) / 2; - // Local newton loop: + // Local newton loop: - // compute S_alpha and S_beta: - S_int[0] = computePCalphaInv > ( Pc_int ); - S_int[1] = computePCalphaInv > ( Pc_int ); + // compute S_alpha and S_beta: + S_int[0] = computePCalphaInv< arrayView1d< real64 const > >( Pc_int ); + S_int[1] = computePCalphaInv< arrayView1d< real64 const > >( Pc_int ); - real64 S_avg = S_int[0] + S_int[1]; + real64 S_avg = S_int[0] + S_int[1]; - // real64 PC_int1 = computePCalphaInv > ( S_int[0] ); - // real64 PC_int2 = computePCalphaInv > ( S_int[1] ); - GEOS_UNUSED_PARAM( S_avg ); + // real64 PC_int1 = computePCalphaInv > ( S_int[0] ); + // real64 PC_int2 = computePCalphaInv > ( S_int[1] ); + GEOS_UNUSED_PARAM( S_avg ); - } + } connectionIndex++; @@ -850,11 +854,11 @@ class FaceBasedAssemblyKernelFactory // constitutiveUpdatePassThru( capPressure, [&] ( auto & castedCapPres ) // { // typename TYPEOFREF( castedCapPres ) ::KernelWrapper const & capPresWrapper = castedCapPres.createKernelWrapper(); - // isothermalCompositionalMultiphaseBaseKernels:: - // CapillaryPressureUpdateKernel:: - // launch< parallelDevicePolicy<> >( dataGroup.size(), - // capPresWrapper, - // phaseVolFrac ); + // isothermalCompositionalMultiphaseBaseKernels:: + // CapillaryPressureUpdateKernel:: + // launch< parallelDevicePolicy<> >( dataGroup.size(), + // capPresWrapper, + // phaseVolFrac ); integer constexpr NUM_EQN = 2; integer constexpr NUM_DOF = 2; From 2a25e7bdd994ef454b7c5922c742374ffdbede1c Mon Sep 17 00:00:00 2001 From: Pavel Tomin Date: Fri, 28 Feb 2025 11:03:47 -0600 Subject: [PATCH 090/104] try this --- .../fluidFlow/ImmiscibleMultiphaseFlow.cpp | 49 +- .../fluidFlow/ImmiscibleMultiphaseFlow.hpp | 11 +- .../ImmiscibleMultiphaseKernels.hpp | 566 +++++++++++++++--- 3 files changed, 533 insertions(+), 93 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index 1e34d659d6c..78afa888ba6 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -600,7 +600,7 @@ void ImmiscibleMultiphaseFlow::assembleAccumulationTerm( DomainPartition & domai } void ImmiscibleMultiphaseFlow::assembleFluxTerms( real64 const dt, - DomainPartition const & domain, + DomainPartition & domain, DofManager const & dofManager, CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) const @@ -615,32 +615,52 @@ void ImmiscibleMultiphaseFlow::assembleFluxTerms( real64 const dt, forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, - MeshLevel const & mesh, + MeshLevel & mesh, string_array const & regionNames ) { - fluxApprox.forAllStencils( mesh, [&]( auto & stencil ) + if( m_hasCapPressure ) { mesh.getElemManager().forElementSubRegions( regionNames, [&]( localIndex const, - ElementSubRegionBase const & subRegion ) + ElementSubRegionBase & subRegion ) { - // if( m_hasCapPressure ) - // { string const & cappresName = subRegion.getReference< string >( viewKeyStruct::capPressureNamesString() ); - CapillaryPressureBase const & capPressure = getConstitutiveModel< CapillaryPressureBase >( subRegion, cappresName ); - // constitutive::constitutiveUpdatePassThru( capPressure, [&] ( auto & castedCapPres ) - // { - // typename TYPEOFREF( castedCapPres ) ::KernelWrapper capPresWrapper = castedCapPres.createKernelWrapper(); - // } ); - // } + CapillaryPressureBase & capPressure = getConstitutiveModel< CapillaryPressureBase >( subRegion, cappresName ); + constitutive::constitutiveUpdatePassThru( capPressure, [&] ( auto & castedCapPres ) + { + typename TYPEOFREF( castedCapPres ) ::KernelWrapper capPresWrapper = castedCapPres.createKernelWrapper(); + fluxApprox.forAllStencils( mesh, [&]( auto & stencil ) + { + typename TYPEOFREF( stencil ) ::KernelWrapper stencilWrapper = stencil.createKernelWrapper(); + immiscibleMultiphaseKernels:: + FaceBasedAssemblyKernelFactory::createAndLaunch< parallelDevicePolicy<> >( m_numPhases, + dofManager.rankOffset(), + dofKey, + m_hasCapPressure, + m_useTotalMassEquation, + m_gravityDensityScheme == GravityDensityScheme::PhasePresence, + getName(), + mesh.getElemManager(), + stencilWrapper, + capPresWrapper, + dt, + localMatrix.toViewConstSizes(), + localRhs.toView() ); + } ); + } ); + } ); + } + else + { + fluxApprox.forAllStencils( mesh, [&]( auto & stencil ) + { typename TYPEOFREF( stencil ) ::KernelWrapper stencilWrapper = stencil.createKernelWrapper(); immiscibleMultiphaseKernels:: FaceBasedAssemblyKernelFactory::createAndLaunch< parallelDevicePolicy<> >( m_numPhases, dofManager.rankOffset(), dofKey, m_hasCapPressure, - capPressure, m_useTotalMassEquation, m_gravityDensityScheme == GravityDensityScheme::PhasePresence, getName(), @@ -650,7 +670,8 @@ void ImmiscibleMultiphaseFlow::assembleFluxTerms( real64 const dt, localMatrix.toViewConstSizes(), localRhs.toView() ); } ); - } ); + } + } ); } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp index 5d876f9cfd7..feca5e497d0 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp @@ -160,12 +160,11 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase * @param matrix the system matrix * @param rhs the system right-hand side vector */ - virtual void - assembleFluxTerms( real64 const dt, - DomainPartition const & domain, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) const; + void assembleFluxTerms( real64 const dt, + DomainPartition & domain, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) const; /** * @brief Function to perform the Application of Dirichlet type BC's diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp index 1318f869e75..ef3b45ce09b 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp @@ -424,7 +424,6 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase real64 dGravHead_dP[numEqn][2]{}; real64 capGrad[numEqn]{}; - real64 capPresIC[numEqn][2]{}; real64 dCapGrad_dP[numEqn][2]{}; real64 dCapGrad_dS[numEqn][2]{}; @@ -436,13 +435,6 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase real64 dMob_dP[numEqn][2]{}; real64 dMob_dS[numEqn][2]{}; - real64 density2[numEqn]{}; - real64 dDens_dP2[numEqn][2]{}; - - real64 uT = 0; - real64 duT_dP[numEqn]{}; - real64 duT_dS[numEqn]{}; - real64 const trans[2] = { stack.transmissibility[connectionIndex][0], stack.transmissibility[connectionIndex][1] }; real64 const dTrans_dP[2] = { stack.dTrans_dPres[connectionIndex][0], stack.dTrans_dPres[connectionIndex][1] }; @@ -518,7 +510,6 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase if( m_hasCapPressure ) // check sign convention { real64 const capPres = m_phaseCapPressure[er][esr][ei][0][ip]; // Pc = Pc1 || Pc2 - capPresIC[ip][ke] = capPres; dCapGrad_dTrans -= signPotDiff[ke] * capPres; // dDPc/dT = (-Pc1 + Pc2) pot -= trans[ke] * capPres; // Phi = T P1 - rho T g z1 - T Pc1 || -T P2 + rho T g z2 + T // Pc2 @@ -570,8 +561,6 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase localIndex const k_up = 1 - localIndex( fmax( fmin( alpha, 1.0 ), 0.0 ) ); // 1 upwind -> k_up = 0 || 2 upwind -> k_up = 1 mobility[ip] = m_mob[seri[k_up]][sesri[k_up]][sei[k_up]][ip]; // M = Mupstream - density2[ip] = m_dens[seri[k_up]][sesri[k_up]][sei[k_up]][0][ip]; // r = rho1 || rho2 - dDens_dP2[ip][k_up] = m_dDens_dPres[seri[k_up]][sesri[k_up]][sei[k_up]][0][ip][Deriv::dP]; // dr/dP = dr1/dP1 || dr2/dP dMob_dP[ip][k_up] = m_dMob[seri[k_up]][sesri[k_up]][sei[k_up]][ip][Deriv::dP]; // dM/dP = {dM/dP1 , 0} OR {0 , dM/dP2} dMob_dS[ip][k_up] = m_dMob[seri[k_up]][sesri[k_up]][sei[k_up]][ip][Deriv::dS]; // dM/dS = {dM/dS1 , 0} OR {0 , dM/dS2} } @@ -581,9 +570,6 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase for( integer ke = 0; ke < 2; ++ke ) { mobility[ip] += mobWeights[ke] * m_mob[seri[ke]][sesri[ke]][sei[ke]][ip]; // M = alpha * M1 + (1 - alpha) * M2 - density2[ip] += mobWeights[ke] * m_dens[seri[ke]][sesri[ke]][sei[ke]][0][ip]; // r = rho1 || rho2 - dDens_dP2[ip][ke] = mobWeights[ke] * m_dDens_dPres[seri[ke]][sesri[ke]][sei[ke]][0][ip][Deriv::dP]; // dr/dP = dr1/dP1 || - // dr2/dP dMob_dP[ip][ke] = mobWeights[ke] * m_dMob[seri[ke]][sesri[ke]][sei[ke]][ip][Deriv::dP]; // dM/dP = {alpha * dM1/dP1 , (1 - // alpha) * dM2/dP2} dMob_dS[ip][ke] = mobWeights[ke] * m_dMob[seri[ke]][sesri[ke]][sei[ke]][ip][Deriv::dS]; // dM/dP = {alpha * dM1/dS1 , (1 - @@ -641,21 +627,8 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase // rho g (z1 - z2) + dT/dP1 * (-Pc1 + Pc2)] + dM/dP1 * DPhi , // M [-T + dT/dP2 * (P1 - P2) - drho2/dP * T g (z1 - z2) - dT/dP2 * // rho g (z1 - z2) + dT/dP2 * (-Pc1 + Pc2)] + dM/dP2 * DPhi } - dFlux_dS[ip][ke] += dMob_dS[ip][ke] * potGrad; // dF/dS = { M [T * -dPc/dS1] + dM/dS1 * DPhi , M [T * dPc/dS2] + dM/dS2 * DPhi - // } - } - - uT += fluxVal[ip] / density2[ip]; - // add contribution from upstream cell mobility derivatives - for( integer ke = 0; ke < 2; ++ke ) - { - duT_dP[ke] += dFlux_dP[ip][ke] - fluxVal[ip] * dDens_dP2[ip][ke] / density2[ip]; // dF/dP = { M [ T + dT/dP1 * (P1 - P2) - - // drho1/dP * T g (z1 - z2) - dT/dP1 * - duT_dP[ke] /= density2[ip]; // rho g (z1 - z2) + dT/dP1 * (-Pc1 + Pc2)] + dM/dP1 * DPhi , - // M [-T + dT/dP2 * (P1 - P2) - drho2/dP * T g (z1 - z2) - dT/dP2 * - // rho g (z1 - z2) + dT/dP2 * (-Pc1 + Pc2)] + dM/dP2 * DPhi } - duT_dS[ke] += dFlux_dS[ip][ke] / density2[ip]; // dF/dS = { M [T * -dPc/dS1] + dM/dS1 * DPhi , M [T * dPc/dS2] + dM/dS2 * DPhi + dFlux_dS[ip][ke] += dMob_dS[ip][ke] * potGrad; // dF/dS = { M [T * -dPc/dS1] + dM/dS1 * DPhi , M [T * dPc/dS2] + dM/dS2 * DPhi // } } @@ -678,44 +651,10 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase // Customize the kernel with this lambda kernelOp( k, seri, sesri, sei, connectionIndex, alpha, mobility, potGrad, fluxVal, dFlux_dP, dFlux_dS ); // Not sure what this - - // does + // does } // loop over phases - if( m_hasCapPressure ) - { - // std::cout << GEOS_FMT( " uT = ( {:4.2e} )", uT ); - // std::cout << GEOS_FMT( " duTdP = ( {:4.2e} )", duT_dP[0] ); - // std::cout << GEOS_FMT( " duTdS = ( {:4.2e} )", duT_dS[0] ); - std::cout << GEOS_FMT( " Pc1 = ( {:4.2e} )", capPresIC[0][0] ); - std::cout << GEOS_FMT( " Pc2 = ( {:4.2e} )", capPresIC[0][1] ); - - - - // -------------------- Here I implement the interface conditions local solver --------------------- // - // initial guess: - real64 S_int[numEqn]{}; - real64 const Pc1 = capPresIC[0][0]; - real64 const Pc2 = capPresIC[0][1]; - - real64 const Pc_int = ( Pc1 + Pc2 ) / 2; - - // Local newton loop: - - // compute S_alpha and S_beta: - S_int[0] = computePCalphaInv< arrayView1d< real64 const > >( Pc_int ); - S_int[1] = computePCalphaInv< arrayView1d< real64 const > >( Pc_int ); - - real64 S_avg = S_int[0] + S_int[1]; - - // real64 PC_int1 = computePCalphaInv > ( S_int[0] ); - // real64 PC_int2 = computePCalphaInv > ( S_int[1] ); - GEOS_UNUSED_PARAM( S_avg ); - - } - - connectionIndex++; } } // loop over connection elements @@ -812,6 +751,446 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase typename STENCILWRAPPER::IndexContainerViewConstType const m_sei; }; +/** + * @class FaceBasedAssemblyInterfaceConditionKernel + * @tparam NUM_DOF number of degrees of freedom + * @tparam STENCILWRAPPER the type of the stencil wrapper + * @tparam CAPPRESWRAPPER the type of the capillary pressure wrapper + * @brief Define the interface for the assembly kernel in charge of flux terms + */ +template< integer NUM_EQN, integer NUM_DOF, typename STENCILWRAPPER, typename CAPPRESWRAPPER > +class FaceBasedAssemblyInterfaceConditionKernel : public FaceBasedAssemblyKernel< NUM_EQN, NUM_DOF, STENCILWRAPPER > +{ +public: + + using AbstractBase = FaceBasedAssemblyKernelBase; + using DofNumberAccessor = AbstractBase::DofNumberAccessor; + using ImmiscibleMultiphaseFlowAccessors = AbstractBase::ImmiscibleMultiphaseFlowAccessors; + using MultiphaseFluidAccessors = AbstractBase::MultiphaseFluidAccessors; + using CapPressureAccessors = AbstractBase::CapPressureAccessors; + using PermeabilityAccessors = AbstractBase::PermeabilityAccessors; + + using Base = FaceBasedAssemblyKernel< NUM_EQN, NUM_DOF, STENCILWRAPPER >; + using Deriv = typename Base::Deriv; + using StackVariables = typename Base::StackVariables; + using Base::numEqn; + using Base::numDof; + using Base::m_stencilWrapper; + using Base::m_dofNumber; + using Base::m_rankOffset; + using Base::m_localMatrix; + using Base::m_localRhs; + using Base::m_numPhases; + using Base::m_permeability; + using Base::m_dPerm_dPres; + using Base::m_phaseVolFrac; + using Base::m_phaseCapPressure; + using Base::m_dPhaseCapPressure_dPhaseVolFrac; + using Base::m_dens; + using Base::m_dDens_dPres; + using Base::m_dMob; + using Base::m_mob; + using Base::m_gravCoef; + using Base::m_ghostRank; + using Base::m_dt; + using Base::m_hasCapPressure; + using Base::m_useTotalMassEquation; + using Base::m_checkPhasePresenceInGravity; + using Base::m_seri; + using Base::m_sesri; + using Base::m_sei; + using Base::m_pres; + + /** + * @brief Constructor for the kernel interface + * @param[in] numPhases number of fluid phases + * @param[in] rankOffset the offset of my MPI rank + * @param[in] stencilWrapper reference to the stencil wrapper + * @param[in] capPressureWrapper reference to the capillary pressure wrapper + * @param[in] dofNumberAccessor + * @param[in] multiPhaseFlowAccessors + * @param[in] fluidAccessors + * @param[in] capPressureAccessors + * @param[in] permeabilityAccessors + * @param[in] dt time step size + * @param[inout] localMatrix the local CRS matrix + * @param[inout] localRhs the local right-hand side vector + * @param[in] hasCapPressure flags for capillary pressure + * @param[in] useTotalMassEquation flags for using total velocity formulation + */ + FaceBasedAssemblyInterfaceConditionKernel( integer const numPhases, + globalIndex const rankOffset, + STENCILWRAPPER const & stencilWrapper, + CAPPRESWRAPPER const & capPressureWrapper, + DofNumberAccessor const & dofNumberAccessor, + ImmiscibleMultiphaseFlowAccessors const & multiPhaseFlowAccessors, + MultiphaseFluidAccessors const & fluidAccessors, + CapPressureAccessors const & capPressureAccessors, + PermeabilityAccessors const & permeabilityAccessors, + real64 const & dt, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs, + integer const hasCapPressure, + integer const useTotalMassEquation, + integer const checkPhasePresenceInGravity ) + : Base( numPhases, + rankOffset, + stencilWrapper, + dofNumberAccessor, + multiPhaseFlowAccessors, + fluidAccessors, + capPressureAccessors, + permeabilityAccessors, + dt, + localMatrix, + localRhs, + hasCapPressure, + useTotalMassEquation, + checkPhasePresenceInGravity ), + m_capPressureWrapper( capPressureWrapper ) + {} + + /** + * @brief Compute the local flux contributions to the residual and Jacobian + * @tparam FUNC the type of the function that can be used to customize the computation of the flux + * @param[in] iconn the connection index + * @param[inout] stack the stack variables + * @param[in] NoOpFunc the function used to customize the computation of the flux + */ + template< typename FUNC = NoOpFunc > // should change to multiphase + GEOS_HOST_DEVICE + void computeFlux( localIndex const iconn, + StackVariables & stack, + FUNC && kernelOp = NoOpFunc{} ) const + { + // first, compute the transmissibilities at this face // get k and dk/dP from global arrays + // and place in stack + m_stencilWrapper.computeWeights( iconn, + m_permeability, + m_dPerm_dPres, + stack.transmissibility, + stack.dTrans_dPres ); + + localIndex k[2]; + localIndex connectionIndex = 0; + + for( k[0] = 0; k[0] < stack.numFluxElems; ++k[0] ) + { + for( k[1] = k[0] + 1; k[1] < stack.numFluxElems; ++k[1] ) + { + // clear working arrays + real64 densMean[numEqn]{}; + real64 dDensMean_dP[numEqn][2]{}; + + real64 presGrad[numEqn]{}; + real64 dPresGrad_dP[numEqn][2]{}; + + real64 gravHead[numEqn]{}; + real64 dGravHead_dP[numEqn][2]{}; + + real64 capGrad[numEqn]{}; + real64 capPresIC[numEqn][2]{}; + real64 dCapGrad_dP[numEqn][2]{}; + real64 dCapGrad_dS[numEqn][2]{}; + + real64 fluxVal[numEqn]{}; + real64 dFlux_dP[numEqn][2]{}; + real64 dFlux_dS[numEqn][2]{}; + + real64 mobility[numEqn]{}; + real64 dMob_dP[numEqn][2]{}; + real64 dMob_dS[numEqn][2]{}; + + real64 density2[numEqn]{}; + real64 dDens_dP2[numEqn][2]{}; + + real64 uT = 0; + real64 duT_dP[numEqn]{}; + real64 duT_dS[numEqn]{}; + + real64 const trans[2] = { stack.transmissibility[connectionIndex][0], stack.transmissibility[connectionIndex][1] }; + real64 const dTrans_dP[2] = { stack.dTrans_dPres[connectionIndex][0], stack.dTrans_dPres[connectionIndex][1] }; + + // cell indices + localIndex const seri[2] = {m_seri( iconn, k[0] ), m_seri( iconn, k[1] )}; + localIndex const sesri[2] = {m_sesri( iconn, k[0] ), m_sesri( iconn, k[1] )}; + localIndex const sei[2] = {m_sei( iconn, k[0] ), m_sei( iconn, k[1] )}; + + // loop over phases + for( integer ip = 0; ip < m_numPhases; ++ip ) + { + // calculate quantities on primary connected cells + integer denom = 0; + for( integer ke = 0; ke < 2; ++ke ) + { + // density + bool const phaseExists = (m_phaseVolFrac[seri[ke]][sesri[ke]][sei[ke]][ip] > 0); + if( m_checkPhasePresenceInGravity && !phaseExists ) + { + continue; + } + + real64 const density = m_dens[seri[ke]][sesri[ke]][sei[ke]][0][ip]; // r = rho1 || rho2 + real64 const dDens_dP = m_dDens_dPres[seri[ke]][sesri[ke]][sei[ke]][0][ip][Deriv::dP]; // dr/dP = dr1/dP1 || dr2/dP + + // average density and derivatives + densMean[ip] += density; // rho = (rho1 + rho2) + dDensMean_dP[ip][ke] = dDens_dP; // drho/dP = { (dr1/dP1) , (dr2/dP2) } + + denom++; + } + + if( denom > 1 ) + { + densMean[ip] /= denom; // rho = (rho1 + rho2) / denom + for( integer ke = 0; ke < 2; ++ke ) + { + dDensMean_dP[ip][ke] /= denom; // drho/dP = { (dr1/dP1) / denom , (dr2/dP2) / denom } + } + } + + //***** calculation of flux ***** + + // compute potential difference + real64 potScale = 0.0; + real64 dPresGrad_dTrans = 0.0; + real64 dGravHead_dTrans = 0.0; + real64 dCapGrad_dTrans = 0.0; + constexpr int signPotDiff[2] = {1, -1}; + + for( integer ke = 0; ke < 2; ++ke ) + { + localIndex const er = seri[ke]; + localIndex const esr = sesri[ke]; + localIndex const ei = sei[ke]; + + real64 const pressure = m_pres[er][esr][ei]; // P = P1 || P2 + presGrad[ip] += trans[ke] * pressure; // DPv = T (P1 - P2) + dPresGrad_dTrans += signPotDiff[ke] * pressure; // dDPv/dT = (P1 - P2) + dPresGrad_dP[ip][ke] = trans[ke]; // dDPv/dP = { T , -T } + + real64 const gravD = trans[ke] * m_gravCoef[er][esr][ei]; // D = T g z1 || -T g z2 + real64 pot = trans[ke] * pressure - densMean[ip] * gravD; // Phi = T P1 - rho T g z1 || -T P2 + rho T g z2 + + gravHead[ip] += densMean[ip] * gravD; // DPg = rho (T g z1 - T g z2) = T rho g (z1 - z2) + dGravHead_dTrans += signPotDiff[ke] * densMean[ip] * m_gravCoef[er][esr][ei]; // dDPg/dT = rho g z1 - rho g z2 = rho g (z1 - z2) + + for( integer i = 0; i < 2; ++i ) + { + dGravHead_dP[ip][i] += dDensMean_dP[ip][i] * gravD; // dDPg/dP = {drho/dP1 * T g (z1 - z2) , drho/dP2 * T g (z1 - z2)} + } + + if( m_hasCapPressure ) // check sign convention + { + real64 const capPres = m_phaseCapPressure[er][esr][ei][0][ip]; // Pc = Pc1 || Pc2 + capPresIC[ip][ke] = capPres; + dCapGrad_dTrans -= signPotDiff[ke] * capPres; // dDPc/dT = (-Pc1 + Pc2) + pot -= trans[ke] * capPres; // Phi = T P1 - rho T g z1 - T Pc1 || -T P2 + rho T g z2 + T + // Pc2 + capGrad[ip] -= trans[ke] * capPres; // DPc = T (-Pc1 + Pc2) + } + + potScale = fmax( potScale, fabs( pot ) ); // maxPhi = Phi1 > Phi2 ? Phi1 : Phi2 + } + + for( integer ke = 0; ke < 2; ++ke ) + { + dPresGrad_dP[ip][ke] += dTrans_dP[ke] * dPresGrad_dTrans; // dDPv/dP = { T + dT/dP1 * (P1 - P2) , -T + dT/dP2 * (P1 - P2)} + dGravHead_dP[ip][ke] += dTrans_dP[ke] * dGravHead_dTrans; // dDPg/dP = { drho/dP1 * T g (z1 - z2) + dT/dP1 * rho g (z1 - z2) , + // drho/dP2 * T g (z1 - z2) + dT/dP2 * rho g (z1 - z2) } + if( m_hasCapPressure ) + { + real64 const dCapPres_dS = m_dPhaseCapPressure_dPhaseVolFrac[seri[ke]][sesri[ke]][sei[ke]][0][ip][ip]; // dPc/dS = dPc1/dS1 || + // dPc2/dS2 + dCapGrad_dP[ip][ke] += dTrans_dP[ke] * dCapGrad_dTrans; // dDPc/dP = { dT/dP1 * + // (-Pc1 + Pc2) , + // dT/dP2 * + // (-Pc1 + Pc2) } + dCapGrad_dS[ip][ke] -= trans[ke] * dCapPres_dS; // dDPc/dS = { -T * + // dPc1/dS1 , T * + // dPc2/dS2 } + } + } + + // *** upwinding *** + + // compute potential gradient + real64 potGrad = presGrad[ip] - gravHead[ip]; // DPhi = T (P1 - P2) - T rho g (z1 - z2) + if( m_hasCapPressure ) + { + potGrad += capGrad[ip]; // DPhi = T (P1 - P2) - T rho g (z1 - z2) + T (-Pc1 + Pc2) + } + + // compute upwinding tolerance + real64 constexpr upwRelTol = 1e-8; + real64 const upwAbsTol = fmax( potScale * upwRelTol, LvArray::NumericLimits< real64 >::epsilon ); // abstol = maxPhi * tol > eps ? + // maxPhi * tol : eps + + // decide mobility coefficients - smooth variation in [-upwAbsTol; upwAbsTol] + real64 const alpha = ( potGrad + upwAbsTol ) / ( 2 * upwAbsTol ); // alpha = (DPhi + abstol) / abstol / 2 + + // choose upstream cell + if( alpha <= 0.0 || alpha >= 1.0 ) // no smoothing needed + { + localIndex const k_up = 1 - localIndex( fmax( fmin( alpha, 1.0 ), 0.0 ) ); // 1 upwind -> k_up = 0 || 2 upwind -> k_up = 1 + + mobility[ip] = m_mob[seri[k_up]][sesri[k_up]][sei[k_up]][ip]; // M = Mupstream + density2[ip] = m_dens[seri[k_up]][sesri[k_up]][sei[k_up]][0][ip]; // r = rho1 || rho2 + dDens_dP2[ip][k_up] = m_dDens_dPres[seri[k_up]][sesri[k_up]][sei[k_up]][0][ip][Deriv::dP]; // dr/dP = dr1/dP1 || dr2/dP + dMob_dP[ip][k_up] = m_dMob[seri[k_up]][sesri[k_up]][sei[k_up]][ip][Deriv::dP]; // dM/dP = {dM/dP1 , 0} OR {0 , dM/dP2} + dMob_dS[ip][k_up] = m_dMob[seri[k_up]][sesri[k_up]][sei[k_up]][ip][Deriv::dS]; // dM/dS = {dM/dS1 , 0} OR {0 , dM/dS2} + } + else // perform smoothing + { + real64 const mobWeights[2] = { alpha, 1.0 - alpha }; + for( integer ke = 0; ke < 2; ++ke ) + { + mobility[ip] += mobWeights[ke] * m_mob[seri[ke]][sesri[ke]][sei[ke]][ip]; // M = alpha * M1 + (1 - alpha) * M2 + density2[ip] += mobWeights[ke] * m_dens[seri[ke]][sesri[ke]][sei[ke]][0][ip]; // r = rho1 || rho2 + dDens_dP2[ip][ke] = mobWeights[ke] * m_dDens_dPres[seri[ke]][sesri[ke]][sei[ke]][0][ip][Deriv::dP]; // dr/dP = dr1/dP1 || + // dr2/dP + dMob_dP[ip][ke] = mobWeights[ke] * m_dMob[seri[ke]][sesri[ke]][sei[ke]][ip][Deriv::dP]; // dM/dP = {alpha * dM1/dP1 , (1 - + // alpha) * dM2/dP2} + dMob_dS[ip][ke] = mobWeights[ke] * m_dMob[seri[ke]][sesri[ke]][sei[ke]][ip][Deriv::dS]; // dM/dP = {alpha * dM1/dS1 , (1 - + // alpha) * dM2/dS2} + } + } + + // pressure gradient depends on all points in the stencil + for( integer ke = 0; ke < 2; ++ke ) + { + dFlux_dP[ip][ke] += dPresGrad_dP[ip][ke]; // dF/dP = { T + dT/dP1 * (P1 - P2) , + // -T + dT/dP2 * (P1 - P2) } + } + + // gravitational head depends only on the two cells connected (same as mean density) + for( integer ke = 0; ke < 2; ++ke ) + { + dFlux_dP[ip][ke] -= dGravHead_dP[ip][ke]; // dF/dP = { T + dT/dP1 * (P1 - P2) - drho/dP1 * T g (z1 - z2) - dT/dP1 * rho g (z1 - + // z2) , + // -T + dT/dP2 * (P1 - P2) - drho/dP2 * T g (z1 - z2) - dT/dP2 * rho g (z1 - + // z2) } + } + + // capillary pressure contribution + if( m_hasCapPressure ) + { + for( integer ke = 0; ke < 2; ++ke ) + { + dFlux_dP[ip][ke] += dCapGrad_dP[ip][ke]; // dF/dP = { T + dT/dP1 * (P1 - P2) - drho/dP1 * T g (z1 - z2) - dT/dP1 * rho g (z1 + // - z2) + dT/dP1 * (-Pc1 + Pc2) , + // -T + dT/dP2 * (P1 - P2) - drho/dP2 * T g (z1 - z2) - dT/dP2 * rho g (z1 + // - z2) + dT/dP2 * (-Pc1 + Pc2) } + + dFlux_dS[ip][ke] += dCapGrad_dS[ip][ke]; // dF/dS = { T * -dPc/dS1 , T * dPc/dS2 } + } + } + + // compute the flux and derivatives using upstream cell mobility + fluxVal[ip] = mobility[ip] * potGrad; // F = M * DPhi + + for( integer ke = 0; ke < 2; ++ke ) + { + dFlux_dP[ip][ke] *= mobility[ip]; // dF/dP = { M [ T + dT/dP1 * (P1 - P2) - drho/dP1 * T g (z1 - z2) - dT/dP1 * rho g (z1 - + // z2) + dT/dP1 * (-Pc1 + Pc2)] , + // M [-T + dT/dP2 * (P1 - P2) - drho/dP2 * T g (z1 - z2) - dT/dP2 * rho g (z1 - + // z2) + dT/dP2 * (-Pc1 + Pc2)] } + + dFlux_dS[ip][ke] *= mobility[ip]; // dF/dS = { M [T * -dPc/dS1] , M [T * dPc/dS2] } + } + + // add contribution from upstream cell mobility derivatives + for( integer ke = 0; ke < 2; ++ke ) + { + dFlux_dP[ip][ke] += dMob_dP[ip][ke] * potGrad; // dF/dP = { M [ T + dT/dP1 * (P1 - P2) - drho1/dP * T g (z1 - z2) - dT/dP1 * + // rho g (z1 - z2) + dT/dP1 * (-Pc1 + Pc2)] + dM/dP1 * DPhi , + // M [-T + dT/dP2 * (P1 - P2) - drho2/dP * T g (z1 - z2) - dT/dP2 * + // rho g (z1 - z2) + dT/dP2 * (-Pc1 + Pc2)] + dM/dP2 * DPhi } + dFlux_dS[ip][ke] += dMob_dS[ip][ke] * potGrad; // dF/dS = { M [T * -dPc/dS1] + dM/dS1 * DPhi , M [T * dPc/dS2] + dM/dS2 * DPhi + // } + } + + uT += fluxVal[ip] / density2[ip]; + + // add contribution from upstream cell mobility derivatives + for( integer ke = 0; ke < 2; ++ke ) + { + duT_dP[ke] += dFlux_dP[ip][ke] - fluxVal[ip] * dDens_dP2[ip][ke] / density2[ip]; // dF/dP = { M [ T + dT/dP1 * (P1 - P2) - + // drho1/dP * T g (z1 - z2) - dT/dP1 * + duT_dP[ke] /= density2[ip]; // rho g (z1 - z2) + dT/dP1 * (-Pc1 + Pc2)] + dM/dP1 * DPhi , + // M [-T + dT/dP2 * (P1 - P2) - drho2/dP * T g (z1 - z2) - dT/dP2 * + // rho g (z1 - z2) + dT/dP2 * (-Pc1 + Pc2)] + dM/dP2 * DPhi } + duT_dS[ke] += dFlux_dS[ip][ke] / density2[ip]; // dF/dS = { M [T * -dPc/dS1] + dM/dS1 * DPhi , M [T * dPc/dS2] + dM/dS2 * DPhi + // } + } + + // populate local flux vector and derivatives + stack.localFlux[k[0]*numEqn + ip] += m_dt * fluxVal[ip]; + stack.localFlux[k[1]*numEqn + ip] -= m_dt * fluxVal[ip]; + + for( integer ke = 0; ke < 2; ++ke ) + { + // pressure + localIndex const localDofIndexPres = k[ke] * numDof; + stack.localFluxJacobian[k[0]*numEqn + ip][localDofIndexPres] += m_dt * dFlux_dP[ip][ke]; + stack.localFluxJacobian[k[1]*numEqn + ip][localDofIndexPres] -= m_dt * dFlux_dP[ip][ke]; + + // saturation (hard-coded for 2-phase currently) + localIndex const localDofIndexSat = k[ke] * numDof + 1; + stack.localFluxJacobian[k[0]*numEqn + ip][localDofIndexSat] += m_dt * dFlux_dS[ip][ke]; + stack.localFluxJacobian[k[1]*numEqn + ip][localDofIndexSat] -= m_dt * dFlux_dS[ip][ke]; + } + + // Customize the kernel with this lambda + kernelOp( k, seri, sesri, sei, connectionIndex, alpha, mobility, potGrad, fluxVal, dFlux_dP, dFlux_dS ); // Not sure what this + + // does + + } // loop over phases + + if( m_hasCapPressure ) + { + // std::cout << GEOS_FMT( " uT = ( {:4.2e} )", uT ); + // std::cout << GEOS_FMT( " duTdP = ( {:4.2e} )", duT_dP[0] ); + // std::cout << GEOS_FMT( " duTdS = ( {:4.2e} )", duT_dS[0] ); + std::cout << GEOS_FMT( " Pc1 = ( {:4.2e} )", capPresIC[0][0] ); + std::cout << GEOS_FMT( " Pc2 = ( {:4.2e} )", capPresIC[0][1] ); + + + + // -------------------- Here I implement the interface conditions local solver --------------------- // + // initial guess: + real64 S_int[numEqn]{}; + real64 const Pc1 = capPresIC[0][0]; + real64 const Pc2 = capPresIC[0][1]; + + real64 const Pc_int = ( Pc1 + Pc2 ) / 2; + + // Local newton loop: + + // compute S_alpha and S_beta: + S_int[0] = computePCalphaInv< arrayView1d< real64 const > >( Pc_int ); + S_int[1] = computePCalphaInv< arrayView1d< real64 const > >( Pc_int ); + + real64 S_avg = S_int[0] + S_int[1]; + + // real64 PC_int1 = computePCalphaInv > ( S_int[0] ); + // real64 PC_int2 = computePCalphaInv > ( S_int[1] ); + GEOS_UNUSED_PARAM( S_avg ); + + } + + + connectionIndex++; + } + } // loop over connection elements + } +protected: + + /// Reference to the capillary pressure wrapper + CAPPRESWRAPPER const m_capPressureWrapper; +}; + /****************************************** */ @@ -841,7 +1220,6 @@ class FaceBasedAssemblyKernelFactory globalIndex const rankOffset, string const & dofKey, integer const hasCapPressure, - CapillaryPressureBase const & capPressure, integer const useTotalMassEquation, integer const checkPhasePresenceInGravity, string const & solverName, @@ -851,14 +1229,6 @@ class FaceBasedAssemblyKernelFactory CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) { - // constitutiveUpdatePassThru( capPressure, [&] ( auto & castedCapPres ) - // { - // typename TYPEOFREF( castedCapPres ) ::KernelWrapper const & capPresWrapper = castedCapPres.createKernelWrapper(); - // isothermalCompositionalMultiphaseBaseKernels:: - // CapillaryPressureUpdateKernel:: - // launch< parallelDevicePolicy<> >( dataGroup.size(), - // capPresWrapper, - // phaseVolFrac ); integer constexpr NUM_EQN = 2; integer constexpr NUM_DOF = 2; @@ -877,7 +1247,57 @@ class FaceBasedAssemblyKernelFactory dt, localMatrix, localRhs, hasCapPressure, useTotalMassEquation, checkPhasePresenceInGravity ); kernelType::template launch< POLICY >( stencilWrapper.size(), kernel ); - // } ); + } + + /** + * @brief Create a new kernel and launch + * @tparam POLICY the policy used in the RAJA kernel + * @tparam STENCILWRAPPER the type of the stencil wrapper + * @tparam CAPPRESWRAPPER the type of the capillary pressure wrapper + * @param[in] rankOffset the offset of my MPI rank + * @param[in] dofKey string to get the element degrees of freedom numbers + * @param[in] solverName name of the solver (to name accessors) + * @param[in] elemManager reference to the element region manager + * @param[in] stencilWrapper reference to the stencil wrapper + * @param[in] capPresWrapper reference to the capillary pressure wrapper + * @param[in] dt time step size + * @param[inout] localMatrix the local CRS matrix + * @param[inout] localRhs the local right-hand side vector + */ + template< typename POLICY, typename STENCILWRAPPER, typename CAPPRESWRAPPER > + static void + createAndLaunch( integer const numPhases, + globalIndex const rankOffset, + string const & dofKey, + integer const hasCapPressure, + integer const useTotalMassEquation, + integer const checkPhasePresenceInGravity, + string const & solverName, + ElementRegionManager const & elemManager, + STENCILWRAPPER const & stencilWrapper, + CAPPRESWRAPPER const & capPresWrapper, + real64 const & dt, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) + { + integer constexpr NUM_EQN = 2; + integer constexpr NUM_DOF = 2; + + ElementRegionManager::ElementViewAccessor< arrayView1d< globalIndex const > > dofNumberAccessor = + elemManager.constructArrayViewAccessor< globalIndex, 1 >( dofKey ); + dofNumberAccessor.setName( solverName + "/accessors/" + dofKey ); + + using kernelType = FaceBasedAssemblyInterfaceConditionKernel< NUM_EQN, NUM_DOF, STENCILWRAPPER, CAPPRESWRAPPER >; + typename kernelType::ImmiscibleMultiphaseFlowAccessors flowAccessors( elemManager, solverName ); + typename kernelType::MultiphaseFluidAccessors fluidAccessors( elemManager, solverName ); + typename kernelType::CapPressureAccessors capPressureAccessors( elemManager, solverName ); + typename kernelType::PermeabilityAccessors permAccessors( elemManager, solverName ); + + kernelType kernel( numPhases, rankOffset, stencilWrapper, capPresWrapper, dofNumberAccessor, + flowAccessors, fluidAccessors, capPressureAccessors, permAccessors, + dt, localMatrix, localRhs, hasCapPressure, useTotalMassEquation, + checkPhasePresenceInGravity ); + kernelType::template launch< POLICY >( stencilWrapper.size(), kernel ); } }; From 28afb1b86e38bf52b4ab32cad06b70f8642f243f Mon Sep 17 00:00:00 2001 From: Ammara-14 Date: Thu, 1 May 2025 21:15:13 -0700 Subject: [PATCH 091/104] first implementation of interface conditions with J-Leverett Pc curve, it compiles with no errors but may not converge --- .../JFunctionCapillaryPressure.cpp | 50 ++ .../JFunctionCapillaryPressure.hpp | 48 ++ .../TableCapillaryPressure.hpp | 28 + .../capillaryPressureSelector.hpp | 12 +- .../finiteVolume/CellElementStencilTPFA.hpp | 98 ++++ .../EmbeddedSurfaceToCellStencil.hpp | 52 ++ .../finiteVolume/FaceElementToCellStencil.hpp | 53 ++ .../finiteVolume/SurfaceElementStencil.hpp | 79 +++ .../fluidFlow/ImmiscibleMultiphaseFlow.cpp | 23 +- .../CapillaryPressureUpdateKernel.hpp | 73 +++ .../ImmiscibleMultiphaseKernels.hpp | 550 ++++++++++++++++-- 11 files changed, 1020 insertions(+), 46 deletions(-) create mode 100644 src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/CapillaryPressureUpdateKernel.hpp diff --git a/src/coreComponents/constitutive/capillaryPressure/JFunctionCapillaryPressure.cpp b/src/coreComponents/constitutive/capillaryPressure/JFunctionCapillaryPressure.cpp index 3e67db4b27b..1a080cb7652 100644 --- a/src/coreComponents/constitutive/capillaryPressure/JFunctionCapillaryPressure.cpp +++ b/src/coreComponents/constitutive/capillaryPressure/JFunctionCapillaryPressure.cpp @@ -120,6 +120,11 @@ JFunctionCapillaryPressure::JFunctionCapillaryPressure( std::string const & name registerWrapper( viewKeyStruct::jFunctionWrappersString(), &m_jFuncKernelWrappers ). setSizedFromParent( 0 ). setRestartFlags( RestartFlags::NO_WRITE ); + + registerWrapper( viewKeyStruct::inverseJFunctionWrappersString(), &m_inverseJFuncKernelWrappers ). + setSizedFromParent( 0 ). + setRestartFlags( RestartFlags::NO_WRITE ); + } void JFunctionCapillaryPressure::postInputInitialization() @@ -185,6 +190,7 @@ void JFunctionCapillaryPressure::initializePreSubGroups() ? true // pc on the gas phase, function must be increasing : false; // pc on the water phase, function must be decreasing TableCapillaryPressureHelpers::validateCapillaryPressureTable( jFuncTable, getFullName(), jFuncMustBeIncreasing ); + } else if( numPhases == 3 ) { @@ -203,6 +209,7 @@ void JFunctionCapillaryPressure::initializePreSubGroups() InputError ); TableFunction const & jFuncTableNWI = functionManager.getGroup< TableFunction >( m_nonWettingIntermediateJFuncTableName ); TableCapillaryPressureHelpers::validateCapillaryPressureTable( jFuncTableNWI, getFullName(), true ); + } } @@ -298,23 +305,64 @@ void JFunctionCapillaryPressure::createAllTableKernelWrappers() // we want to make sure that the wrappers are always up-to-date, so we recreate them everytime m_jFuncKernelWrappers.clear(); + m_inverseJFuncKernelWrappers.clear(); + if( numPhases == 2 ) { + TableFunction const & jFuncTable = functionManager.getGroup< TableFunction >( m_wettingNonWettingJFuncTableName ); m_jFuncKernelWrappers.emplace_back( jFuncTable.createKernelWrapper() ); + + auto const & satArrayView = jFuncTable.getCoordinates()[0]; + auto const & jArrayView = jFuncTable.getValues(); + + std::vector satVec( satArrayView.size() ); + std::vector jVec( jArrayView.size() ); + + std::copy( satArrayView.begin(), satArrayView.end(), satVec.begin() ); + std::copy( jArrayView.begin(), jArrayView.end(), jVec.begin() ); + + // Reverse both arrays (if original J is decreasing in S) +std::reverse( jVec.begin(), jVec.end() ); +std::reverse( satVec.begin(), satVec.end() ); + + +auto inverseTable = std::make_shared( "inverseJFunc", this ); + +real64_array invJVec( jVec.size() ); +real64_array invSatVec( satVec.size() ); +std::copy( jVec.begin(), jVec.end(), invJVec.data() ); +std::copy( satVec.begin(), satVec.end(), invSatVec.data() ); + +array1d< real64_array > coordinates; +coordinates.emplace_back( std::move( invJVec ) ); + + +std::vector< units::Unit > dimUnits = { units::Unknown }; // or actual unit if available + +inverseTable->setTableCoordinates( coordinates, dimUnits ); +inverseTable->setTableValues( std::move( invSatVec ), units::Unknown ); +inverseTable->setInterpolationMethod( TableFunction::InterpolationType::Linear ); + +m_inverseJFuncKernelWrappers.emplace_back( inverseTable->createKernelWrapper() ); +m_inverseTables.emplace_back( std::move( inverseTable ) ); + } else if( numPhases == 3 ) { // the assumption used everywhere in this class is that the WI information comes before the NWI information TableFunction const & jFuncTableWI = functionManager.getGroup< TableFunction >( m_wettingIntermediateJFuncTableName ); m_jFuncKernelWrappers.emplace_back( jFuncTableWI.createKernelWrapper() ); + m_inverseJFuncKernelWrappers.emplace_back( jFuncTableWI.createKernelWrapper() ); TableFunction const & jFuncTableNWI = functionManager.getGroup< TableFunction >( m_nonWettingIntermediateJFuncTableName ); m_jFuncKernelWrappers.emplace_back( jFuncTableNWI.createKernelWrapper() ); + m_inverseJFuncKernelWrappers.emplace_back( jFuncTableNWI.createKernelWrapper() ); } } JFunctionCapillaryPressure::KernelWrapper:: KernelWrapper( arrayView1d< TableFunction::KernelWrapper const > const & jFuncKernelWrappers, + arrayView1d< TableFunction::KernelWrapper const > const & inverseJFuncKernelWrappers, arrayView2d< real64 const > const & jFuncMultiplier, arrayView1d< integer const > const & phaseTypes, arrayView1d< integer const > const & phaseOrder, @@ -325,6 +373,7 @@ JFunctionCapillaryPressure::KernelWrapper:: phaseCapPres, dPhaseCapPres_dPhaseVolFrac ), m_jFuncKernelWrappers( jFuncKernelWrappers ), + m_inverseJFuncKernelWrappers( inverseJFuncKernelWrappers ), m_jFuncMultiplier( jFuncMultiplier ) {} @@ -333,6 +382,7 @@ JFunctionCapillaryPressure::createKernelWrapper() { createAllTableKernelWrappers(); return KernelWrapper( m_jFuncKernelWrappers, + m_inverseJFuncKernelWrappers, m_jFuncMultiplier, m_phaseTypes, m_phaseOrder, diff --git a/src/coreComponents/constitutive/capillaryPressure/JFunctionCapillaryPressure.hpp b/src/coreComponents/constitutive/capillaryPressure/JFunctionCapillaryPressure.hpp index 55f099e24fa..a7a27d14fcd 100644 --- a/src/coreComponents/constitutive/capillaryPressure/JFunctionCapillaryPressure.hpp +++ b/src/coreComponents/constitutive/capillaryPressure/JFunctionCapillaryPressure.hpp @@ -65,6 +65,7 @@ class JFunctionCapillaryPressure : public CapillaryPressureBase public: KernelWrapper( arrayView1d< TableFunction::KernelWrapper const > const & jFuncKernelWrappers, + arrayView1d< TableFunction::KernelWrapper const > const & inverseJFuncKernelWrappers, arrayView2d< real64 const > const & jFuncMultiplier, arrayView1d< integer const > const & phaseTypes, arrayView1d< integer const > const & phaseOrder, @@ -77,6 +78,13 @@ class JFunctionCapillaryPressure : public CapillaryPressureBase arraySlice1d< real64, cappres::USD_CAPPRES - 2 > const & phaseCapPres, arraySlice2d< real64, cappres::USD_CAPPRES_DS - 2 > const & dPhaseCapPres_dPhaseVolFrac ) const; + GEOS_HOST_DEVICE + void computeInv( arraySlice1d< real64, compflow::USD_PHASE - 1 > const & phaseVolFraction, + arraySlice1d< real64 const > const & jFuncMultiplier, + arraySlice1d< real64 const, cappres::USD_CAPPRES - 2 > const & phaseCapPres, + arraySlice2d< real64, cappres::USD_CAPPRES_DS - 2 > const & dPhaseCapPres_dPhaseVolFrac ) const; + + GEOS_HOST_DEVICE virtual void update( localIndex const k, localIndex const q, @@ -87,6 +95,7 @@ class JFunctionCapillaryPressure : public CapillaryPressureBase /// Array of kernel wrappers for the J-function /// Is of size 1 for two-phase flow, and of size 2 for three-phase flow arrayView1d< TableFunction::KernelWrapper const > const m_jFuncKernelWrappers; + arrayView1d< TableFunction::KernelWrapper const > const m_inverseJFuncKernelWrappers; /// Array of cell-wise J-function multipliers /// The second dimension is of size 1 for two-phase flow, and of size 2 for three-phase flow @@ -113,6 +122,7 @@ class JFunctionCapillaryPressure : public CapillaryPressureBase static constexpr char const * permeabilityExponentString() { return "permeabilityExponent"; } static constexpr char const * permeabilityDirectionString() { return "permeabilityDirection"; } static constexpr char const * jFunctionWrappersString() { return "jFunctionWrappers"; } + static constexpr char const * inverseJFunctionWrappersString() { return "inverseJFunctionWrappers"; } }; /** @@ -170,6 +180,9 @@ class JFunctionCapillaryPressure : public CapillaryPressureBase /// J-function kernel wrapper for the first pair (wetting-intermediate if NP=3, wetting-non-wetting otherwise) array1d< TableFunction::KernelWrapper > m_jFuncKernelWrappers; + array1d< TableFunction::KernelWrapper > m_inverseJFuncKernelWrappers; + + std::vector< std::shared_ptr > m_inverseTables; }; @@ -244,6 +257,41 @@ JFunctionCapillaryPressure::KernelWrapper:: } } +GEOS_HOST_DEVICE +inline void +JFunctionCapillaryPressure::KernelWrapper:: + computeInv( arraySlice1d< real64, compflow::USD_PHASE - 1 > const & phaseVolFraction, + arraySlice1d< real64 const > const & jFuncMultiplier, + arraySlice1d< real64 const, cappres::USD_CAPPRES - 2 > const & phaseCapPres, + arraySlice2d< real64, cappres::USD_CAPPRES_DS - 2 > const & dPhaseCapPres_dPhaseVolFrac ) const +{ + LvArray::forValuesInSlice( dPhaseCapPres_dPhaseVolFrac, []( real64 & val ){ val = 0.0; } ); + + using PT = CapillaryPressureBase::PhaseType; + integer const ipWater = m_phaseOrder[PT::WATER]; + integer const ipOil = m_phaseOrder[PT::OIL]; + integer const ipGas = m_phaseOrder[PT::GAS]; + + // apply multiplier + real64 capPresWater_J = phaseCapPres[ipWater] / jFuncMultiplier[0]; + // std::cout << GEOS_FMT( " JM_2 = ( {:4.2e} )", jFuncMultiplier[0] ); + array1d input(1); + input[0] = capPresWater_J; + // std::cout << GEOS_FMT( " J_int2 = ( {:4.2e} )", input[0] ); + // std::cout << GEOS_FMT( " Pc_int2 = ( {:4.2e} )", phaseCapPres[ipWater] ); + auto inputSlice = input.toSliceConst(); + + + + phaseVolFraction[ipWater] = + m_inverseJFuncKernelWrappers[0].compute( inputSlice, + &(dPhaseCapPres_dPhaseVolFrac)[ipWater][ipWater] ); + dPhaseCapPres_dPhaseVolFrac[ipWater][ipWater] /= jFuncMultiplier[0]; + // std::cout << GEOS_FMT( " S_int2 = ( {:4.2e} )", phaseVolFraction[ipWater] ); + // std::cout << GEOS_FMT( " dS/dP = ( {:4.2e} )", dPhaseCapPres_dPhaseVolFrac[ipWater][ipWater] ); + phaseVolFraction[ipGas] = 1.0 - phaseVolFraction[ipWater]; +} + GEOS_HOST_DEVICE inline void JFunctionCapillaryPressure::KernelWrapper:: diff --git a/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressure.hpp b/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressure.hpp index 739b9993083..602946c55de 100644 --- a/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressure.hpp +++ b/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressure.hpp @@ -65,6 +65,12 @@ class TableCapillaryPressure : public CapillaryPressureBase arraySlice1d< real64, cappres::USD_CAPPRES - 2 > const & phaseCapPres, arraySlice2d< real64, cappres::USD_CAPPRES_DS - 2 > const & dPhaseCapPres_dPhaseVolFrac ) const; + GEOS_HOST_DEVICE + void computeInv( arraySlice1d< real64, compflow::USD_PHASE - 1 > const & phaseVolFraction, + arraySlice1d< real64 const, cappres::USD_CAPPRES - 2 > const & phaseCapPres, + arraySlice2d< real64, cappres::USD_CAPPRES_DS - 2 > const & dPhaseCapPres_dPhaseVolFrac ) const; + + GEOS_HOST_DEVICE virtual void update( localIndex const k, localIndex const q, @@ -173,6 +179,28 @@ TableCapillaryPressure::KernelWrapper:: } } +GEOS_HOST_DEVICE +inline void +TableCapillaryPressure::KernelWrapper:: + computeInv( arraySlice1d< real64, compflow::USD_PHASE - 1 > const & phaseVolFraction, + arraySlice1d< real64 const, cappres::USD_CAPPRES - 2 > const & phaseCapPres, + arraySlice2d< real64, cappres::USD_CAPPRES_DS - 2 > const & dPhaseCapPres_dPhaseVolFrac ) const +{ + LvArray::forValuesInSlice( dPhaseCapPres_dPhaseVolFrac, []( real64 & val ){ val = 0.0; } ); + + using PT = CapillaryPressureBase::PhaseType; + integer const ipWater = m_phaseOrder[PT::WATER]; + // integer const ipOil = m_phaseOrder[PT::OIL]; + // integer const ipGas = m_phaseOrder[PT::GAS]; + + // put capillary pressure on the wetting phase + + phaseVolFraction[ipWater] = + m_capPresKernelWrappers[0].compute( &(phaseCapPres)[ipWater], + &(dPhaseCapPres_dPhaseVolFrac)[ipWater][ipWater] ); + +} + GEOS_HOST_DEVICE inline void TableCapillaryPressure::KernelWrapper:: diff --git a/src/coreComponents/constitutive/capillaryPressure/capillaryPressureSelector.hpp b/src/coreComponents/constitutive/capillaryPressure/capillaryPressureSelector.hpp index b164f55aa16..90c362850b6 100644 --- a/src/coreComponents/constitutive/capillaryPressure/capillaryPressureSelector.hpp +++ b/src/coreComponents/constitutive/capillaryPressure/capillaryPressureSelector.hpp @@ -36,20 +36,24 @@ template< typename LAMBDA > void constitutiveUpdatePassThru( CapillaryPressureBase const & capPres, LAMBDA && lambda ) { - ConstitutivePassThruHandler< BrooksCoreyCapillaryPressure, + ConstitutivePassThruHandler< + BrooksCoreyCapillaryPressure, JFunctionCapillaryPressure, TableCapillaryPressure, - VanGenuchtenCapillaryPressure >::execute( capPres, std::forward< LAMBDA >( lambda ) ); + VanGenuchtenCapillaryPressure + >::execute( capPres, std::forward< LAMBDA >( lambda ) ); } template< typename LAMBDA > void constitutiveUpdatePassThru( CapillaryPressureBase & capPres, LAMBDA && lambda ) { - ConstitutivePassThruHandler< BrooksCoreyCapillaryPressure, + ConstitutivePassThruHandler< + BrooksCoreyCapillaryPressure, JFunctionCapillaryPressure, TableCapillaryPressure, - VanGenuchtenCapillaryPressure >::execute( capPres, std::forward< LAMBDA >( lambda ) ); + VanGenuchtenCapillaryPressure + >::execute( capPres, std::forward< LAMBDA >( lambda ) ); } } // namespace constitutive diff --git a/src/coreComponents/finiteVolume/CellElementStencilTPFA.hpp b/src/coreComponents/finiteVolume/CellElementStencilTPFA.hpp index 88fa3bb2b27..391d614baba 100644 --- a/src/coreComponents/finiteVolume/CellElementStencilTPFA.hpp +++ b/src/coreComponents/finiteVolume/CellElementStencilTPFA.hpp @@ -70,6 +70,20 @@ class CellElementStencilTPFAWrapper : public StencilWrapperBase< TwoPointStencil CoefficientAccessor< arrayView3d< real64 const > > const & dCoeff_dVar, real64 ( &weight )[1][2], real64 ( &dWeight_dVar )[1][2] ) const; +/** + * @brief Compute half weights and derivatives w.r.t to one variable. + * @param[in] iconn connection index + * @param[in] coefficient view accessor to the coefficient used to compute the weights + * @param[in] dCoeff_dVar view accessor to the derivative of the coefficient w.r.t to the variable + * @param[out] weight view weights + * @param[out] dWeight_dVar derivative of the weights w.r.t to the variable + */ + GEOS_HOST_DEVICE + void computeHalfWeights( localIndex const iconn, + CoefficientAccessor< arrayView3d< real64 const > > const & coefficient, + CoefficientAccessor< arrayView3d< real64 const > > const & dCoeff_dVar, + real64 ( &weight )[1][2], + real64 ( &dWeight_dVar )[1][2] ) const; /** * @brief Compute weights and derivatives w.r.t to one variable without coefficient @@ -293,6 +307,90 @@ CellElementStencilTPFAWrapper:: } } +GEOS_HOST_DEVICE +inline void +CellElementStencilTPFAWrapper:: + computeHalfWeights( localIndex const iconn, + CoefficientAccessor< arrayView3d< real64 const > > const & coefficient, + CoefficientAccessor< arrayView3d< real64 const > > const & dCoeff_dVar, + real64 (& weight)[1][2], + real64 (& dWeight_dVar )[1][2] ) const +{ + real64 halfWeight[2]; + real64 dHalfWeight_dVar[2]; + + // real64 const tolerance = 1e-30 * lengthTolerance; // TODO: choice of constant based on physics? + + for( localIndex i = 0; i < 2; ++i ) + { + localIndex const er = m_elementRegionIndices[iconn][i]; + localIndex const esr = m_elementSubRegionIndices[iconn][i]; + localIndex const ei = m_elementIndices[iconn][i]; + + halfWeight[i] = m_weights[iconn][i]; + dHalfWeight_dVar[i] = m_weights[iconn][i]; + + // Proper computation + real64 faceNormal[3]; + LvArray::tensorOps::copy< 3 >( faceNormal, m_faceNormal[iconn] ); + if( LvArray::tensorOps::AiBi< 3 >( m_cellToFaceVec[iconn][i], faceNormal ) < 0.0 ) + { + LvArray::tensorOps::scale< 3 >( faceNormal, -1 ); + } + + real64 faceConormal[3]; + real64 dFaceConormal_dVar[3]; + LvArray::tensorOps::hadamardProduct< 3 >( faceConormal, coefficient[er][esr][ei][0], faceNormal ); + LvArray::tensorOps::hadamardProduct< 3 >( dFaceConormal_dVar, dCoeff_dVar[er][esr][ei][0], faceNormal ); + halfWeight[i] *= LvArray::tensorOps::AiBi< 3 >( m_cellToFaceVec[iconn][i], faceConormal ); + dHalfWeight_dVar[i] *= LvArray::tensorOps::AiBi< 3 >( m_cellToFaceVec[iconn][i], dFaceConormal_dVar ); + + // correct negative weight issue arising from non-K-orthogonal grids + // if( halfWeight[i] < 0.0 ) + // { + // LvArray::tensorOps::hadamardProduct< 3 >( faceConormal, + // coefficient[er][esr][ei][0], + // m_cellToFaceVec[iconn][i] ); + // LvArray::tensorOps::hadamardProduct< 3 >( dFaceConormal_dVar, + // dCoeff_dVar[er][esr][ei][0], + // m_cellToFaceVec[iconn][i] ); + // halfWeight[i] = m_weights[iconn][i]; + // dHalfWeight_dVar[i] = m_weights[iconn][i]; + // halfWeight[i] *= LvArray::tensorOps::AiBi< 3 >( m_cellToFaceVec[iconn][i], faceConormal ); + // dHalfWeight_dVar[i] *= LvArray::tensorOps::AiBi< 3 >( m_cellToFaceVec[iconn][i], dFaceConormal_dVar ); + // } + } + + // // Do harmonic and arithmetic averaging + // real64 const product = halfWeight[0]*halfWeight[1]; + // real64 const sum = halfWeight[0]+halfWeight[1]; + + // real64 const harmonicWeight = sum > 0 ? product / sum : 0.0; + // real64 const arithmeticWeight = sum / 2; + + // real64 dHarmonicWeight_dVar[2]; + // real64 dArithmeticWeight_dVar[2]; + + // dHarmonicWeight_dVar[0] = sum > 0 ? (dHalfWeight_dVar[0]*sum*halfWeight[1] - dHalfWeight_dVar[0]*halfWeight[0]*halfWeight[1]) / ( sum*sum ) : 0.0; + // dHarmonicWeight_dVar[1] = sum > 0 ? (dHalfWeight_dVar[1]*sum*halfWeight[0] - dHalfWeight_dVar[1]*halfWeight[1]*halfWeight[0]) / ( sum*sum ) : 0.0; + + // dArithmeticWeight_dVar[0] = dHalfWeight_dVar[0] / 2; + // dArithmeticWeight_dVar[1] = dHalfWeight_dVar[1] / 2; + + // real64 const meanPermCoeff = 1.0; //TODO make it a member if it is really necessary + + // real64 const value = meanPermCoeff * harmonicWeight + (1 - meanPermCoeff) * arithmeticWeight; + for( localIndex ke = 0; ke < 2; ++ke ) + { + // weight[0][ke] = m_transMultiplier[iconn] * value * (ke == 0 ? 1 : -1); + weight[0][ke] = m_transMultiplier[iconn] * halfWeight[ke] * (ke == 0 ? 1 : -1); + + // real64 const dValue_dVar = meanPermCoeff * dHarmonicWeight_dVar[ke] + (1 - meanPermCoeff) * dArithmeticWeight_dVar[ke]; + // dWeight_dVar[0][ke] = m_transMultiplier[iconn] * dValue_dVar; + dWeight_dVar[0][ke] = m_transMultiplier[iconn] * dHalfWeight_dVar[ke]; + } +} + GEOS_HOST_DEVICE inline void CellElementStencilTPFAWrapper:: diff --git a/src/coreComponents/finiteVolume/EmbeddedSurfaceToCellStencil.hpp b/src/coreComponents/finiteVolume/EmbeddedSurfaceToCellStencil.hpp index 7f9c1562366..27462c5b516 100644 --- a/src/coreComponents/finiteVolume/EmbeddedSurfaceToCellStencil.hpp +++ b/src/coreComponents/finiteVolume/EmbeddedSurfaceToCellStencil.hpp @@ -98,6 +98,22 @@ class EmbeddedSurfaceToCellStencilWrapper : public StencilWrapperBase< TwoPointS real64 ( &weight )[1][2], real64 ( &dWeight_dVar )[1][2] ) const; + /** + * @brief Compute half weigths and derivatives w.r.t to one variable. + * @param[in] iconn connection index + * @param[in] coefficient view accessor to the coefficient used to compute the weights + * @param[in] dCoeff_dVar view accessor to the derivative of the coefficient w.r.t to the variable + * @param[out] weight view weights + * @param[out] dWeight_dVar derivative of the weigths w.r.t to the variable + */ + + GEOS_HOST_DEVICE + void computeHalfWeights( localIndex const iconn, + CoefficientAccessor< arrayView3d< real64 const > > const & coefficient, + CoefficientAccessor< arrayView3d< real64 const > > const & dCoeff_dVar, + real64 ( &weight )[1][2], + real64 ( &dWeight_dVar )[1][2] ) const; + /** * @brief Compute weigths and derivatives w.r.t to one variable without coefficient * Used in ReactiveCompositionalMultiphaseOBL solver for thermal transmissibility computation: @@ -243,6 +259,42 @@ EmbeddedSurfaceToCellStencilWrapper:: dWeight_dVar[0][1] = ( t0 * dt1 * sumOfTrans - dt1 * t0 * t1 ) / ( sumOfTrans * sumOfTrans ); } +GEOS_HOST_DEVICE +inline void +EmbeddedSurfaceToCellStencilWrapper:: + computeHalfWeights( localIndex iconn, + CoefficientAccessor< arrayView3d< real64 const > > const & coefficient, + CoefficientAccessor< arrayView3d< real64 const > > const & dCoeff_dVar, + real64 ( & weight )[1][2], + real64 ( & dWeight_dVar )[1][2] ) const +{ + localIndex const er0 = m_elementRegionIndices[iconn][0]; + localIndex const esr0 = m_elementSubRegionIndices[iconn][0]; + localIndex const ei0 = m_elementIndices[iconn][0]; + + localIndex const er1 = m_elementRegionIndices[iconn][1]; + localIndex const esr1 = m_elementSubRegionIndices[iconn][1]; + localIndex const ei1 = m_elementIndices[iconn][1]; + + // Will change when implementing collocation points. Will use fracture normal to project the permeability + real64 const t0 = m_weights[iconn][0] * LvArray::tensorOps::l2Norm< 3 >( coefficient[er0][esr0][ei0][0] ); + // We consider the 3rd component of the permeability which is the normal one. + real64 const t1 = m_weights[iconn][1] * coefficient[er1][esr1][ei1][0][2]; + + real64 const sumOfTrans = t0+t1; + real64 const value = t0*t1/sumOfTrans; + + weight[0][0] = value; + weight[0][1] = -value; + + // We consider the 3rd component of the permeability which is the normal one. + real64 const dt0 = m_weights[iconn][0] * dCoeff_dVar[er0][esr0][ei0][0][0]; + real64 const dt1 = m_weights[iconn][1] * dCoeff_dVar[er1][esr1][ei1][0][2]; + + dWeight_dVar[0][0] = ( dt0 * t1 * sumOfTrans - dt0 * t0 * t1 ) / ( sumOfTrans * sumOfTrans ); + dWeight_dVar[0][1] = ( t0 * dt1 * sumOfTrans - dt1 * t0 * t1 ) / ( sumOfTrans * sumOfTrans ); +} + GEOS_HOST_DEVICE inline void EmbeddedSurfaceToCellStencilWrapper:: diff --git a/src/coreComponents/finiteVolume/FaceElementToCellStencil.hpp b/src/coreComponents/finiteVolume/FaceElementToCellStencil.hpp index 3b970bd8b2b..a01a4541e85 100644 --- a/src/coreComponents/finiteVolume/FaceElementToCellStencil.hpp +++ b/src/coreComponents/finiteVolume/FaceElementToCellStencil.hpp @@ -106,6 +106,21 @@ class FaceElementToCellStencilWrapper : public StencilWrapperBase< TwoPointStenc real64 ( &weight )[1][2], real64 ( &dWeight_dVar )[1][2] ) const; +/** + * @brief Compute half weigths and derivatives w.r.t to one variable. + * @param[in] iconn connection index + * @param[in] coefficient view accessor to the coefficient used to compute the weights + * @param[in] dCoeff_dVar view accessor to the derivative of the coefficient w.r.t to the variable + * @param[out] weight view weights + * @param[out] dWeight_dVar derivative of the weigths w.r.t to the variable + */ + GEOS_HOST_DEVICE + void computeHalfWeights( localIndex iconn, + CoefficientAccessor< arrayView3d< real64 const > > const & coefficient, + CoefficientAccessor< arrayView3d< real64 const > > const & dCoeff_dVar, + real64 ( &weight )[1][2], + real64 ( &dWeight_dVar )[1][2] ) const; + /** * @brief Compute weigths and derivatives w.r.t to one variable without coefficient * Used in ReactiveCompositionalMultiphaseOBL solver for thermal transmissibility computation: @@ -289,6 +304,44 @@ inline void FaceElementToCellStencilWrapper:: dWeight_dVar[0][1] = ( t0 * dt1 * sumOfTrans - dt1 * t0 * t1 ) / ( sumOfTrans * sumOfTrans ); } +GEOS_HOST_DEVICE +inline void FaceElementToCellStencilWrapper:: + computeHalfWeights( localIndex const iconn, + CoefficientAccessor< arrayView3d< real64 const > > const & coefficient, + CoefficientAccessor< arrayView3d< real64 const > > const & dCoeff_dVar, + real64 ( & weight )[1][2], + real64 ( & dWeight_dVar )[1][2] ) const +{ + localIndex const er0 = m_elementRegionIndices[iconn][0]; + localIndex const esr0 = m_elementSubRegionIndices[iconn][0]; + localIndex const ei0 = m_elementIndices[iconn][0]; + + localIndex const er1 = m_elementRegionIndices[iconn][1]; + localIndex const esr1 = m_elementSubRegionIndices[iconn][1]; + localIndex const ei1 = m_elementIndices[iconn][1]; + + real64 faceConormal[3]; + + // Will change when implementing collocation points. + LvArray::tensorOps::hadamardProduct< 3 >( faceConormal, coefficient[er0][esr0][ei0][0], m_faceNormal[iconn] ); + real64 const t0 = m_weights[iconn][0] * LvArray::tensorOps::AiBi< 3 >( m_cellToFaceVec[iconn], faceConormal ); + // We consider the 3rd component of the permeability which is the normal one. + real64 const t1 = m_weights[iconn][1] * coefficient[er1][esr1][ei1][0][2]; + + real64 const sumOfTrans = t0+t1; + real64 const value = m_transMultiplier[iconn]*t0*t1/sumOfTrans; + + weight[0][0] = value; + weight[0][1] = -value; + + // We consider the 3rd component of the permeability which is the normal one. + real64 const dt0 = m_weights[iconn][0] * dCoeff_dVar[er0][esr0][ei0][0][0]; + real64 const dt1 = m_weights[iconn][1] * dCoeff_dVar[er1][esr1][ei1][0][2]; + + dWeight_dVar[0][0] = ( dt0 * t1 * sumOfTrans - dt0 * t0 * t1 ) / ( sumOfTrans * sumOfTrans ); + dWeight_dVar[0][1] = ( t0 * dt1 * sumOfTrans - dt1 * t0 * t1 ) / ( sumOfTrans * sumOfTrans ); +} + GEOS_HOST_DEVICE inline void FaceElementToCellStencilWrapper diff --git a/src/coreComponents/finiteVolume/SurfaceElementStencil.hpp b/src/coreComponents/finiteVolume/SurfaceElementStencil.hpp index 69b2a85c08a..a6492187386 100644 --- a/src/coreComponents/finiteVolume/SurfaceElementStencil.hpp +++ b/src/coreComponents/finiteVolume/SurfaceElementStencil.hpp @@ -110,6 +110,21 @@ class SurfaceElementStencilWrapper : public StencilWrapperBase< SurfaceElementSt real64 ( &weight )[maxNumConnections][2], real64 ( &dWeight_dVar )[maxNumConnections][2] ) const; + /** + * @brief Compute weights and derivatives w.r.t to one variable. + * @param[in] iconn connection index + * @param[in] coefficient view accessor to the coefficient used to compute the weights + * @param[in] dCoeff_dVar view accessor to the derivative of the coefficient w.r.t to the variable + * @param[out] weight view weights + * @param[out] dWeight_dVar derivative of the weights w.r.t to the variable + */ + GEOS_HOST_DEVICE + void computeHalfWeights( localIndex iconn, + CoefficientAccessor< arrayView3d< real64 const > > const & coefficient, + CoefficientAccessor< arrayView3d< real64 const > > const & dCoeff_dVar, + real64 ( &weight )[maxNumConnections][2], + real64 ( &dWeight_dVar )[maxNumConnections][2] ) const; + /** * @brief Compute weights and derivatives w.r.t to one variable without coefficient * Used in ReactiveCompositionalMultiphaseOBL solver for thermal transmissibility computation: @@ -364,6 +379,70 @@ SurfaceElementStencilWrapper:: } } +GEOS_HOST_DEVICE +inline void +SurfaceElementStencilWrapper:: + computeHalfWeights( localIndex iconn, + CoefficientAccessor< arrayView3d< real64 const > > const & coefficient, + CoefficientAccessor< arrayView3d< real64 const > > const & dCoeff_dVar, + real64 ( & weight )[maxNumConnections][2], + real64 ( & dWeight_dVar )[maxNumConnections][2] ) const +{ + + real64 sumOfTrans = 0.0; + for( localIndex k=0; k >( dataGroup.size(), capPresWrapper, @@ -622,13 +624,17 @@ void ImmiscibleMultiphaseFlow::assembleFluxTerms( real64 const dt, { mesh.getElemManager().forElementSubRegions( regionNames, [&]( localIndex const, - ElementSubRegionBase & subRegion ) - { + ElementSubRegionBase & subRegion ) // Check if you need this. + { + // Capillary pressure wrapper string const & cappresName = subRegion.getReference< string >( viewKeyStruct::capPressureNamesString() ); - CapillaryPressureBase & capPressure = getConstitutiveModel< CapillaryPressureBase >( subRegion, cappresName ); - constitutive::constitutiveUpdatePassThru( capPressure, [&] ( auto & castedCapPres ) - { - typename TYPEOFREF( castedCapPres ) ::KernelWrapper capPresWrapper = castedCapPres.createKernelWrapper(); + JFunctionCapillaryPressure & capPressure = getConstitutiveModel< JFunctionCapillaryPressure >( subRegion, cappresName ); + JFunctionCapillaryPressure::KernelWrapper capPresWrapper = capPressure.createKernelWrapper(); + + // Relative permeability wrapper + string const & relPermName = subRegion.getReference< string >( viewKeyStruct::relPermNamesString() ); + BrooksCoreyRelativePermeability & relPerm = getConstitutiveModel< BrooksCoreyRelativePermeability >( subRegion, relPermName ); + BrooksCoreyRelativePermeability::KernelWrapper relPermWrapper = relPerm.createKernelWrapper(); fluxApprox.forAllStencils( mesh, [&]( auto & stencil ) { @@ -644,12 +650,13 @@ void ImmiscibleMultiphaseFlow::assembleFluxTerms( real64 const dt, mesh.getElemManager(), stencilWrapper, capPresWrapper, + relPermWrapper, + subRegion, dt, localMatrix.toViewConstSizes(), localRhs.toView() ); } ); } ); - } ); } else { diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/CapillaryPressureUpdateKernel.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/CapillaryPressureUpdateKernel.hpp new file mode 100644 index 00000000000..2a02f536ea9 --- /dev/null +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/CapillaryPressureUpdateKernel.hpp @@ -0,0 +1,73 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 TotalEnergies + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2023-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/** + * @file CapillaryPressureUpdateKernel.hpp + */ + +#ifndef GEOS_PHYSICSSOLVERS_FLUIDFLOW_IMMISCIBLEMULTIPHASE_CAPILLARYPRESSUREUPDATEKERNEL_HPP +#define GEOS_PHYSICSSOLVERS_FLUIDFLOW_IMMISCIBLEMULTIPHASE_CAPILLARYPRESSUREUPDATEKERNEL_HPP + +#include "common/DataTypes.hpp" +#include "common/GEOS_RAJA_Interface.hpp" + +namespace geos +{ + +namespace immiscibleMultiphaseKernels +{ + +/******************************** CapillaryPressureUpdateKernel ********************************/ + +struct CapillaryPressureUpdateKernel +{ + template< typename POLICY, typename CAPPRES_WRAPPER > + static void + launch( localIndex const size, + CAPPRES_WRAPPER const & capPresWrapper, + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const & phaseVolFrac ) + { + forAll< POLICY >( size, [=] GEOS_HOST_DEVICE ( localIndex const k ) + { + for( localIndex q = 0; q < capPresWrapper.numGauss(); ++q ) + { + capPresWrapper.update( k, q, phaseVolFrac[k] ); + } + } ); + } + + template< typename POLICY, typename CAPPRES_WRAPPER > + static void + launch( SortedArrayView< localIndex const > const & targetSet, + CAPPRES_WRAPPER const & capPresWrapper, + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const & phaseVolFrac ) + { + forAll< POLICY >( targetSet.size(), [=] GEOS_HOST_DEVICE ( localIndex const a ) + { + localIndex const k = targetSet[a]; + for( localIndex q = 0; q < capPresWrapper.numGauss(); ++q ) + { + capPresWrapper.update( k, q, phaseVolFrac[k] ); + } + } ); + } +}; + +} // namespace immiscibleMultiphaseKernels + +} // namespace geos + + +#endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_IMMISCIBLEMULTIPHASE_CAPILLARYPRESSUREUPDATEKERNEL_HPP diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp index ef3b45ce09b..fa6b6f69d17 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp @@ -32,12 +32,15 @@ #include "constitutive/fluid/twophasefluid/TwoPhaseFluidFields.hpp" #include "constitutive/capillaryPressure/CapillaryPressureFields.hpp" #include "constitutive/capillaryPressure/CapillaryPressureBase.hpp" +#include "constitutive/capillaryPressure/JFunctionCapillaryPressure.hpp" +#include "constitutive/capillaryPressure/TableCapillaryPressure.hpp" #include "constitutive/permeability/PermeabilityBase.hpp" #include "constitutive/permeability/PermeabilityFields.hpp" #include "constitutive/relativePermeability/RelativePermeabilityBase.hpp" #include "constitutive/relativePermeability/RelativePermeabilityFields.hpp" #include "fieldSpecification/AquiferBoundaryCondition.hpp" #include "finiteVolume/BoundaryStencil.hpp" +#include "finiteVolume/CellElementStencilTPFA.hpp" #include "finiteVolume/FluxApproximationBase.hpp" #include "linearAlgebra/interfaces/InterfaceTypes.hpp" #include "physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp" @@ -103,12 +106,15 @@ class FaceBasedAssemblyKernelBase using MultiphaseFluidAccessors = StencilMaterialAccessors< constitutive::TwoPhaseFluid, fields::twophasefluid::phaseDensity, - fields::twophasefluid::dPhaseDensity >; + fields::twophasefluid::dPhaseDensity, + fields::twophasefluid::phaseViscosity, + fields::twophasefluid::dPhaseViscosity >; using CapPressureAccessors = - StencilMaterialAccessors< CapillaryPressureBase, + StencilMaterialAccessors< JFunctionCapillaryPressure, fields::cappres::phaseCapPressure, - fields::cappres::dPhaseCapPressure_dPhaseVolFraction >; + fields::cappres::dPhaseCapPressure_dPhaseVolFraction, + fields::cappres::jFuncMultiplier >; using PermeabilityAccessors = StencilMaterialAccessors< PermeabilityBase, @@ -158,9 +164,12 @@ class FaceBasedAssemblyKernelBase m_mob( multiPhaseFlowAccessors.get( fields::immiscibleMultiphaseFlow::phaseMobility {} ) ), m_dMob( multiPhaseFlowAccessors.get( fields::immiscibleMultiphaseFlow::dPhaseMobility {} ) ), m_dens( fluidAccessors.get( fields::twophasefluid::phaseDensity {} ) ), + m_visc( fluidAccessors.get( fields::twophasefluid::phaseViscosity {} ) ), m_dDens_dPres( fluidAccessors.get( fields::twophasefluid::dPhaseDensity {} ) ), + m_dVisc_dPres( fluidAccessors.get( fields::twophasefluid::dPhaseViscosity {} ) ), m_phaseCapPressure( capPressureAccessors.get( fields::cappres::phaseCapPressure {} ) ), m_dPhaseCapPressure_dPhaseVolFrac( capPressureAccessors.get( fields::cappres::dPhaseCapPressure_dPhaseVolFraction {} ) ), + m_jFuncMultiplier( capPressureAccessors.get( fields::cappres::jFuncMultiplier {} ) ), m_localMatrix( localMatrix ), m_localRhs( localRhs ), m_hasCapPressure ( hasCapPressure ), @@ -199,16 +208,20 @@ class FaceBasedAssemblyKernelBase ElementViewConst< arrayView2d< real64 const, immiscibleFlow::USD_PHASE > > const m_mob; ElementViewConst< arrayView3d< real64 const, immiscibleFlow::USD_PHASE_DS > > const m_dMob; - /// Views on fluid density + /// Views on fluid density and viscosity ElementViewConst< arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > > const m_dens; + ElementViewConst< arrayView3d< real64 const, constitutive::multifluid::USD_PHASE > > const m_visc; ElementViewConst< arrayView4d< real64 const, constitutive::multifluid::USD_PHASE_DC > > const m_dDens_dPres; + ElementViewConst< arrayView4d< real64 const, constitutive::multifluid::USD_PHASE_DC > > const m_dVisc_dPres; /// Views on capillary pressure ElementViewConst< arrayView3d< real64 const, cappres::USD_CAPPRES > > const m_phaseCapPressure; ElementViewConst< arrayView4d< real64 const, cappres::USD_CAPPRES_DS > > const m_dPhaseCapPressure_dPhaseVolFrac; + ElementViewConst< arrayView2d< real64 const > > const m_jFuncMultiplier; // Residual and jacobian + /// View on the local CRS matrix CRSMatrixView< real64, globalIndex const > const m_localMatrix; /// View on the local RHS @@ -334,6 +347,11 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase /// Derivatives of transmissibility with respect to pressure real64 dTrans_dPres[maxNumConns][2]{}; + /// Transmissibility + real64 transmissibilityHat[maxNumConns][2]{}; + /// Derivatives of transmissibility with respect to pressure + real64 dTransHat_dPres[maxNumConns][2]{}; + // Local degrees of freedom and local residual/jacobian /// Indices of the matrix rows/columns corresponding to the dofs in this face @@ -751,14 +769,16 @@ class FaceBasedAssemblyKernel : public FaceBasedAssemblyKernelBase typename STENCILWRAPPER::IndexContainerViewConstType const m_sei; }; + /** * @class FaceBasedAssemblyInterfaceConditionKernel * @tparam NUM_DOF number of degrees of freedom * @tparam STENCILWRAPPER the type of the stencil wrapper * @tparam CAPPRESWRAPPER the type of the capillary pressure wrapper + * @tparam RELPERMWRAPPER the type of the realtive permeability wrapper * @brief Define the interface for the assembly kernel in charge of flux terms */ -template< integer NUM_EQN, integer NUM_DOF, typename STENCILWRAPPER, typename CAPPRESWRAPPER > +template< integer NUM_EQN, integer NUM_DOF, typename STENCILWRAPPER, typename CAPPRESWRAPPER, typename RELPERMWRAPPER > class FaceBasedAssemblyInterfaceConditionKernel : public FaceBasedAssemblyKernel< NUM_EQN, NUM_DOF, STENCILWRAPPER > { public: @@ -785,9 +805,12 @@ class FaceBasedAssemblyInterfaceConditionKernel : public FaceBasedAssemblyKernel using Base::m_dPerm_dPres; using Base::m_phaseVolFrac; using Base::m_phaseCapPressure; + using Base::m_jFuncMultiplier; using Base::m_dPhaseCapPressure_dPhaseVolFrac; using Base::m_dens; using Base::m_dDens_dPres; + using Base::m_visc; + using Base::m_dVisc_dPres; using Base::m_dMob; using Base::m_mob; using Base::m_gravCoef; @@ -822,6 +845,7 @@ class FaceBasedAssemblyInterfaceConditionKernel : public FaceBasedAssemblyKernel globalIndex const rankOffset, STENCILWRAPPER const & stencilWrapper, CAPPRESWRAPPER const & capPressureWrapper, + RELPERMWRAPPER const & relPermWrapper, DofNumberAccessor const & dofNumberAccessor, ImmiscibleMultiphaseFlowAccessors const & multiPhaseFlowAccessors, MultiphaseFluidAccessors const & fluidAccessors, @@ -832,7 +856,8 @@ class FaceBasedAssemblyInterfaceConditionKernel : public FaceBasedAssemblyKernel arrayView1d< real64 > const & localRhs, integer const hasCapPressure, integer const useTotalMassEquation, - integer const checkPhasePresenceInGravity ) + integer const checkPhasePresenceInGravity, + localIndex const GEOS_UNUSED_PARAM(domainSize) ) : Base( numPhases, rankOffset, stencilWrapper, @@ -847,7 +872,8 @@ class FaceBasedAssemblyInterfaceConditionKernel : public FaceBasedAssemblyKernel hasCapPressure, useTotalMassEquation, checkPhasePresenceInGravity ), - m_capPressureWrapper( capPressureWrapper ) + m_capPressureWrapper( capPressureWrapper ), + m_relPermWrapper( relPermWrapper ) {} /** @@ -857,6 +883,7 @@ class FaceBasedAssemblyInterfaceConditionKernel : public FaceBasedAssemblyKernel * @param[inout] stack the stack variables * @param[in] NoOpFunc the function used to customize the computation of the flux */ + template< typename FUNC = NoOpFunc > // should change to multiphase GEOS_HOST_DEVICE void computeFlux( localIndex const iconn, @@ -874,6 +901,12 @@ class FaceBasedAssemblyInterfaceConditionKernel : public FaceBasedAssemblyKernel localIndex k[2]; localIndex connectionIndex = 0; + m_stencilWrapper.computeHalfWeights( iconn, + m_permeability, + m_dPerm_dPres, + stack.transmissibilityHat, + stack.dTransHat_dPres ); + for( k[0] = 0; k[0] < stack.numFluxElems; ++k[0] ) { for( k[1] = k[0] + 1; k[1] < stack.numFluxElems; ++k[1] ) @@ -890,6 +923,7 @@ class FaceBasedAssemblyInterfaceConditionKernel : public FaceBasedAssemblyKernel real64 capGrad[numEqn]{}; real64 capPresIC[numEqn][2]{}; + real64 jFMultiplier[numEqn][2]{}; real64 dCapGrad_dP[numEqn][2]{}; real64 dCapGrad_dS[numEqn][2]{}; @@ -903,14 +937,22 @@ class FaceBasedAssemblyInterfaceConditionKernel : public FaceBasedAssemblyKernel real64 density2[numEqn]{}; real64 dDens_dP2[numEqn][2]{}; + real64 gravCoefHat[numEqn]{}; real64 uT = 0; + real64 total_mobility = 0; real64 duT_dP[numEqn]{}; real64 duT_dS[numEqn]{}; + real64 potGrad_ip[numEqn]{}; + real64 alpha_ip[numEqn]{}; + real64 const trans[2] = { stack.transmissibility[connectionIndex][0], stack.transmissibility[connectionIndex][1] }; real64 const dTrans_dP[2] = { stack.dTrans_dPres[connectionIndex][0], stack.dTrans_dPres[connectionIndex][1] }; + real64 const transHat[2] = { stack.transmissibilityHat[connectionIndex][0], stack.transmissibilityHat[connectionIndex][1] }; + real64 const dTransHat_dP[2] = { stack.dTransHat_dPres[connectionIndex][0], stack.dTransHat_dPres[connectionIndex][1] }; + // cell indices localIndex const seri[2] = {m_seri( iconn, k[0] ), m_seri( iconn, k[1] )}; localIndex const sesri[2] = {m_sesri( iconn, k[0] ), m_sesri( iconn, k[1] )}; @@ -956,6 +998,8 @@ class FaceBasedAssemblyInterfaceConditionKernel : public FaceBasedAssemblyKernel real64 dPresGrad_dTrans = 0.0; real64 dGravHead_dTrans = 0.0; real64 dCapGrad_dTrans = 0.0; + gravCoefHat[0] = 0; + gravCoefHat[1] = 0; constexpr int signPotDiff[2] = {1, -1}; for( integer ke = 0; ke < 2; ++ke ) @@ -971,6 +1015,8 @@ class FaceBasedAssemblyInterfaceConditionKernel : public FaceBasedAssemblyKernel real64 const gravD = trans[ke] * m_gravCoef[er][esr][ei]; // D = T g z1 || -T g z2 real64 pot = trans[ke] * pressure - densMean[ip] * gravD; // Phi = T P1 - rho T g z1 || -T P2 + rho T g z2 + gravCoefHat[0] += m_gravCoef[er][esr][ei] * 0.5; + gravCoefHat[1] += m_gravCoef[er][esr][ei] * 0.5; gravHead[ip] += densMean[ip] * gravD; // DPg = rho (T g z1 - T g z2) = T rho g (z1 - z2) dGravHead_dTrans += signPotDiff[ke] * densMean[ip] * m_gravCoef[er][esr][ei]; // dDPg/dT = rho g z1 - rho g z2 = rho g (z1 - z2) @@ -983,6 +1029,8 @@ class FaceBasedAssemblyInterfaceConditionKernel : public FaceBasedAssemblyKernel if( m_hasCapPressure ) // check sign convention { real64 const capPres = m_phaseCapPressure[er][esr][ei][0][ip]; // Pc = Pc1 || Pc2 + jFMultiplier[ip][ke] = m_jFuncMultiplier[er][esr][ei][0]; + capPresIC[ip][ke] = capPres; dCapGrad_dTrans -= signPotDiff[ke] * capPres; // dDPc/dT = (-Pc1 + Pc2) pot -= trans[ke] * capPres; // Phi = T P1 - rho T g z1 - T Pc1 || -T P2 + rho T g z2 + T @@ -993,6 +1041,11 @@ class FaceBasedAssemblyInterfaceConditionKernel : public FaceBasedAssemblyKernel potScale = fmax( potScale, fabs( pot ) ); // maxPhi = Phi1 > Phi2 ? Phi1 : Phi2 } + // std::cout << GEOS_FMT( " z1 = ( {:4.2e} )", m_gravCoef[seri[0]][sesri[0]][sei[0]] ); + // std::cout << GEOS_FMT( " z2 = ( {:4.2e} )", m_gravCoef[seri[1]][sesri[1]][sei[1]] ); + // std::cout << GEOS_FMT( " zhat1 = ( {:4.2e} )", gravCoefHat[0] ); + // std::cout << GEOS_FMT( " zhat2 = ( {:4.2e} )", gravCoefHat[1] ); + for( integer ke = 0; ke < 2; ++ke ) { dPresGrad_dP[ip][ke] += dTrans_dP[ke] * dPresGrad_dTrans; // dDPv/dP = { T + dT/dP1 * (P1 - P2) , -T + dT/dP2 * (P1 - P2)} @@ -1027,7 +1080,7 @@ class FaceBasedAssemblyInterfaceConditionKernel : public FaceBasedAssemblyKernel // maxPhi * tol : eps // decide mobility coefficients - smooth variation in [-upwAbsTol; upwAbsTol] - real64 const alpha = ( potGrad + upwAbsTol ) / ( 2 * upwAbsTol ); // alpha = (DPhi + abstol) / abstol / 2 + real64 alpha = ( potGrad + upwAbsTol ) / ( 2 * upwAbsTol ); // alpha = (DPhi + abstol) / abstol / 2 // choose upstream cell if( alpha <= 0.0 || alpha >= 1.0 ) // no smoothing needed @@ -1123,7 +1176,13 @@ class FaceBasedAssemblyInterfaceConditionKernel : public FaceBasedAssemblyKernel duT_dS[ke] += dFlux_dS[ip][ke] / density2[ip]; // dF/dS = { M [T * -dPc/dS1] + dM/dS1 * DPhi , M [T * dPc/dS2] + dM/dS2 * DPhi // } } + potGrad_ip[ip] = potGrad; + alpha_ip[ip] = alpha; + + } // loop over phases + if (std::fabs(jFMultiplier[0][0] - jFMultiplier[0][1]) < 1e-8 && std::fabs(jFMultiplier[1][0] - jFMultiplier[1][1]) < 1e-8 ) { + for( integer ip = 0; ip < 2; ++ip ) { // populate local flux vector and derivatives stack.localFlux[k[0]*numEqn + ip] += m_dt * fluxVal[ip]; stack.localFlux[k[1]*numEqn + ip] -= m_dt * fluxVal[ip]; @@ -1142,45 +1201,464 @@ class FaceBasedAssemblyInterfaceConditionKernel : public FaceBasedAssemblyKernel } // Customize the kernel with this lambda - kernelOp( k, seri, sesri, sei, connectionIndex, alpha, mobility, potGrad, fluxVal, dFlux_dP, dFlux_dS ); // Not sure what this - - // does + kernelOp( k, seri, sesri, sei, connectionIndex, alpha_ip[ip], mobility, potGrad_ip[ip], fluxVal, dFlux_dP, dFlux_dS ); // Not sure what this + + }// does + } else { - } // loop over phases + - if( m_hasCapPressure ) - { // std::cout << GEOS_FMT( " uT = ( {:4.2e} )", uT ); // std::cout << GEOS_FMT( " duTdP = ( {:4.2e} )", duT_dP[0] ); // std::cout << GEOS_FMT( " duTdS = ( {:4.2e} )", duT_dS[0] ); - std::cout << GEOS_FMT( " Pc1 = ( {:4.2e} )", capPresIC[0][0] ); - std::cout << GEOS_FMT( " Pc2 = ( {:4.2e} )", capPresIC[0][1] ); - + std::cout << GEOS_FMT( " Pc1 = ( {:4.2e} )", capPresIC[1][0] ); + std::cout << GEOS_FMT( " Pc2 = ( {:4.2e} )", capPresIC[1][1] ); + std::cout << GEOS_FMT( " T1 = ( {:4.2e} )", trans[0] ); + std::cout << GEOS_FMT( " T2 = ( {:4.2e} )", trans[1] ); + std::cout << GEOS_FMT( " That1 = ( {:4.2e} )", transHat[0] ); + std::cout << GEOS_FMT( " That2 = ( {:4.2e} )", transHat[1] ); + // -------------------- Here I implement the interface conditions local solver --------------------- // + // nonlinear solver's parameters + real64 tol = 1.0e-7; + int max_iter = 50; + // initial guess: real64 S_int[numEqn]{}; - real64 const Pc1 = capPresIC[0][0]; - real64 const Pc2 = capPresIC[0][1]; + real64 const Pc1 = capPresIC[1][0]; + real64 const Pc2 = capPresIC[1][1]; + + real64 Pc_int = ( Pc1 + Pc2 ) / 2; + // std::cout << GEOS_FMT( " Pc_int = ( {:4.2e} )", Pc_int ); + // // Local newton loop: + + // Use of the capillary pressure kernel wrapper + + StackArray< real64, 2, 2, immiscibleFlow::LAYOUT_PHASE > facePhaseVolFrac1( 1, 2 ); + StackArray< real64, 3, 2, constitutive::cappres::LAYOUT_CAPPRES > faceCapPres1( 1, 1, 2 ); + StackArray< real64, 4, 4, constitutive::cappres::LAYOUT_CAPPRES_DS > dfacePhaseVolFrac_dCapPres1( 1, 1, 2, 2 ); + StackArray< real64, 2, 2, immiscibleFlow::LAYOUT_PHASE > facePhaseVolFrac2( 1, 2 ); + StackArray< real64, 3, 2, constitutive::cappres::LAYOUT_CAPPRES > faceCapPres2( 1, 1, 2 ); + StackArray< real64, 4, 4, constitutive::cappres::LAYOUT_CAPPRES_DS > dfacePhaseVolFrac_dCapPres2( 1, 1, 2, 2 ); + StackArray< real64, 1, 4> JFunc1( 2 ); + StackArray< real64, 1, 4> JFunc2( 2 ); + + + // Use of the relative permeability kernel wrapper + + StackArray< real64, 3, 2, constitutive::relperm::LAYOUT_RELPERM > faceTrappedVolFrac1( 1, 1, 2 ); + StackArray< real64, 3, 2, constitutive::relperm::LAYOUT_RELPERM > faceRelPerm1( 1, 1, 2 ); + StackArray< real64, 4, 4, constitutive::relperm::LAYOUT_RELPERM_DS > dfacePhaseRelPerm1_dPhaseVolFrac( 1, 1, 2, 2 ); + StackArray< real64, 3, 2, constitutive::relperm::LAYOUT_RELPERM > faceTrappedVolFrac2( 1, 1, 2 ); + StackArray< real64, 3, 2, constitutive::relperm::LAYOUT_RELPERM > faceRelPerm2( 1, 1, 2 ); + StackArray< real64, 4, 4, constitutive::relperm::LAYOUT_RELPERM_DS > dfacePhaseRelPerm2_dPhaseVolFrac( 1, 1, 2, 2 ); + + real64 halfFluxVal[numEqn][2]{}; + real64 dhalfFlux_dP[numEqn][4]{}; + real64 dhalfFlux_dS[numEqn][4]{}; + real64 dhalfFlux_duT[numEqn][2]{}; + + // While loop + int iter = 0; + + + while (iter < max_iter) { + // clear working arrays + + // densMean = {0 , 0}; + // dDensMean_dP[numEqn][0] = {0 , 0}; + // dDensMean_dP[numEqn][1] = {0 , 0}; + + // presGrad[numEqn] = {0 , 0}; + // dPresGrad_dP[numEqn][0] = {0 , 0}; + // dPresGrad_dP[numEqn][1] = {0 , 0}; + + // gravHead[numEqn] = {0 , 0}; + // dGravHead_dP[numEqn][0] = {0 , 0}; + // dGravHead_dP[numEqn][1] = {0 , 0}; + + // capGrad[numEqn] = {0 , 0}; + // capPresIC[numEqn][0] = {0 , 0}; + // capPresIC[numEqn][1] = {0 , 0}; + // dCapGrad_dP[numEqn][0] = {0 , 0}; + // dCapGrad_dP[numEqn][1] = {0 , 0}; + // dCapGrad_dS[numEqn][0] = {0 , 0}; + // dCapGrad_dS[numEqn][1] = {0 , 0}; + // dCapPresIC_dS[numEqn][0] = {0 , 0}; + // dCapPresIC_dS[numEqn][1] = {0 , 0}; + + // fluxVal[numEqn][0] = {0 , 0}; + // fluxVal[numEqn][1] = {0 , 0}; + // dFlux_dP[numEqn][0] = {0 , 0}; + // dFlux_dP[numEqn][1] = {0 , 0}; + // dFlux_dP[numEqn][2] = {0 , 0}; + // dFlux_dP[numEqn][3] = {0 , 0}; + // dFlux_dS[numEqn][0] = {0 , 0}; + // dFlux_dS[numEqn][1] = {0 , 0}; + // dFlux_dS[numEqn][2] = {0 , 0}; + // dFlux_dS[numEqn][3] = {0 , 0}; + + + + real64 density[numEqn]{}; + real64 dDens_dP[numEqn][2]{}; + real64 viscosity[numEqn]{}; + real64 dVisc_dP[numEqn][2]{}; + + // mobility[numEqn] = {0 , 0}; + // dMob_dP[numEqn][0] = {0 , 0}; + // dMob_dP[numEqn][1] = {0 , 0}; + // dMob_dS[numEqn][0] = {0 , 0}; + // dMob_dS[numEqn][1] = {0 , 0}; + + real64 local_residual = 0; + real64 local_jacobian = 0; + + + // Compute the inverse: + faceCapPres1[0][0][1] = Pc_int; + faceCapPres2[0][0][1] = Pc_int; + JFunc1[0] = jFMultiplier[0][0]; + JFunc2[0] = jFMultiplier[0][1]; + + + m_capPressureWrapper.computeInv( facePhaseVolFrac1[0], + JFunc1.toSliceConst(), + faceCapPres1[0][0], + dfacePhaseVolFrac_dCapPres1[0][0]); + + m_capPressureWrapper.computeInv( facePhaseVolFrac2[0], + JFunc2.toSliceConst(), + faceCapPres2[0][0], + dfacePhaseVolFrac_dCapPres2[0][0]); + + // compute relative permeability for both cells: + m_relPermWrapper.compute( facePhaseVolFrac1[0], + faceTrappedVolFrac1[0][0], + faceRelPerm1[0][0], + dfacePhaseRelPerm1_dPhaseVolFrac[0][0]); + + m_relPermWrapper.compute( facePhaseVolFrac2[0], + faceTrappedVolFrac2[0][0], + faceRelPerm2[0][0], + dfacePhaseRelPerm2_dPhaseVolFrac[0][0]); + + + // real64 Sw_alpha = facePhaseVolFrac1[0][0]; + // real64 Sw_beta = facePhaseVolFrac2[0][0]; + // std::cout << GEOS_FMT( " Sw_alpha = ( {:4.2e} )", Sw_alpha ); + // std::cout << GEOS_FMT( " Sw_beta = ( {:4.2e} )", Sw_beta ); + + // real64 Sn_alpha = facePhaseVolFrac1[0][1]; + // real64 Sn_beta = facePhaseVolFrac2[0][1]; + // std::cout << GEOS_FMT( " Sn_alpha = ( {:4.2e} )", Sn_alpha ); + // std::cout << GEOS_FMT( " Sn_beta = ( {:4.2e} )", Sn_beta ); + + // std::cout << GEOS_FMT( " Krw_alpha = ( {:4.2e} )", faceRelPerm1[0][0][0] ); + // std::cout << GEOS_FMT( " Krn_alpha = ( {:4.2e} )", faceRelPerm1[0][0][1] ); + + + + for( integer ix = 0; ix < 2; ++ix ) // for loop for each interface + { + // loop over phases + // clear arrays: + presGrad[0] = 0; + presGrad[1] = 0; + gravHead[0] = 0; + gravHead[1] = 0; + dGravHead_dP[0][0] = 0; + dGravHead_dP[0][1] = 0; + dGravHead_dP[1][0] = 0; + dGravHead_dP[1][1] = 0; + capGrad[0] = 0; + capGrad[1] = 0; + dCapGrad_dP[0][0] = 0; + dCapGrad_dP[1][0] = 0; + dCapGrad_dP[0][1] = 0; + dCapGrad_dP[1][1] = 0; + + for( integer ip = 0; ip < m_numPhases; ++ip ) + { + // calculate quantities on primary connected cells + // density + density[ip] = m_dens[seri[ix]][sesri[ix]][sei[ix]][0][ip]; // r = rho1 || rho2 + dDens_dP[ip][ix] = m_dDens_dPres[seri[ix]][sesri[ix]][sei[ix]][0][ip][Deriv::dP]; // dr/dP = dr1/dP1 || dr2/dP + + viscosity[ip] = m_visc[seri[ix]][sesri[ix]][sei[ix]][0][ip]; // r = rho1 || rho2 + dVisc_dP[ip][ix] = m_dVisc_dPres[seri[ix]][sesri[ix]][sei[ix]][0][ip][Deriv::dP]; // dr/dP = dr1/dP1 || dr2/dP + + densMean[ip] = density[ip]; // rho = (rho1 + rho2) + dDensMean_dP[ip][0] = dDens_dP[ip][ix]; // drho/dP = { (dr1/dP1) , (dr2/dP2) } + dDensMean_dP[ip][1] = dDens_dP[ip][ix]; + + //***** calculation of flux ***** + + // compute potential difference + real64 potScale = 0.0; + real64 dPresGrad_dTrans = 0.0; + real64 dGravHead_dTrans = 0.0; + real64 dCapGrad_dTrans = 0.0; + constexpr int signPotDiff[2] = {1, -1}; + + for( integer ke = 0; ke < 2; ++ke ) + { + localIndex const er = seri[ix]; + localIndex const esr = sesri[ix]; + localIndex const ei = sei[ix]; + + real64 const pressure = m_pres[er][esr][ei]; // P = P1 || P2 + presGrad[ip] += transHat[ix] * pressure; // DPv = T (P1 - P2) + dPresGrad_dTrans += signPotDiff[ke] * pressure; // dDPv/dT = (P1 - P2) + dPresGrad_dP[ip][ke] = transHat[ix]; // dDPv/dP = { T , -T } + + real64 const gravD = transHat[ix] * gravCoefHat[ix]; // D = T g z1 || -T g z2 + real64 pot = transHat[ix] * pressure - densMean[ip] * gravD; // Phi = T P1 - rho T g z1 || -T P2 + rho T g z2 + + gravHead[ip] += densMean[ip] * gravD; // DPg = rho (T g z1 - T g z2) = T rho g (z1 - z2) + dGravHead_dTrans += signPotDiff[ke] * densMean[ip] * gravCoefHat[ix]; // dDPg/dT = rho g z1 - rho g z2 = rho g (z1 - z2) + + for( integer i = 0; i < 2; ++i ) + { + dGravHead_dP[ip][i] += dDensMean_dP[ip][i] * gravD; // dDPg/dP = {drho/dP1 * T g (z1 - z2) , drho/dP2 * T g (z1 - z2)} + } + + if( m_hasCapPressure ) // check sign convention + { + real64 capPres = m_phaseCapPressure[er][esr][ei][0][ip]; // Pc = Pc1 || Pc2 + + if( ke == 1 && ix == 0 ) { + capPres = faceCapPres1[0][0][ip]; + } else if ( ke == 1 && ix == 1 ) { + capPres = faceCapPres2[0][0][ip]; + } + + dCapGrad_dTrans -= signPotDiff[ke] * capPres; // dDPc/dT = (-Pc1 + Pc2) + pot -= transHat[ix] * capPres; // Phi = T P1 - rho T g z1 - T Pc1 || -T P2 + rho T g z2 + T + // Pc2 + capGrad[ip] -= transHat[ix] * capPres; // DPc = T (-Pc1 + Pc2) + } + + potScale = fmax( potScale, fabs( pot ) ); // maxPhi = Phi1 > Phi2 ? Phi1 : Phi2 + } + + for( integer ke = 0; ke < 2; ++ke ) + { + dPresGrad_dP[ip][ke] += dTransHat_dP[ix] * dPresGrad_dTrans; // dDPv/dP = { T + dT/dP1 * (P1 - P2) , -T + dT/dP2 * (P1 - P2)} + dGravHead_dP[ip][ke] += dTransHat_dP[ix] * dGravHead_dTrans; // dDPg/dP = { drho/dP1 * T g (z1 - z2) + dT/dP1 * rho g (z1 - z2) , + // drho/dP2 * T g (z1 - z2) + dT/dP2 * rho g (z1 - z2) } + if( m_hasCapPressure ) + { + real64 constexpr eps = 1e-8; + real64 dCapPres_dS = m_dPhaseCapPressure_dPhaseVolFrac[seri[ix]][sesri[ix]][sei[ix]][0][ip][ip]; // dPc/dS = dPc1/dS1 || + + + if( ke == 1 && ix == 0 ) { + real64 dCapPresIC_dS = dfacePhaseVolFrac_dCapPres1[0][0][ip][ip]; + dCapPres_dS = 1 / ( dCapPresIC_dS + eps); + } else if ( ke == 1 && ix == 1 ) { + real64 dCapPresIC_dS = dfacePhaseVolFrac_dCapPres2[0][0][ip][ip]; + dCapPres_dS = 1 / ( dCapPresIC_dS + eps); + } + // dPc2/dS2 + dCapGrad_dP[ip][ke] += dTransHat_dP[ix] * dCapGrad_dTrans; // dDPc/dP = { dT/dP1 * + // (-Pc1 + Pc2) , + // dT/dP2 * + // (-Pc1 + Pc2) } + dCapGrad_dS[ip][ke] -= transHat[ix] * dCapPres_dS; // dDPc/dS = { -T * + // dPc1/dS1 , T * + // dPc2/dS2 } + } + } + + // *** upwinding *** + + // compute potential gradient + real64 potGrad = presGrad[ip] - gravHead[ip]; // DPhi = T (P1 - P2) - T rho g (z1 - z2) + if( m_hasCapPressure ) + { + potGrad += capGrad[ip]; // DPhi = T (P1 - P2) - T rho g (z1 - z2) + T (-Pc1 + Pc2) + } - real64 const Pc_int = ( Pc1 + Pc2 ) / 2; + // compute upwinding tolerance + real64 constexpr upwRelTol = 1e-8; + real64 const upwAbsTol = fmax( potScale * upwRelTol, LvArray::NumericLimits< real64 >::epsilon ); // abstol = maxPhi * tol > eps ? + // maxPhi * tol : eps - // Local newton loop: + // decide mobility coefficients - smooth variation in [-upwAbsTol; upwAbsTol] + real64 const alpha = ( potGrad + upwAbsTol ) / ( 2 * upwAbsTol ); // alpha = (DPhi + abstol) / abstol / 2 - // compute S_alpha and S_beta: - S_int[0] = computePCalphaInv< arrayView1d< real64 const > >( Pc_int ); - S_int[1] = computePCalphaInv< arrayView1d< real64 const > >( Pc_int ); + // choose upstream cell + // if( alpha <= 0.0 || alpha >= 1.0 ) // no smoothing needed + // { + constexpr int sign[2] = {1, -1}; - real64 S_avg = S_int[0] + S_int[1]; + localIndex const k_up = 1 - localIndex( fmax( fmin( alpha, 1.0 ), 0.0 ) ); // 1 upwind -> k_up = 0 || 2 upwind -> k_up = 1 - // real64 PC_int1 = computePCalphaInv > ( S_int[0] ); - // real64 PC_int2 = computePCalphaInv > ( S_int[1] ); - GEOS_UNUSED_PARAM( S_avg ); + if( k_up == 1 && ix == 0 ) { + + mobility[ip] = faceRelPerm1[0][ip][ip] * density[ip] / viscosity[ip]; // M = Mupstream + dMob_dP[ip][k_up] = mobility[ip] * (dDens_dP[ip][ip] / density[ip] - dVisc_dP[ip][ip] / viscosity[ip]); // dM/dP = {dM/dP1 , 0} OR {0 , dM/dP2} + dMob_dS[ip][k_up] = dfacePhaseRelPerm1_dPhaseVolFrac[0][0][ip][ip] * density[ip] / viscosity[ip]; // dM/dS = {dM/dS1 , 0} OR {0 , dM/dS2} + } else if ( k_up == 1 && ix == 1 ) { + mobility[ip] = faceRelPerm2[0][ip][ip] * density[ip] / viscosity[ip]; // M = Mupstream + dMob_dP[ip][k_up] = mobility[ip] * (dDens_dP[ip][ip] / density[ip] - dVisc_dP[ip][ip] / viscosity[ip]); // dM/dP = {dM/dP1 , 0} OR {0 , dM/dP2} + dMob_dS[ip][k_up] = dfacePhaseRelPerm2_dPhaseVolFrac[0][0][ip][ip] * density[ip] / viscosity[ip]; // dM/dS = {dM/dS1 , 0} OR {0 , dM/dS2} + } else { + mobility[ip] = m_mob[seri[k_up]][sesri[k_up]][sei[k_up]][ip]; // M = Mupstream + dMob_dP[ip][k_up] = m_dMob[seri[k_up]][sesri[k_up]][sei[k_up]][ip][Deriv::dP]; // dM/dP = {dM/dP1 , 0} OR {0 , dM/dP2} + dMob_dS[ip][k_up] = m_dMob[seri[k_up]][sesri[k_up]][sei[k_up]][ip][Deriv::dS]; // dM/dS = {dM/dS1 , 0} OR {0 , dM/dS2} + } + + + // } + // else // perform smoothing + // { + // real64 const mobWeights[2] = { alpha, 1.0 - alpha }; + // for( integer ke = 0; ke < 2; ++ke ) + // { + + // mobility[ip] += mobWeights[ke] * m_mob[seri[ke]][sesri[ke]][sei[ke]][ip]; // M = alpha * M1 + (1 - alpha) * M2 + // density2[ip] += mobWeights[ke] * m_dens[seri[ke]][sesri[ke]][sei[ke]][0][ip]; // r = rho1 || rho2 + // dDens_dP2[ip][ke] = mobWeights[ke] * m_dDens_dPres[seri[ke]][sesri[ke]][sei[ke]][0][ip][Deriv::dP]; // dr/dP = dr1/dP1 || + // // dr2/dP + // dMob_dP[ip][ke] = mobWeights[ke] * m_dMob[seri[ke]][sesri[ke]][sei[ke]][ip][Deriv::dP]; // dM/dP = {alpha * dM1/dP1 , (1 - + // // alpha) * dM2/dP2} + // dMob_dS[ip][ke] = mobWeights[ke] * m_dMob[seri[ke]][sesri[ke]][sei[ke]][ip][Deriv::dS]; // dM/dP = {alpha * dM1/dS1 , (1 - + // // alpha) * dM2/dS2} + // } + // } + real64 constexpr eps = 0.5e-8; + total_mobility += mobility[ip] + eps; + potGrad_ip[ip] = potGrad; + alpha_ip[ip] = alpha; + + } // loop over phases + + /// Three Forces Flux Contribution: 1- Viscous 2- Gravitational 3- Capillary + // loop over phases + for( integer ip = 0; ip < m_numPhases; ++ip ) + { + // 1- Viscous: pressure gradient depends on all points in the stencil + for( integer ke = 0; ke < 2; ++ke ) + { + halfFluxVal[ip][ix] = mobility[ip] / total_mobility * uT; + dhalfFlux_dP[ip][ix + ke] = dPresGrad_dP[ip][ke]; // dF/dP = { T + dT/dP1 * (P1 - P2) , + // -T + dT/dP2 * (P1 - P2) } + } + + // 2- Gravitational: gravitational head depends only on the two cells connected (same as mean density) + for( integer ke = 0; ke < 2; ++ke ) + { + halfFluxVal[ip][ix] -= mobility[0] * mobility[1] / total_mobility * gravHead[ip]; + dhalfFlux_dP[ip][ix + ke] -= dGravHead_dP[ip][ke]; // dF/dP = { T + dT/dP1 * (P1 - P2) - drho/dP1 * T g (z1 - z2) - dT/dP1 * rho g (z1 - + // z2) , + // -T + dT/dP2 * (P1 - P2) - drho/dP2 * T g (z1 - z2) - dT/dP2 * rho g (z1 - + // z2) } + } + + // 3- Capillary: capillary pressure contribution + if( m_hasCapPressure ) + { + for( integer ke = 0; ke < 2; ++ke ) + { + halfFluxVal[ip][ix] += mobility[0] * mobility[1] / total_mobility * capGrad[ip]; + dhalfFlux_dP[ip][ix + ke] += dCapGrad_dP[ip][ke]; // dF/dP = { T + dT/dP1 * (P1 - P2) - drho/dP1 * T g (z1 - z2) - dT/dP1 * rho g (z1 + // - z2) + dT/dP1 * (-Pc1 + Pc2) , + // -T + dT/dP2 * (P1 - P2) - drho/dP2 * T g (z1 - z2) - dT/dP2 * rho g (z1 + // - z2) + dT/dP2 * (-Pc1 + Pc2) } + + dhalfFlux_dS[ip][ix + ke] = dCapGrad_dS[ip][ke]; // dF/dS = { T * -dPc/dS1 , T * dPc/dS2 } + } + } + + + for( integer ke = 0; ke < 2; ++ke ) + { + dhalfFlux_dP[ip][ix + ke] *= mobility[ip]; // dF/dP = { M [ T + dT/dP1 * (P1 - P2) - drho/dP1 * T g (z1 - z2) - dT/dP1 * rho g (z1 - + // z2) + dT/dP1 * (-Pc1 + Pc2)] , + // M [-T + dT/dP2 * (P1 - P2) - drho/dP2 * T g (z1 - z2) - dT/dP2 * rho g (z1 - + // z2) + dT/dP2 * (-Pc1 + Pc2)] } + + dhalfFlux_dS[ip][ix + ke] *= mobility[ip]; // dF/dS = { M [T * -dPc/dS1] , M [T * dPc/dS2] } + } + + // add contribution from upstream cell mobility derivatives + for( integer ke = 0; ke < 2; ++ke ) + { + dhalfFlux_dP[ip][ix + ke] += dMob_dP[ip][ke] * potGrad_ip[ip]; // dF/dP = { M [ T + dT/dP1 * (P1 - P2) - drho1/dP * T g (z1 - z2) - dT/dP1 * + // rho g (z1 - z2) + dT/dP1 * (-Pc1 + Pc2)] + dM/dP1 * DPhi , + // M [-T + dT/dP2 * (P1 - P2) - drho2/dP * T g (z1 - z2) - dT/dP2 * + // rho g (z1 - z2) + dT/dP2 * (-Pc1 + Pc2)] + dM/dP2 * DPhi } + dhalfFlux_dS[ip][ix + ke] += dMob_dS[ip][ke] * potGrad_ip[ip]; // dF/dS = { M [T * -dPc/dS1] + dM/dS1 * DPhi , M [T * dPc/dS2] + dM/dS2 * DPhi + // } } + // does + + } // loop over phases + + } // loop over half fluxes + + local_jacobian = dhalfFlux_dS[1][1]*dfacePhaseVolFrac_dCapPres1[0][0][1][1] - dhalfFlux_dS[1][3]*dfacePhaseVolFrac_dCapPres2[0][0][1][1]; + local_residual = halfFluxVal[1][0] - halfFluxVal[1][1]; + + real64 deltaPc = local_residual/local_jacobian; + Pc_int -= deltaPc; + + iter++; + + // Check convergence + if (std::fabs(local_residual) < tol) { + break; // Converged + } + + + } + + for( integer ip = 0; ip < m_numPhases; ++ip ) + { + // populate local flux vector and derivatives + stack.localFlux[k[0]*numEqn + ip] += m_dt * (halfFluxVal[ip][0] + halfFluxVal[ip][1]); + stack.localFlux[k[1]*numEqn + ip] -= m_dt * (halfFluxVal[ip][0] + halfFluxVal[ip][1]); + + for( integer ke = 0; ke < 2; ++ke ) + { + // pressure + localIndex const localDofIndexPres = k[ke] * numDof; + stack.localFluxJacobian[k[0]*numEqn + ip][localDofIndexPres] += m_dt * dhalfFlux_dP[ip][ke]; + stack.localFluxJacobian[k[1]*numEqn + ip][localDofIndexPres] -= m_dt * dhalfFlux_dP[ip][ke]; + + // saturation (hard-coded for 2-phase currently) + localIndex const localDofIndexSat = k[ke] * numDof + 1; + stack.localFluxJacobian[k[0]*numEqn + ip][localDofIndexSat] += m_dt * dhalfFlux_dS[ip][ke]; + stack.localFluxJacobian[k[1]*numEqn + ip][localDofIndexSat] -= m_dt * dhalfFlux_dS[ip][ke]; + } + + // Customize the kernel with this lambda + kernelOp( k, seri, sesri, sei, connectionIndex, alpha_ip[ip], mobility, potGrad_ip[ip], fluxVal, dFlux_dP, dFlux_dS ); // Not sure what this + + + // } +// // // compute S_alpha and S_beta: + // S_int[0] = computePCalphaInv< arrayView1d< real64 const > >( Pc_int ); + // S_int[1] = computePCalphaInv< arrayView1d< real64 const > >( Pc_int ); + + // real64 S_avg = S_int[0] + S_int[1]; + + // // real64 PC_int1 = computePCalphaInv > ( S_int[0] ); + // // real64 PC_int2 = computePCalphaInv > ( S_int[1] ); + + + + // GEOS_UNUSED_PARAM( Pc_int ); + + } // loop over phases + } // end of else for interface conditions connectionIndex++; } } // loop over connection elements @@ -1189,6 +1667,7 @@ class FaceBasedAssemblyInterfaceConditionKernel : public FaceBasedAssemblyKernel /// Reference to the capillary pressure wrapper CAPPRESWRAPPER const m_capPressureWrapper; + RELPERMWRAPPER const m_relPermWrapper; }; @@ -1264,7 +1743,7 @@ class FaceBasedAssemblyKernelFactory * @param[inout] localMatrix the local CRS matrix * @param[inout] localRhs the local right-hand side vector */ - template< typename POLICY, typename STENCILWRAPPER, typename CAPPRESWRAPPER > + template< typename POLICY, typename STENCILWRAPPER, typename CAPPRESWRAPPER, typename RELPERMWRAPPER > static void createAndLaunch( integer const numPhases, globalIndex const rankOffset, @@ -1276,28 +1755,31 @@ class FaceBasedAssemblyKernelFactory ElementRegionManager const & elemManager, STENCILWRAPPER const & stencilWrapper, CAPPRESWRAPPER const & capPresWrapper, + RELPERMWRAPPER const & relPermWrapper, + ElementSubRegionBase const & subRegion, real64 const & dt, CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) { integer constexpr NUM_EQN = 2; integer constexpr NUM_DOF = 2; - + localIndex const domainSize = subRegion.size(); + // GEOS_UNUSED_PARAM( domainSize ); ElementRegionManager::ElementViewAccessor< arrayView1d< globalIndex const > > dofNumberAccessor = elemManager.constructArrayViewAccessor< globalIndex, 1 >( dofKey ); dofNumberAccessor.setName( solverName + "/accessors/" + dofKey ); - using kernelType = FaceBasedAssemblyInterfaceConditionKernel< NUM_EQN, NUM_DOF, STENCILWRAPPER, CAPPRESWRAPPER >; + using kernelType = FaceBasedAssemblyInterfaceConditionKernel< NUM_EQN, NUM_DOF, STENCILWRAPPER, CAPPRESWRAPPER, RELPERMWRAPPER >; typename kernelType::ImmiscibleMultiphaseFlowAccessors flowAccessors( elemManager, solverName ); typename kernelType::MultiphaseFluidAccessors fluidAccessors( elemManager, solverName ); typename kernelType::CapPressureAccessors capPressureAccessors( elemManager, solverName ); typename kernelType::PermeabilityAccessors permAccessors( elemManager, solverName ); - kernelType kernel( numPhases, rankOffset, stencilWrapper, capPresWrapper, dofNumberAccessor, + kernelType kernel( numPhases, rankOffset, stencilWrapper, capPresWrapper, relPermWrapper, dofNumberAccessor, flowAccessors, fluidAccessors, capPressureAccessors, permAccessors, dt, localMatrix, localRhs, hasCapPressure, useTotalMassEquation, - checkPhasePresenceInGravity ); - kernelType::template launch< POLICY >( stencilWrapper.size(), kernel ); + checkPhasePresenceInGravity, domainSize); + kernelType::template launch< POLICY >( stencilWrapper.size() , kernel ); } }; From b47698e5ec0a7d8eb3c78ed9c9705c66959115c7 Mon Sep 17 00:00:00 2001 From: Ammara-14 Date: Fri, 9 May 2025 14:02:08 -0700 Subject: [PATCH 092/104] updates to the array indices --- .../ImmiscibleMultiphaseKernels.hpp | 318 ++++++++++-------- 1 file changed, 169 insertions(+), 149 deletions(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp index fa6b6f69d17..a8d38df9229 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp @@ -101,6 +101,7 @@ class FaceBasedAssemblyKernelBase fields::flow::gravityCoefficient, fields::immiscibleMultiphaseFlow::phaseVolumeFraction, fields::immiscibleMultiphaseFlow::phaseMobility, + fields::immiscibleMultiphaseFlow::phaseMass_n, fields::immiscibleMultiphaseFlow::dPhaseMobility >; using MultiphaseFluidAccessors = @@ -161,6 +162,7 @@ class FaceBasedAssemblyKernelBase m_gravCoef( multiPhaseFlowAccessors.get( fields::flow::gravityCoefficient {} ) ), m_pres( multiPhaseFlowAccessors.get( fields::flow::pressure {} ) ), m_phaseVolFrac( multiPhaseFlowAccessors.get( fields::immiscibleMultiphaseFlow::phaseVolumeFraction {} ) ), + m_phaseMass_n( multiPhaseFlowAccessors.get( fields::immiscibleMultiphaseFlow::phaseMass_n {} ) ), m_mob( multiPhaseFlowAccessors.get( fields::immiscibleMultiphaseFlow::phaseMobility {} ) ), m_dMob( multiPhaseFlowAccessors.get( fields::immiscibleMultiphaseFlow::dPhaseMobility {} ) ), m_dens( fluidAccessors.get( fields::twophasefluid::phaseDensity {} ) ), @@ -203,6 +205,7 @@ class FaceBasedAssemblyKernelBase /// Views on pressure and phase volume fraction ElementViewConst< arrayView1d< real64 const > > const m_pres; ElementViewConst< arrayView2d< real64 const, immiscibleFlow::USD_PHASE > > const m_phaseVolFrac; + ElementViewConst< arrayView2d< real64 const, immiscibleFlow::USD_PHASE > > const m_phaseMass_n; /// Views on fluid mobility ElementViewConst< arrayView2d< real64 const, immiscibleFlow::USD_PHASE > > const m_mob; @@ -804,6 +807,7 @@ class FaceBasedAssemblyInterfaceConditionKernel : public FaceBasedAssemblyKernel using Base::m_permeability; using Base::m_dPerm_dPres; using Base::m_phaseVolFrac; + using Base::m_phaseMass_n; using Base::m_phaseCapPressure; using Base::m_jFuncMultiplier; using Base::m_dPhaseCapPressure_dPhaseVolFrac; @@ -901,6 +905,25 @@ class FaceBasedAssemblyInterfaceConditionKernel : public FaceBasedAssemblyKernel localIndex k[2]; localIndex connectionIndex = 0; + // // Create an output file stream object (ofstream) + // std::ofstream outFile("iterations.csv"); + + + // // Write data to the file + // outFile << "Jacobian"; + // outFile << ","; + // outFile << "residual"; + // outFile << ","; + // outFile << "F_alpha"; + // outFile << ","; + // outFile << "F_beta"; + // outFile << ","; + // outFile << "Pc"; + // outFile << ","; + // outFile << "newton"; + // outFile << std::endl; + + m_stencilWrapper.computeHalfWeights( iconn, m_permeability, m_dPerm_dPres, @@ -1041,10 +1064,6 @@ class FaceBasedAssemblyInterfaceConditionKernel : public FaceBasedAssemblyKernel potScale = fmax( potScale, fabs( pot ) ); // maxPhi = Phi1 > Phi2 ? Phi1 : Phi2 } - // std::cout << GEOS_FMT( " z1 = ( {:4.2e} )", m_gravCoef[seri[0]][sesri[0]][sei[0]] ); - // std::cout << GEOS_FMT( " z2 = ( {:4.2e} )", m_gravCoef[seri[1]][sesri[1]][sei[1]] ); - // std::cout << GEOS_FMT( " zhat1 = ( {:4.2e} )", gravCoefHat[0] ); - // std::cout << GEOS_FMT( " zhat2 = ( {:4.2e} )", gravCoefHat[1] ); for( integer ke = 0; ke < 2; ++ke ) { @@ -1168,18 +1187,19 @@ class FaceBasedAssemblyInterfaceConditionKernel : public FaceBasedAssemblyKernel // add contribution from upstream cell mobility derivatives for( integer ke = 0; ke < 2; ++ke ) { - duT_dP[ke] += dFlux_dP[ip][ke] - fluxVal[ip] * dDens_dP2[ip][ke] / density2[ip]; // dF/dP = { M [ T + dT/dP1 * (P1 - P2) - - // drho1/dP * T g (z1 - z2) - dT/dP1 * - duT_dP[ke] /= density2[ip]; // rho g (z1 - z2) + dT/dP1 * (-Pc1 + Pc2)] + dM/dP1 * DPhi , - // M [-T + dT/dP2 * (P1 - P2) - drho2/dP * T g (z1 - z2) - dT/dP2 * - // rho g (z1 - z2) + dT/dP2 * (-Pc1 + Pc2)] + dM/dP2 * DPhi } - duT_dS[ke] += dFlux_dS[ip][ke] / density2[ip]; // dF/dS = { M [T * -dPc/dS1] + dM/dS1 * DPhi , M [T * dPc/dS2] + dM/dS2 * DPhi - // } + duT_dP[ke] += dFlux_dP[ip][ke] - fluxVal[ip] * dDens_dP2[ip][ke] / density2[ip]; + + duT_dP[ke] /= density2[ip]; + duT_dS[ke] += dFlux_dS[ip][ke] / density2[ip]; } + potGrad_ip[ip] = potGrad; alpha_ip[ip] = alpha; } // loop over phases + // std::cout << GEOS_FMT( " Pc1 = ( {:4.2e} )", capPresIC[1][0] ); + // std::cout << GEOS_FMT( " Pc2 = ( {:4.2e} )", capPresIC[1][1] ); + if (std::fabs(jFMultiplier[0][0] - jFMultiplier[0][1]) < 1e-8 && std::fabs(jFMultiplier[1][0] - jFMultiplier[1][1]) < 1e-8 ) { for( integer ip = 0; ip < 2; ++ip ) { @@ -1206,24 +1226,14 @@ class FaceBasedAssemblyInterfaceConditionKernel : public FaceBasedAssemblyKernel }// does } else { - - - // std::cout << GEOS_FMT( " uT = ( {:4.2e} )", uT ); - // std::cout << GEOS_FMT( " duTdP = ( {:4.2e} )", duT_dP[0] ); - // std::cout << GEOS_FMT( " duTdS = ( {:4.2e} )", duT_dS[0] ); - std::cout << GEOS_FMT( " Pc1 = ( {:4.2e} )", capPresIC[1][0] ); - std::cout << GEOS_FMT( " Pc2 = ( {:4.2e} )", capPresIC[1][1] ); - std::cout << GEOS_FMT( " T1 = ( {:4.2e} )", trans[0] ); - std::cout << GEOS_FMT( " T2 = ( {:4.2e} )", trans[1] ); - std::cout << GEOS_FMT( " That1 = ( {:4.2e} )", transHat[0] ); - std::cout << GEOS_FMT( " That2 = ( {:4.2e} )", transHat[1] ); + // -------------------- Here I implement the interface conditions local solver --------------------- // // nonlinear solver's parameters real64 tol = 1.0e-7; - int max_iter = 50; + int max_iter = 20; // initial guess: real64 S_int[numEqn]{}; @@ -1231,7 +1241,7 @@ class FaceBasedAssemblyInterfaceConditionKernel : public FaceBasedAssemblyKernel real64 const Pc2 = capPresIC[1][1]; real64 Pc_int = ( Pc1 + Pc2 ) / 2; - // std::cout << GEOS_FMT( " Pc_int = ( {:4.2e} )", Pc_int ); + // std::cout << GEOS_FMT( " Pc_int_old = ( {:4.2e} )", Pc_int ); // // Local newton loop: // Use of the capillary pressure kernel wrapper @@ -1239,12 +1249,53 @@ class FaceBasedAssemblyInterfaceConditionKernel : public FaceBasedAssemblyKernel StackArray< real64, 2, 2, immiscibleFlow::LAYOUT_PHASE > facePhaseVolFrac1( 1, 2 ); StackArray< real64, 3, 2, constitutive::cappres::LAYOUT_CAPPRES > faceCapPres1( 1, 1, 2 ); StackArray< real64, 4, 4, constitutive::cappres::LAYOUT_CAPPRES_DS > dfacePhaseVolFrac_dCapPres1( 1, 1, 2, 2 ); + StackArray< real64, 4, 4, constitutive::cappres::LAYOUT_CAPPRES_DS > dCapPres1_dfacePhaseVolFrac( 1, 1, 2, 2 ); StackArray< real64, 2, 2, immiscibleFlow::LAYOUT_PHASE > facePhaseVolFrac2( 1, 2 ); StackArray< real64, 3, 2, constitutive::cappres::LAYOUT_CAPPRES > faceCapPres2( 1, 1, 2 ); StackArray< real64, 4, 4, constitutive::cappres::LAYOUT_CAPPRES_DS > dfacePhaseVolFrac_dCapPres2( 1, 1, 2, 2 ); + StackArray< real64, 4, 4, constitutive::cappres::LAYOUT_CAPPRES_DS > dCapPres2_dfacePhaseVolFrac( 1, 1, 2, 2 ); StackArray< real64, 1, 4> JFunc1( 2 ); StackArray< real64, 1, 4> JFunc2( 2 ); - + + JFunc1[0] = jFMultiplier[0][0]; + JFunc2[0] = jFMultiplier[0][1]; + + // finding endpoints: + facePhaseVolFrac1[0][0] = 0.0; + facePhaseVolFrac1[0][1] = 1.0; + m_capPressureWrapper.compute( facePhaseVolFrac1[0], + JFunc1.toSliceConst(), + faceCapPres1[0][0], + dCapPres1_dfacePhaseVolFrac[0][0]); + real64 const Pc1_min = faceCapPres1[0][0][1]; + facePhaseVolFrac1[0][0] = 1.0; + facePhaseVolFrac1[0][1] = 0.0; + m_capPressureWrapper.compute( facePhaseVolFrac1[0], + JFunc1.toSliceConst(), + faceCapPres1[0][0], + dCapPres1_dfacePhaseVolFrac[0][0]); + real64 const Pc1_max = faceCapPres1[0][0][1]; + + facePhaseVolFrac2[0][0] = 0.0; + facePhaseVolFrac2[0][1] = 1.0; + m_capPressureWrapper.compute( facePhaseVolFrac2[0], + JFunc2.toSliceConst(), + faceCapPres2[0][0], + dCapPres2_dfacePhaseVolFrac[0][0]); + real64 const Pc2_min = faceCapPres2[0][0][1]; + facePhaseVolFrac2[0][0] = 1.0; + facePhaseVolFrac2[0][1] = 0.0; + m_capPressureWrapper.compute( facePhaseVolFrac2[0], + JFunc2.toSliceConst(), + faceCapPres2[0][0], + dCapPres2_dfacePhaseVolFrac[0][0]); + real64 const Pc2_max = faceCapPres2[0][0][1]; + + + std::cout << GEOS_FMT( " Pc_max1 = ( {:4.2e} )", Pc1_max ); + std::cout << GEOS_FMT( " Pc_min1 = ( {:4.2e} )", Pc1_min ); + std::cout << GEOS_FMT( " Pc_max2 = ( {:4.2e} )", Pc2_max ); + std::cout << GEOS_FMT( " Pc_min2 = ( {:4.2e} )", Pc2_min ); // Use of the relative permeability kernel wrapper @@ -1265,40 +1316,7 @@ class FaceBasedAssemblyInterfaceConditionKernel : public FaceBasedAssemblyKernel while (iter < max_iter) { - // clear working arrays - - // densMean = {0 , 0}; - // dDensMean_dP[numEqn][0] = {0 , 0}; - // dDensMean_dP[numEqn][1] = {0 , 0}; - - // presGrad[numEqn] = {0 , 0}; - // dPresGrad_dP[numEqn][0] = {0 , 0}; - // dPresGrad_dP[numEqn][1] = {0 , 0}; - - // gravHead[numEqn] = {0 , 0}; - // dGravHead_dP[numEqn][0] = {0 , 0}; - // dGravHead_dP[numEqn][1] = {0 , 0}; - - // capGrad[numEqn] = {0 , 0}; - // capPresIC[numEqn][0] = {0 , 0}; - // capPresIC[numEqn][1] = {0 , 0}; - // dCapGrad_dP[numEqn][0] = {0 , 0}; - // dCapGrad_dP[numEqn][1] = {0 , 0}; - // dCapGrad_dS[numEqn][0] = {0 , 0}; - // dCapGrad_dS[numEqn][1] = {0 , 0}; - // dCapPresIC_dS[numEqn][0] = {0 , 0}; - // dCapPresIC_dS[numEqn][1] = {0 , 0}; - - // fluxVal[numEqn][0] = {0 , 0}; - // fluxVal[numEqn][1] = {0 , 0}; - // dFlux_dP[numEqn][0] = {0 , 0}; - // dFlux_dP[numEqn][1] = {0 , 0}; - // dFlux_dP[numEqn][2] = {0 , 0}; - // dFlux_dP[numEqn][3] = {0 , 0}; - // dFlux_dS[numEqn][0] = {0 , 0}; - // dFlux_dS[numEqn][1] = {0 , 0}; - // dFlux_dS[numEqn][2] = {0 , 0}; - // dFlux_dS[numEqn][3] = {0 , 0}; + @@ -1307,21 +1325,27 @@ class FaceBasedAssemblyInterfaceConditionKernel : public FaceBasedAssemblyKernel real64 viscosity[numEqn]{}; real64 dVisc_dP[numEqn][2]{}; - // mobility[numEqn] = {0 , 0}; - // dMob_dP[numEqn][0] = {0 , 0}; - // dMob_dP[numEqn][1] = {0 , 0}; - // dMob_dS[numEqn][0] = {0 , 0}; - // dMob_dS[numEqn][1] = {0 , 0}; real64 local_residual = 0; real64 local_jacobian = 0; - - // Compute the inverse: - faceCapPres1[0][0][1] = Pc_int; - faceCapPres2[0][0][1] = Pc_int; - JFunc1[0] = jFMultiplier[0][0]; - JFunc2[0] = jFMultiplier[0][1]; + real64 Pc_int1 = fmin(Pc1_max, fmax(Pc_int, Pc1_min)); + real64 Pc_int2 = fmin(Pc2_max, fmax(Pc_int, Pc2_min)); + + // std::cout << GEOS_FMT( " Pc_int1 = ( {:4.2e} )", Pc_int1 ); + // std::cout << GEOS_FMT( " Pc_int2 = ( {:4.2e} )", Pc_int2 ); + + // Compute the inverse using pc tilde:: + faceCapPres1[0][0][1] = fmin(Pc2_max, fmax(Pc_int1, Pc2_min)); + faceCapPres2[0][0][1] = fmin(Pc1_max, fmax(Pc_int2, Pc1_min)); + + + std::cout << GEOS_FMT( " faceCapPres1[0][0][1] = ( {:4.2e} )", faceCapPres1[0][0][1] ); + std::cout << GEOS_FMT( " faceCapPres2[0][0][1] = ( {:4.2e} )", faceCapPres2[0][0][1] ); + + std::cout << GEOS_FMT( " faceCapPres1[0][0][0] = ( {:4.2e} )", faceCapPres1[0][0][0] ); + std::cout << GEOS_FMT( " faceCapPres2[0][0][0] = ( {:4.2e} )", faceCapPres2[0][0][0] ); + m_capPressureWrapper.computeInv( facePhaseVolFrac1[0], @@ -1346,22 +1370,31 @@ class FaceBasedAssemblyInterfaceConditionKernel : public FaceBasedAssemblyKernel dfacePhaseRelPerm2_dPhaseVolFrac[0][0]); - // real64 Sw_alpha = facePhaseVolFrac1[0][0]; - // real64 Sw_beta = facePhaseVolFrac2[0][0]; - // std::cout << GEOS_FMT( " Sw_alpha = ( {:4.2e} )", Sw_alpha ); - // std::cout << GEOS_FMT( " Sw_beta = ( {:4.2e} )", Sw_beta ); + // real64 Sw_alpha = facePhaseVolFrac1[0][1]; + // real64 Sw_beta = facePhaseVolFrac2[0][1]; + // // std::cout << GEOS_FMT( " Sw_alpha = ( {:4.2e} )", Sw_alpha ); + // // std::cout << GEOS_FMT( " Sw_beta = ( {:4.2e} )", Sw_beta ); + + // real64 Sn_alpha = facePhaseVolFrac1[0][0]; + // real64 Sn_beta = facePhaseVolFrac2[0][0]; + - // real64 Sn_alpha = facePhaseVolFrac1[0][1]; - // real64 Sn_beta = facePhaseVolFrac2[0][1]; - // std::cout << GEOS_FMT( " Sn_alpha = ( {:4.2e} )", Sn_alpha ); - // std::cout << GEOS_FMT( " Sn_beta = ( {:4.2e} )", Sn_beta ); + //get derivatives: + m_capPressureWrapper.compute( facePhaseVolFrac1[0], + JFunc1.toSliceConst(), + faceCapPres1[0][0], + dCapPres1_dfacePhaseVolFrac[0][0]); - // std::cout << GEOS_FMT( " Krw_alpha = ( {:4.2e} )", faceRelPerm1[0][0][0] ); - // std::cout << GEOS_FMT( " Krn_alpha = ( {:4.2e} )", faceRelPerm1[0][0][1] ); + m_capPressureWrapper.compute( facePhaseVolFrac2[0], + JFunc1.toSliceConst(), + faceCapPres2[0][0], + dCapPres2_dfacePhaseVolFrac[0][0]); + - for( integer ix = 0; ix < 2; ++ix ) // for loop for each interface + + for( integer ix = 0; ix < 2; ++ix ) // for loop over each half flux { // loop over phases // clear arrays: @@ -1405,9 +1438,9 @@ class FaceBasedAssemblyInterfaceConditionKernel : public FaceBasedAssemblyKernel for( integer ke = 0; ke < 2; ++ke ) { - localIndex const er = seri[ix]; - localIndex const esr = sesri[ix]; - localIndex const ei = sei[ix]; + localIndex const er = seri[ke]; + localIndex const esr = sesri[ke]; + localIndex const ei = sei[ke]; real64 const pressure = m_pres[er][esr][ei]; // P = P1 || P2 presGrad[ip] += transHat[ix] * pressure; // DPv = T (P1 - P2) @@ -1427,7 +1460,7 @@ class FaceBasedAssemblyInterfaceConditionKernel : public FaceBasedAssemblyKernel if( m_hasCapPressure ) // check sign convention { - real64 capPres = m_phaseCapPressure[er][esr][ei][0][ip]; // Pc = Pc1 || Pc2 + real64 capPres = m_phaseCapPressure[seri[ix]][sesri[ix]][sei[ix]][0][ip]; // Pc = Pc1 || Pc2 if( ke == 1 && ix == 0 ) { capPres = faceCapPres1[0][0][ip]; @@ -1456,11 +1489,9 @@ class FaceBasedAssemblyInterfaceConditionKernel : public FaceBasedAssemblyKernel if( ke == 1 && ix == 0 ) { - real64 dCapPresIC_dS = dfacePhaseVolFrac_dCapPres1[0][0][ip][ip]; - dCapPres_dS = 1 / ( dCapPresIC_dS + eps); + dCapPres_dS = dCapPres1_dfacePhaseVolFrac[0][0][ip][ip]; } else if ( ke == 1 && ix == 1 ) { - real64 dCapPresIC_dS = dfacePhaseVolFrac_dCapPres2[0][0][ip][ip]; - dCapPres_dS = 1 / ( dCapPresIC_dS + eps); + dCapPres_dS = dCapPres2_dfacePhaseVolFrac[0][0][ip][ip]; } // dPc2/dS2 dCapGrad_dP[ip][ke] += dTransHat_dP[ix] * dCapGrad_dTrans; // dDPc/dP = { dT/dP1 * @@ -1500,12 +1531,12 @@ class FaceBasedAssemblyInterfaceConditionKernel : public FaceBasedAssemblyKernel if( k_up == 1 && ix == 0 ) { - mobility[ip] = faceRelPerm1[0][ip][ip] * density[ip] / viscosity[ip]; // M = Mupstream - dMob_dP[ip][k_up] = mobility[ip] * (dDens_dP[ip][ip] / density[ip] - dVisc_dP[ip][ip] / viscosity[ip]); // dM/dP = {dM/dP1 , 0} OR {0 , dM/dP2} + mobility[ip] = faceRelPerm1[0][0][ip] * density[ip] / viscosity[ip]; // M = Mupstream + dMob_dP[ip][k_up] = mobility[ip] * (dDens_dP[ip][ix] / density[ip] - dVisc_dP[ip][ix] / viscosity[ip]); // dM/dP = {dM/dP1 , 0} OR {0 , dM/dP2} dMob_dS[ip][k_up] = dfacePhaseRelPerm1_dPhaseVolFrac[0][0][ip][ip] * density[ip] / viscosity[ip]; // dM/dS = {dM/dS1 , 0} OR {0 , dM/dS2} } else if ( k_up == 1 && ix == 1 ) { - mobility[ip] = faceRelPerm2[0][ip][ip] * density[ip] / viscosity[ip]; // M = Mupstream - dMob_dP[ip][k_up] = mobility[ip] * (dDens_dP[ip][ip] / density[ip] - dVisc_dP[ip][ip] / viscosity[ip]); // dM/dP = {dM/dP1 , 0} OR {0 , dM/dP2} + mobility[ip] = faceRelPerm2[0][0][ip] * density[ip] / viscosity[ip]; // M = Mupstream + dMob_dP[ip][k_up] = mobility[ip] * (dDens_dP[ip][ix] / density[ip] - dVisc_dP[ip][ix] / viscosity[ip]); // dM/dP = {dM/dP1 , 0} OR {0 , dM/dP2} dMob_dS[ip][k_up] = dfacePhaseRelPerm2_dPhaseVolFrac[0][0][ip][ip] * density[ip] / viscosity[ip]; // dM/dS = {dM/dS1 , 0} OR {0 , dM/dS2} } else { mobility[ip] = m_mob[seri[k_up]][sesri[k_up]][sei[k_up]][ip]; // M = Mupstream @@ -1539,87 +1570,91 @@ class FaceBasedAssemblyInterfaceConditionKernel : public FaceBasedAssemblyKernel } // loop over phases /// Three Forces Flux Contribution: 1- Viscous 2- Gravitational 3- Capillary + constexpr int sign[2] = {1, -1}; // loop over phases for( integer ip = 0; ip < m_numPhases; ++ip ) { // 1- Viscous: pressure gradient depends on all points in the stencil for( integer ke = 0; ke < 2; ++ke ) { - halfFluxVal[ip][ix] = mobility[ip] / total_mobility * uT; - dhalfFlux_dP[ip][ix + ke] = dPresGrad_dP[ip][ke]; // dF/dP = { T + dT/dP1 * (P1 - P2) , + halfFluxVal[ip][ix] = sign[0] * mobility[ip] / total_mobility * uT; + dhalfFlux_dP[ip][ix + ke] = sign[0] * sign[ip] * (dMob_dP[0][ke] * mobility[0] - dMob_dP[1][ke] * mobility[1]) / (total_mobility * total_mobility) * uT; // dF/dP = { T + dT/dP1 * (P1 - P2) , // -T + dT/dP2 * (P1 - P2) } + dhalfFlux_dS[ip][ix + ke] = sign[0] * sign[ip] * (dMob_dS[0][ke] * mobility[0] - dMob_dS[1][ke] * mobility[1]) / (total_mobility * total_mobility) * uT; + } // 2- Gravitational: gravitational head depends only on the two cells connected (same as mean density) for( integer ke = 0; ke < 2; ++ke ) { halfFluxVal[ip][ix] -= mobility[0] * mobility[1] / total_mobility * gravHead[ip]; - dhalfFlux_dP[ip][ix + ke] -= dGravHead_dP[ip][ke]; // dF/dP = { T + dT/dP1 * (P1 - P2) - drho/dP1 * T g (z1 - z2) - dT/dP1 * rho g (z1 - - // z2) , - // -T + dT/dP2 * (P1 - P2) - drho/dP2 * T g (z1 - z2) - dT/dP2 * rho g (z1 - - // z2) } + + dhalfFlux_dP[ip][ix + ke] -= (dMob_dP[0][ke] * mobility[0] * mobility[0]+ dMob_dP[1][ke] * mobility[1] * mobility[1]) / (total_mobility * total_mobility) * gravHead[ip] + mobility[0] * mobility[1] / total_mobility * dGravHead_dP[ip][ke]; // dF/dP = { T + dT/dP1 * (P1 - P2) , + // -T + dT/dP2 * (P1 - P2) } + dhalfFlux_dS[ip][ix + ke] -= (dMob_dS[0][ke] * mobility[0] * mobility[0]+ dMob_dS[1][ke] * mobility[1] * mobility[1]) / (total_mobility * total_mobility) * gravHead[ip]; } // 3- Capillary: capillary pressure contribution + if( m_hasCapPressure ) { for( integer ke = 0; ke < 2; ++ke ) { - halfFluxVal[ip][ix] += mobility[0] * mobility[1] / total_mobility * capGrad[ip]; - dhalfFlux_dP[ip][ix + ke] += dCapGrad_dP[ip][ke]; // dF/dP = { T + dT/dP1 * (P1 - P2) - drho/dP1 * T g (z1 - z2) - dT/dP1 * rho g (z1 - // - z2) + dT/dP1 * (-Pc1 + Pc2) , - // -T + dT/dP2 * (P1 - P2) - drho/dP2 * T g (z1 - z2) - dT/dP2 * rho g (z1 - // - z2) + dT/dP2 * (-Pc1 + Pc2) } + halfFluxVal[ip][ix] -= sign[ip] * mobility[0] * mobility[1] / total_mobility * capGrad[1]; - dhalfFlux_dS[ip][ix + ke] = dCapGrad_dS[ip][ke]; // dF/dS = { T * -dPc/dS1 , T * dPc/dS2 } + dhalfFlux_dP[ip][ix + ke] -= sign[ip] * (dMob_dP[0][ke] * mobility[0] * mobility[0]+ dMob_dP[1][ke] * mobility[1] * mobility[1]) / (total_mobility * total_mobility) * capGrad[1] + mobility[0] * mobility[1] / total_mobility * dCapGrad_dP[ip][ke]; // dF/dP = { T + dT/dP1 * (P1 - P2) , + // -T + dT/dP2 * (P1 - P2) } + dhalfFlux_dS[ip][ix + ke] -= sign[ip] * (dMob_dP[0][ke] * mobility[0] * mobility[0]+ dMob_dP[1][ke] * mobility[1] * mobility[1]) / (total_mobility * total_mobility) * capGrad[1] + mobility[0] * mobility[1] / total_mobility * dCapGrad_dS[ip][ke]; } } - - for( integer ke = 0; ke < 2; ++ke ) - { - dhalfFlux_dP[ip][ix + ke] *= mobility[ip]; // dF/dP = { M [ T + dT/dP1 * (P1 - P2) - drho/dP1 * T g (z1 - z2) - dT/dP1 * rho g (z1 - - // z2) + dT/dP1 * (-Pc1 + Pc2)] , - // M [-T + dT/dP2 * (P1 - P2) - drho/dP2 * T g (z1 - z2) - dT/dP2 * rho g (z1 - - // z2) + dT/dP2 * (-Pc1 + Pc2)] } - - dhalfFlux_dS[ip][ix + ke] *= mobility[ip]; // dF/dS = { M [T * -dPc/dS1] , M [T * dPc/dS2] } - } - - // add contribution from upstream cell mobility derivatives - for( integer ke = 0; ke < 2; ++ke ) - { - dhalfFlux_dP[ip][ix + ke] += dMob_dP[ip][ke] * potGrad_ip[ip]; // dF/dP = { M [ T + dT/dP1 * (P1 - P2) - drho1/dP * T g (z1 - z2) - dT/dP1 * - // rho g (z1 - z2) + dT/dP1 * (-Pc1 + Pc2)] + dM/dP1 * DPhi , - // M [-T + dT/dP2 * (P1 - P2) - drho2/dP * T g (z1 - z2) - dT/dP2 * - // rho g (z1 - z2) + dT/dP2 * (-Pc1 + Pc2)] + dM/dP2 * DPhi } - dhalfFlux_dS[ip][ix + ke] += dMob_dS[ip][ke] * potGrad_ip[ip]; // dF/dS = { M [T * -dPc/dS1] + dM/dS1 * DPhi , M [T * dPc/dS2] + dM/dS2 * DPhi - // } - } - - // does } // loop over phases } // loop over half fluxes - local_jacobian = dhalfFlux_dS[1][1]*dfacePhaseVolFrac_dCapPres1[0][0][1][1] - dhalfFlux_dS[1][3]*dfacePhaseVolFrac_dCapPres2[0][0][1][1]; - local_residual = halfFluxVal[1][0] - halfFluxVal[1][1]; - + local_jacobian = dhalfFlux_dS[1][1]*dfacePhaseVolFrac_dCapPres1[0][0][1][1] + dhalfFlux_dS[1][3]*dfacePhaseVolFrac_dCapPres2[0][0][1][1]; + local_residual = halfFluxVal[1][0] + halfFluxVal[1][1]; + + // // Write data to the file + // outFile << local_jacobian; + // outFile << ","; + // outFile << local_residual; + // outFile << ","; + // outFile << halfFluxVal[1][0]; + // outFile << ","; + // outFile << halfFluxVal[1][1]; + // outFile << ","; + // outFile << Pc_int; + // outFile << ","; + // outFile << iter; + // outFile << std::endl; + + if (std::fabs(local_jacobian) < 1e-16) { + std::cout << "Derivative is too small" << std::endl; + break; + } + + //std::cout << GEOS_FMT( " phase_mass = ( {:4.2e} )", phase_mass ); real64 deltaPc = local_residual/local_jacobian; + + std::cout << GEOS_FMT( " local_R = ( {:4.2e} )", local_residual ); + std::cout << GEOS_FMT( " deltaPc = ( {:4.2e} )", deltaPc ); + Pc_int -= deltaPc; - iter++; // Check convergence if (std::fabs(local_residual) < tol) { break; // Converged } + iter++; + } // while loop - } - + // // Close the file after writing + // outFile.close(); for( integer ip = 0; ip < m_numPhases; ++ip ) { // populate local flux vector and derivatives @@ -1642,21 +1677,6 @@ class FaceBasedAssemblyInterfaceConditionKernel : public FaceBasedAssemblyKernel // Customize the kernel with this lambda kernelOp( k, seri, sesri, sei, connectionIndex, alpha_ip[ip], mobility, potGrad_ip[ip], fluxVal, dFlux_dP, dFlux_dS ); // Not sure what this - - // } -// // // compute S_alpha and S_beta: - // S_int[0] = computePCalphaInv< arrayView1d< real64 const > >( Pc_int ); - // S_int[1] = computePCalphaInv< arrayView1d< real64 const > >( Pc_int ); - - // real64 S_avg = S_int[0] + S_int[1]; - - // // real64 PC_int1 = computePCalphaInv > ( S_int[0] ); - // // real64 PC_int2 = computePCalphaInv > ( S_int[1] ); - - - - // GEOS_UNUSED_PARAM( Pc_int ); - } // loop over phases } // end of else for interface conditions connectionIndex++; From 7493d2912ef3a4700fa8aac1c1d9ee3df5b29733 Mon Sep 17 00:00:00 2001 From: Randolph Settgast Date: Fri, 10 Oct 2025 16:23:52 -0700 Subject: [PATCH 093/104] feat: data structure for enabling capillary interface conditions (#3657) * enable creation of new FaceElementSubregion entries from interface sets * wip: draft for a working example * wip: parsing registered container "interfaceFaceSetNames" * wip: two-regions example * wip: initializePreSubGroups() is executing * wip: inelegant access to relperms * wip: filling up m_constitutitveFluidModels * wip: apply formatter uncrustify * Update ImmiscibleMultiphaseFlow.cpp * Update ImmiscibleMultiphaseFlow.cpp * Update ImmiscibleMultiphaseFlow.cpp * Update uni_directional_flow_interface_condition.xml * wip: commenting some attributions of addToFractureMesh * wip: split attributions of addToFractureMesh * wip: strongly typed implementation * Update immiscibleTwoPhase_GravitySegregation_1d.xml * wip: remove reference to nonexistent test file * wip: apply formatter uncrustify * added capPressure and fluid to m_constitutitveFluidModels * wip: rename attribute m_constitutitveFluidModels to m_interfaceConstitutivePairs * wip: extending example xml file * Update ImmiscibleMultiphaseFlow.cpp * Update ImmiscibleMultiphaseFlow.cpp * Update SurfaceElementRegion.cpp * refactor: split functionality of addToFractureMesh * Update ImmiscibleMultiphaseKernels.hpp * Update ImmiscibleMultiphaseKernels.hpp * passing m_interfaceFaceSetNames and m_interfaceConstitutivePairs to the FluxComputeKernel * some cleanup * wip: reducing signature of addToSurfaceMesh Co-Authored-By: Randolph Settgast * run formatter uncrusitfy Co-Authored-By: Randolph Settgast Revert "run formatter uncrusitfy" This reverts commit c801af3c526046770fff6460ee07025824e62a2b. run formatter uncrusitfy * wip: using originalFaceToEdgeMap * fix: unused variable 'edgeMap' * Update SurfaceElementRegion.cpp * Update SurfaceElementRegion.cpp * Update SurfaceElementRegion.cpp * Update SurfaceElementRegion.hpp * Update ImmiscibleMultiphaseFlow.cpp * wip: adding a index map between interfaceRegion and its associated "Connectors" * Update StencilBase.hpp * Update StencilBase.hpp * Update ImmiscibleMultiphaseFlow.cpp * wip: Simplify implementation * wip: uncrustify style * wip: remove geos scope * Update ImmiscibleMultiphaseKernels.hpp * Update ImmiscibleMultiphaseKernels.hpp * Update ImmiscibleMultiphaseFlow.cpp * debugged and working local solver for the interface conditions that converges for viscous, gravity, and capillary fluxes * Update StencilBase.hpp * Update ImmiscibleMultiphaseFlow.hpp Introducing an alternative container m_connectorIndicesByInterfaceRegion this implies call the nonlinear interface solver in a separate call * WIP: adding some extra comments * wip: fix indentation * Adding an example input file * refactor: clean up files * Update ImmiscibleMultiphaseKernels.hpp * Update ImmiscibleMultiphaseKernels.hpp * Moved the local solver to be an inline static function * change interfaceConstitutivePairs type from ConstitutiveBase to each model's type Base * added a unit Test for the local interface conditions solver and resolved some merge conflicts * adding unitTest --------- Co-authored-by: Omar Duran Co-authored-by: Ammara-14 --- ...miscibleTwoPhase_GravitySegregation_1d.xml | 2 +- ...oPhase_GravitySegregation_1d_pc_heter2.xml | 280 ++ .../initialPressure.txt | 10 + .../initialSaturation1.txt | 10 + .../initialSaturation2.txt | 10 + .../jFunction_linear.txt | 2 + .../permx.geos | 10 + .../permy.geos | 10 + .../permz.geos | 10 + .../phaseVolumeFraction_water_linear.txt | 2 + .../tables/jFunction.txt | 13 + .../tables/jFunction_linear.txt | 2 + .../tables/phaseVolumeFraction_water.txt | 13 + .../phaseVolumeFraction_water_linear.txt | 2 + .../x.txt | 1 + .../y.txt | 1 + .../z.txt | 10 + .../tables/jFunction_linear.txt | 2 + .../tables/phaseVolumeFraction_water.txt | 76 + .../phaseVolumeFraction_water_linear.txt | 2 + .../uni_directional_flow_base.xml | 225 ++ ...i_directional_flow_interface_condition.xml | 66 + .../BrooksCoreyCapillaryPressure.hpp | 174 +- .../CapillaryPressureSelector.hpp | 24 +- .../JFunctionCapillaryPressure.cpp | 39 +- .../JFunctionCapillaryPressure.hpp | 34 +- .../TableCapillaryPressure.cpp | 48 +- .../TableCapillaryPressure.hpp | 35 +- .../VanGenuchtenCapillaryPressure.hpp | 68 + .../unitTests/FluidModelTest_impl.hpp | 2 +- .../finiteVolume/CellElementStencilTPFA.hpp | 36 +- .../EmbeddedSurfaceToCellStencil.hpp | 16 +- .../finiteVolume/FaceElementToCellStencil.hpp | 30 +- .../finiteVolume/SurfaceElementStencil.hpp | 16 +- .../testImmiscibleInterfaceConditions.cpp | 677 +++++ .../wellsTests/CMakeLists.txt | 17 + .../fluidFlow/ImmiscibleMultiphaseFlow.cpp | 91 +- .../fluidFlow/ImmiscibleMultiphaseFlow.hpp | 25 +- .../ImmiscibleMultiphaseKernels.hpp | 2453 ++++++++++++----- 39 files changed, 3636 insertions(+), 908 deletions(-) create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/immiscibleTwoPhase_GravitySegregation_1d_pc_heter2.xml create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/initialPressure.txt create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/initialSaturation1.txt create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/initialSaturation2.txt create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/jFunction_linear.txt create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/permx.geos create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/permy.geos create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/permz.geos create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/phaseVolumeFraction_water_linear.txt create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/tables/jFunction.txt create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/tables/jFunction_linear.txt create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/tables/phaseVolumeFraction_water.txt create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/tables/phaseVolumeFraction_water_linear.txt create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/x.txt create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/y.txt create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/z.txt create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/tables/jFunction_linear.txt create mode 100755 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/tables/phaseVolumeFraction_water.txt create mode 100755 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/tables/phaseVolumeFraction_water_linear.txt create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/uni_directional_flow_base.xml create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/uni_directional_flow_interface_condition.xml create mode 100644 src/coreComponents/integrationTests/fluidFlowTests/testImmiscibleInterfaceConditions.cpp diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_GravitySegregation_1d/immiscibleTwoPhase_GravitySegregation_1d.xml b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_GravitySegregation_1d/immiscibleTwoPhase_GravitySegregation_1d.xml index 12e6d52f990..62d4f6cf3bb 100644 --- a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_GravitySegregation_1d/immiscibleTwoPhase_GravitySegregation_1d.xml +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_GravitySegregation_1d/immiscibleTwoPhase_GravitySegregation_1d.xml @@ -115,7 +115,7 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/initialPressure.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/initialPressure.txt new file mode 100644 index 00000000000..63943bfa00d --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/initialPressure.txt @@ -0,0 +1,10 @@ +1e7 +1e7 +1e7 +1e7 +1e7 +1e7 +1e7 +1e7 +1e7 +1e7 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/initialSaturation1.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/initialSaturation1.txt new file mode 100644 index 00000000000..79cccb86897 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/initialSaturation1.txt @@ -0,0 +1,10 @@ +0.4 +0.4 +0.8 +0.8 +0.8 +0.8 +0.8 +0.8 +0.8 +0.8 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/initialSaturation2.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/initialSaturation2.txt new file mode 100644 index 00000000000..72c544974fe --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/initialSaturation2.txt @@ -0,0 +1,10 @@ +0.6 +0.6 +0.2 +0.2 +0.2 +0.2 +0.2 +0.2 +0.2 +0.2 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/jFunction_linear.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/jFunction_linear.txt new file mode 100644 index 00000000000..c3dfd50073f --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/jFunction_linear.txt @@ -0,0 +1,2 @@ +4.33172935918785 +1.66604975353379 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/permx.geos b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/permx.geos new file mode 100644 index 00000000000..ec8beb6c503 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/permx.geos @@ -0,0 +1,10 @@ +112.5 +112.5 +112.5 +112.5 +112.5 +50 +50 +50 +50 +50 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/permy.geos b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/permy.geos new file mode 100644 index 00000000000..ec8beb6c503 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/permy.geos @@ -0,0 +1,10 @@ +112.5 +112.5 +112.5 +112.5 +112.5 +50 +50 +50 +50 +50 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/permz.geos b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/permz.geos new file mode 100644 index 00000000000..ec8beb6c503 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/permz.geos @@ -0,0 +1,10 @@ +112.5 +112.5 +112.5 +112.5 +112.5 +50 +50 +50 +50 +50 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/phaseVolumeFraction_water_linear.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/phaseVolumeFraction_water_linear.txt new file mode 100644 index 00000000000..0d66ea1aee9 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/phaseVolumeFraction_water_linear.txt @@ -0,0 +1,2 @@ +0 +1 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/tables/jFunction.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/tables/jFunction.txt new file mode 100644 index 00000000000..dfd48c60a6b --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/tables/jFunction.txt @@ -0,0 +1,13 @@ +4.331729359 +3.523266264 +2.677103439 +2.356150157 +2.166062360 +2.034158727 +1.934627222 +1.855494313 +1.790286970 +1.735134860 +1.687551617 +1.666049754 + diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/tables/jFunction_linear.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/tables/jFunction_linear.txt new file mode 100644 index 00000000000..13036f8fd03 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/tables/jFunction_linear.txt @@ -0,0 +1,2 @@ +100.00 +1.00 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/tables/phaseVolumeFraction_water.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/tables/phaseVolumeFraction_water.txt new file mode 100644 index 00000000000..4c7e1f01e40 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/tables/phaseVolumeFraction_water.txt @@ -0,0 +1,13 @@ +0 +0.05 +0.15 +0.25 +0.35 +0.45 +0.55 +0.65 +0.75 +0.85 +0.95 +1 + diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/tables/phaseVolumeFraction_water_linear.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/tables/phaseVolumeFraction_water_linear.txt new file mode 100644 index 00000000000..0a269ee3741 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/tables/phaseVolumeFraction_water_linear.txt @@ -0,0 +1,2 @@ +0.0 +1.0 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/x.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/x.txt new file mode 100644 index 00000000000..7ed6ff82de6 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/x.txt @@ -0,0 +1 @@ +5 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/y.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/y.txt new file mode 100644 index 00000000000..7ed6ff82de6 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/y.txt @@ -0,0 +1 @@ +5 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/z.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/z.txt new file mode 100644 index 00000000000..d71cc528224 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/z.txt @@ -0,0 +1,10 @@ +5 +15 +25 +35 +45 +55 +65 +75 +85 +95 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/tables/jFunction_linear.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/tables/jFunction_linear.txt new file mode 100644 index 00000000000..c2cba8f9783 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/tables/jFunction_linear.txt @@ -0,0 +1,2 @@ +10000 +3000 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/tables/phaseVolumeFraction_water.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/tables/phaseVolumeFraction_water.txt new file mode 100755 index 00000000000..30a57a9dee4 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/tables/phaseVolumeFraction_water.txt @@ -0,0 +1,76 @@ +0 +0.013333333 +0.026666667 +0.04 +0.053333333 +0.066666667 +0.08 +0.093333333 +0.106666667 +0.12 +0.133333333 +0.146666667 +0.16 +0.173333333 +0.186666667 +0.2 +0.213333333 +0.226666667 +0.24 +0.253333333 +0.266666667 +0.28 +0.293333333 +0.306666667 +0.32 +0.333333333 +0.346666667 +0.36 +0.373333333 +0.386666667 +0.4 +0.413333333 +0.426666667 +0.44 +0.453333333 +0.466666667 +0.48 +0.493333333 +0.506666667 +0.52 +0.533333333 +0.546666667 +0.56 +0.573333333 +0.586666667 +0.6 +0.613333333 +0.626666667 +0.64 +0.653333333 +0.666666667 +0.68 +0.693333333 +0.706666667 +0.72 +0.733333333 +0.746666667 +0.76 +0.773333333 +0.786666667 +0.8 +0.813333333 +0.826666667 +0.84 +0.853333333 +0.866666667 +0.88 +0.893333333 +0.906666667 +0.92 +0.933333333 +0.946666667 +0.96 +0.973333333 +0.986666667 +1 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/tables/phaseVolumeFraction_water_linear.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/tables/phaseVolumeFraction_water_linear.txt new file mode 100755 index 00000000000..0d66ea1aee9 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/tables/phaseVolumeFraction_water_linear.txt @@ -0,0 +1,2 @@ +0 +1 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/uni_directional_flow_base.xml b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/uni_directional_flow_base.xml new file mode 100644 index 00000000000..2640edbdc80 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/uni_directional_flow_base.xml @@ -0,0 +1,225 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/uni_directional_flow_interface_condition.xml b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/uni_directional_flow_interface_condition.xml new file mode 100644 index 00000000000..c263012d27c --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/uni_directional_flow_interface_condition.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/coreComponents/constitutive/capillaryPressure/BrooksCoreyCapillaryPressure.hpp b/src/coreComponents/constitutive/capillaryPressure/BrooksCoreyCapillaryPressure.hpp index c020174dd21..6b9972253d7 100644 --- a/src/coreComponents/constitutive/capillaryPressure/BrooksCoreyCapillaryPressure.hpp +++ b/src/coreComponents/constitutive/capillaryPressure/BrooksCoreyCapillaryPressure.hpp @@ -57,6 +57,11 @@ class BrooksCoreyCapillaryPressureUpdate final : public CapillaryPressureBaseUpd arraySlice1d< real64, cappres::USD_CAPPRES - 2 > const & phaseCapPres, arraySlice2d< real64, cappres::USD_CAPPRES_DS - 2 > const & dPhaseCapPres_dPhaseVolFrac ) const; + GEOS_HOST_DEVICE + void computeInv( arraySlice1d< real64, compflow::USD_PHASE - 1 > const & phaseVolFraction, + arraySlice1d< real64 const, cappres::USD_CAPPRES - 2 > const & phaseCapPres, + arraySlice2d< real64, cappres::USD_CAPPRES_DS - 2 > const & dPhaseCapPres_dPhaseVolFrac ) const; + GEOS_HOST_DEVICE virtual void update( localIndex const k, localIndex const q, @@ -80,14 +85,35 @@ class BrooksCoreyCapillaryPressureUpdate final : public CapillaryPressureBaseUpd real64 & phaseCapPressure, real64 & dPhaseCapPressure_dVolFrac ); + +GEOS_HOST_DEVICE +GEOS_FORCE_INLINE +static void +evaluateBrooksCoreyFunctionInv( real64 const phaseCapPressure, + int const ip, + real64 const volFracScaleInv, + real64 const exponentInv, + real64 const entryPressure, + real64 const maxCapPres_eps, + real64 const phaseMinVolumeFraction, + arrayView1d< integer const > const phaseOrder, + real64 & phaseVolFraction, + real64 & dPhaseCapPressure_dVolFrac ); + arrayView1d< real64 const > m_phaseMinVolumeFraction; arrayView1d< real64 const > m_phaseCapPressureExponentInv; arrayView1d< real64 const > m_phaseEntryPressure; real64 m_capPressureEpsilon; real64 m_volFracScale; + }; + + + + + class BrooksCoreyCapillaryPressure : public CapillaryPressureBase { public: @@ -171,11 +197,12 @@ BrooksCoreyCapillaryPressureUpdate:: // compute first gas-oil capillary pressure as a function of gas-phase vol fraction integer const ip_gas = m_phaseOrder[CapillaryPressureBase::PhaseType::GAS]; - if( ip_gas >= 0 ) + integer const ip_oil = m_phaseOrder[CapillaryPressureBase::PhaseType::OIL]; + if( ip_oil >= 0 ) { - real64 const volFracScaled = (phaseVolFraction[ip_gas] - m_phaseMinVolumeFraction[ip_gas]) * volFracScaleInv; - real64 const exponentInv = m_phaseCapPressureExponentInv[ip_gas]; - real64 const entryPressure = -m_phaseEntryPressure[ip_gas]; // for gas capillary pressure, take the opposite of the + real64 const volFracScaled = (phaseVolFraction[ip_oil] - m_phaseMinVolumeFraction[ip_oil]) * volFracScaleInv; + real64 const exponentInv = m_phaseCapPressureExponentInv[ip_oil]; + real64 const entryPressure = -m_phaseEntryPressure[ip_oil]; // for gas capillary pressure, take the opposite of the // BC function real64 const wettingVolFracScaled = 1-volFracScaled; @@ -186,9 +213,101 @@ BrooksCoreyCapillaryPressureUpdate:: exponentInv, entryPressure, eps, - phaseCapPres[ip_gas], - dPhaseCapPres_dPhaseVolFrac[ip_gas][ip_gas] ); + phaseCapPres[ip_oil], + dPhaseCapPres_dPhaseVolFrac[ip_oil][ip_oil] ); + } +} + +GEOS_HOST_DEVICE +inline void +BrooksCoreyCapillaryPressureUpdate:: + computeInv( arraySlice1d< real64, compflow::USD_PHASE - 1 > const & phaseVolFraction, + arraySlice1d< real64 const, cappres::USD_CAPPRES - 2 > const & phaseCapPres, + arraySlice2d< real64, cappres::USD_CAPPRES_DS - 2 > const & dPhaseCapPres_dPhaseVolFrac ) const +{ + LvArray::forValuesInSlice( dPhaseCapPres_dPhaseVolFrac, []( real64 & val ){ val = 0.0; } ); + + real64 const volFracScaleInv = 1.0 / m_volFracScale; + + // the Brooks-Corey model does not support volFracScaled = 0, + // hence we need an epsilon value to avoid a division by zero + // TODO: for S < epsilon, replace the original unbounded BC curve with a bounded power-law extension + real64 const eps = m_capPressureEpsilon; + + + // compute first water-oil capillary pressure as a function of water-phase vol fraction + integer const ip_water = m_phaseOrder[CapillaryPressureBase::PhaseType::WATER]; + integer const ip_gas = m_phaseOrder[CapillaryPressureBase::PhaseType::GAS]; + if( ip_water >= 0 ) + { + real64 const volFracScaled_eps = (eps - m_phaseMinVolumeFraction[ip_water]) * volFracScaleInv; + real64 const exponentInv = m_phaseCapPressureExponentInv[ip_water]; + real64 const entryPressure = m_phaseEntryPressure[ip_water]; + + real64 const wettingVolFracScaled_eps = volFracScaled_eps; + real64 const dWettingVolFracScaled_dVolFrac = volFracScaleInv; + + real64 maxCapPres_eps = 0.0; + real64 max_dpc_eps = 0.0; + + evaluateBrooksCoreyFunction( wettingVolFracScaled_eps, + dWettingVolFracScaled_dVolFrac, + exponentInv, + entryPressure, + eps, + maxCapPres_eps, + max_dpc_eps ); + + evaluateBrooksCoreyFunctionInv( phaseCapPres[ip_water], + ip_water, + volFracScaleInv, + exponentInv, + entryPressure, + maxCapPres_eps, + m_phaseMinVolumeFraction[ip_water], + m_phaseOrder, + phaseVolFraction[ip_water], + dPhaseCapPres_dPhaseVolFrac[ip_water][ip_water] ); + phaseVolFraction[ip_gas] = 1.0 - phaseVolFraction[ip_water]; } + + + // compute first gas-oil capillary pressure as a function of gas-phase vol fraction + + + // if( ip_gas >= 0 ) + // { + // real64 const volFracScaled_eps = (eps - m_phaseMinVolumeFraction[ip_gas]) * volFracScaleInv; + // real64 const exponentInv = m_phaseCapPressureExponentInv[ip_gas]; + // real64 const entryPressure = -m_phaseEntryPressure[ip_gas]; // for gas capillary pressure, take the opposite of the + // // BC function + + // real64 const wettingVolFracScaled_eps = 1-volFracScaled_eps; + // real64 const dWettingVolFracScaled_dVolFrac = -volFracScaleInv; + + // real64 maxCapPres_eps = 0.0; + // real64 max_dpc_eps = 0.0; + + // evaluateBrooksCoreyFunction( wettingVolFracScaled_eps, + // dWettingVolFracScaled_dVolFrac, + // exponentInv, + // entryPressure, + // eps, + // maxCapPres_eps, + // max_dpc_eps ); + + // evaluateBrooksCoreyFunctionInv( phaseCapPres[ip_gas], + // ip_gas, + // volFracScaleInv, + // exponentInv, + // entryPressure, + // maxCapPres_eps, + // m_phaseMinVolumeFraction[ip_gas], + // m_phaseOrder, + // phaseVolFraction[ip_gas], + // dPhaseCapPres_dPhaseVolFrac[ip_gas][ip_gas] ); + // phaseVolFraction[ip_water] = 1.0 - phaseVolFraction[ip_gas]; + // } } GEOS_HOST_DEVICE @@ -224,6 +343,49 @@ BrooksCoreyCapillaryPressureUpdate:: } +GEOS_HOST_DEVICE +inline void +BrooksCoreyCapillaryPressureUpdate:: + evaluateBrooksCoreyFunctionInv( real64 const phaseCapPressure, + int const ip, + real64 const volFracScaleInv, + real64 const exponentInv, + real64 const entryPressure, + real64 const maxCapPres_eps, + real64 const phaseMinVolumeFraction, + arrayView1d< integer const > const phaseOrder, + real64 & phaseVolFraction, + real64 & dPhaseCapPressure_dVolFrac ) +{ + + + phaseVolFraction = 0.0; + real64 value = 0.0; + dPhaseCapPressure_dVolFrac = 0.0; + integer const ip_oil = phaseOrder[CapillaryPressureBase::PhaseType::OIL]; + + real64 const dScaledWettingPhaseVolFrac_dVolFrac = (ip == ip_oil) + ? -volFracScaleInv : volFracScaleInv; + + if( phaseCapPressure <= maxCapPres_eps && phaseCapPressure >= entryPressure ) + { + // intermediate value + real64 const val = pow( entryPressure, exponentInv) / pow( phaseCapPressure , exponentInv + 1 ); + + value = (phaseCapPressure * val) * volFracScaleInv + phaseMinVolumeFraction; // entryPressure * (S_w)^( - 1 / exponentInv ) + dPhaseCapPressure_dVolFrac = -dScaledWettingPhaseVolFrac_dVolFrac * val * exponentInv; + phaseVolFraction = (ip == ip_oil) ? 1.0 - value : value; + } + else // enforce a constant and bounded capillary pressure + { + real64 const val = (phaseCapPressure > maxCapPres_eps) + ? pow( entryPressure, exponentInv) / pow( maxCapPres_eps , exponentInv) : 1.0; + value = val * volFracScaleInv + phaseMinVolumeFraction; + phaseVolFraction = (ip == ip_oil) ? 1.0 - value : value; + } + +} + } // namespace constitutive diff --git a/src/coreComponents/constitutive/capillaryPressure/CapillaryPressureSelector.hpp b/src/coreComponents/constitutive/capillaryPressure/CapillaryPressureSelector.hpp index 90c362850b6..c9b96e018b7 100644 --- a/src/coreComponents/constitutive/capillaryPressure/CapillaryPressureSelector.hpp +++ b/src/coreComponents/constitutive/capillaryPressure/CapillaryPressureSelector.hpp @@ -36,24 +36,24 @@ template< typename LAMBDA > void constitutiveUpdatePassThru( CapillaryPressureBase const & capPres, LAMBDA && lambda ) { - ConstitutivePassThruHandler< - BrooksCoreyCapillaryPressure, - JFunctionCapillaryPressure, - TableCapillaryPressure, - VanGenuchtenCapillaryPressure - >::execute( capPres, std::forward< LAMBDA >( lambda ) ); + ConstitutivePassThruHandler< + BrooksCoreyCapillaryPressure, + JFunctionCapillaryPressure, + TableCapillaryPressure, + VanGenuchtenCapillaryPressure + >::execute( capPres, std::forward< LAMBDA >( lambda ) ); } template< typename LAMBDA > void constitutiveUpdatePassThru( CapillaryPressureBase & capPres, LAMBDA && lambda ) { - ConstitutivePassThruHandler< - BrooksCoreyCapillaryPressure, - JFunctionCapillaryPressure, - TableCapillaryPressure, - VanGenuchtenCapillaryPressure - >::execute( capPres, std::forward< LAMBDA >( lambda ) ); + ConstitutivePassThruHandler< + BrooksCoreyCapillaryPressure, + JFunctionCapillaryPressure, + TableCapillaryPressure, + VanGenuchtenCapillaryPressure + >::execute( capPres, std::forward< LAMBDA >( lambda ) ); } } // namespace constitutive diff --git a/src/coreComponents/constitutive/capillaryPressure/JFunctionCapillaryPressure.cpp b/src/coreComponents/constitutive/capillaryPressure/JFunctionCapillaryPressure.cpp index 687aff531cb..738efb7b77f 100644 --- a/src/coreComponents/constitutive/capillaryPressure/JFunctionCapillaryPressure.cpp +++ b/src/coreComponents/constitutive/capillaryPressure/JFunctionCapillaryPressure.cpp @@ -120,10 +120,11 @@ JFunctionCapillaryPressure::JFunctionCapillaryPressure( std::string const & name registerWrapper( viewKeyStruct::jFunctionWrappersString(), &m_jFuncKernelWrappers ). setSizedFromParent( 0 ). setRestartFlags( RestartFlags::NO_WRITE ); - + registerWrapper( viewKeyStruct::inverseJFunctionWrappersString(), &m_inverseJFuncKernelWrappers ). setSizedFromParent( 0 ). setRestartFlags( RestartFlags::NO_WRITE ); + } void JFunctionCapillaryPressure::postInputInitialization() @@ -315,36 +316,36 @@ void JFunctionCapillaryPressure::createAllTableKernelWrappers() auto const & satArrayView = jFuncTable.getCoordinates()[0]; auto const & jArrayView = jFuncTable.getValues(); - std::vector satVec( satArrayView.size() ); - std::vector jVec( jArrayView.size() ); + std::vector< real64 > satVec( satArrayView.size() ); + std::vector< real64 > jVec( jArrayView.size() ); std::copy( satArrayView.begin(), satArrayView.end(), satVec.begin() ); std::copy( jArrayView.begin(), jArrayView.end(), jVec.begin() ); // Reverse both arrays (if original J is decreasing in S) -std::reverse( jVec.begin(), jVec.end() ); -std::reverse( satVec.begin(), satVec.end() ); + std::reverse( jVec.begin(), jVec.end() ); + std::reverse( satVec.begin(), satVec.end() ); + - -auto inverseTable = std::make_shared( "inverseJFunc", this ); + auto inverseTable = std::make_shared< TableFunction >( "inverseJFunc", this ); -real64_array invJVec( jVec.size() ); -real64_array invSatVec( satVec.size() ); -std::copy( jVec.begin(), jVec.end(), invJVec.data() ); -std::copy( satVec.begin(), satVec.end(), invSatVec.data() ); + real64_array invJVec( jVec.size() ); + real64_array invSatVec( satVec.size() ); + std::copy( jVec.begin(), jVec.end(), invJVec.data() ); + std::copy( satVec.begin(), satVec.end(), invSatVec.data() ); -array1d< real64_array > coordinates; -coordinates.emplace_back( std::move( invJVec ) ); + array1d< real64_array > coordinates; + coordinates.emplace_back( std::move( invJVec ) ); -std::vector< units::Unit > dimUnits = { units::Unknown }; // or actual unit if available + std::vector< units::Unit > dimUnits = { units::Unknown }; // or actual unit if available -inverseTable->setTableCoordinates( coordinates, dimUnits ); -inverseTable->setTableValues( std::move( invSatVec ), units::Unknown ); -inverseTable->setInterpolationMethod( TableFunction::InterpolationType::Linear ); + inverseTable->setTableCoordinates( coordinates, dimUnits ); + inverseTable->setTableValues( std::move( invSatVec ), units::Unknown ); + inverseTable->setInterpolationMethod( TableFunction::InterpolationType::Linear ); -m_inverseJFuncKernelWrappers.emplace_back( inverseTable->createKernelWrapper() ); -m_inverseTables.emplace_back( std::move( inverseTable ) ); + m_inverseJFuncKernelWrappers.emplace_back( inverseTable->createKernelWrapper() ); + m_inverseTables.emplace_back( std::move( inverseTable ) ); } else if( numPhases == 3 ) diff --git a/src/coreComponents/constitutive/capillaryPressure/JFunctionCapillaryPressure.hpp b/src/coreComponents/constitutive/capillaryPressure/JFunctionCapillaryPressure.hpp index 89bb6e7ef2c..80815e98236 100644 --- a/src/coreComponents/constitutive/capillaryPressure/JFunctionCapillaryPressure.hpp +++ b/src/coreComponents/constitutive/capillaryPressure/JFunctionCapillaryPressure.hpp @@ -82,7 +82,7 @@ class JFunctionCapillaryPressure : public CapillaryPressureBase void computeInv( arraySlice1d< real64, compflow::USD_PHASE - 1 > const & phaseVolFraction, arraySlice1d< real64 const > const & jFuncMultiplier, arraySlice1d< real64 const, cappres::USD_CAPPRES - 2 > const & phaseCapPres, - arraySlice2d< real64, cappres::USD_CAPPRES_DS - 2 > const & dPhaseCapPres_dPhaseVolFrac ) const; + arraySlice2d< real64, cappres::USD_CAPPRES_DS - 2 > const & dPhaseCapPres_dPhaseVolFrac ) const; GEOS_HOST_DEVICE @@ -181,7 +181,7 @@ class JFunctionCapillaryPressure : public CapillaryPressureBase array1d< TableFunction::KernelWrapper > m_jFuncKernelWrappers; array1d< TableFunction::KernelWrapper > m_inverseJFuncKernelWrappers; - std::vector< std::shared_ptr > m_inverseTables; + std::vector< std::shared_ptr< TableFunction > > m_inverseTables; }; @@ -260,9 +260,9 @@ GEOS_HOST_DEVICE inline void JFunctionCapillaryPressure::KernelWrapper:: computeInv( arraySlice1d< real64, compflow::USD_PHASE - 1 > const & phaseVolFraction, - arraySlice1d< real64 const > const & jFuncMultiplier, - arraySlice1d< real64 const, cappres::USD_CAPPRES - 2 > const & phaseCapPres, - arraySlice2d< real64, cappres::USD_CAPPRES_DS - 2 > const & dPhaseCapPres_dPhaseVolFrac ) const + arraySlice1d< real64 const > const & jFuncMultiplier, + arraySlice1d< real64 const, cappres::USD_CAPPRES - 2 > const & phaseCapPres, + arraySlice2d< real64, cappres::USD_CAPPRES_DS - 2 > const & dPhaseCapPres_dPhaseVolFrac ) const { LvArray::forValuesInSlice( dPhaseCapPres_dPhaseVolFrac, []( real64 & val ){ val = 0.0; } ); @@ -271,24 +271,24 @@ JFunctionCapillaryPressure::KernelWrapper:: integer const ipOil = m_phaseOrder[PT::OIL]; integer const ipGas = m_phaseOrder[PT::GAS]; - // apply multiplier + // apply multiplier real64 capPresWater_J = phaseCapPres[ipWater] / jFuncMultiplier[0]; - // std::cout << GEOS_FMT( " JM_2 = ( {:4.2e} )", jFuncMultiplier[0] ); - array1d input(1); + // std::cout << GEOS_FMT( " JM_2 = ( {:4.2e} )", jFuncMultiplier[0] ); + array1d< real64 > input( 1 ); input[0] = capPresWater_J; - // std::cout << GEOS_FMT( " J_int2 = ( {:4.2e} )", input[0] ); - // std::cout << GEOS_FMT( " Pc_int2 = ( {:4.2e} )", phaseCapPres[ipWater] ); + // std::cout << GEOS_FMT( " J_int2 = ( {:4.2e} )", input[0] ); + // std::cout << GEOS_FMT( " Pc_int2 = ( {:4.2e} )", phaseCapPres[ipWater] ); auto inputSlice = input.toSliceConst(); - phaseVolFraction[ipWater] = - m_inverseJFuncKernelWrappers[0].compute( inputSlice, - &(dPhaseCapPres_dPhaseVolFrac)[ipWater][ipWater] ); - dPhaseCapPres_dPhaseVolFrac[ipWater][ipWater] /= jFuncMultiplier[0]; - // std::cout << GEOS_FMT( " S_int2 = ( {:4.2e} )", phaseVolFraction[ipWater] ); - // std::cout << GEOS_FMT( " dS/dP = ( {:4.2e} )", dPhaseCapPres_dPhaseVolFrac[ipWater][ipWater] ); - phaseVolFraction[ipGas] = 1.0 - phaseVolFraction[ipWater]; + phaseVolFraction[ipWater] = + m_inverseJFuncKernelWrappers[0].compute( inputSlice, + &(dPhaseCapPres_dPhaseVolFrac)[ipWater][ipWater] ); + dPhaseCapPres_dPhaseVolFrac[ipWater][ipWater] /= jFuncMultiplier[0]; + // std::cout << GEOS_FMT( " S_int2 = ( {:4.2e} )", phaseVolFraction[ipWater] ); + // std::cout << GEOS_FMT( " dS/dP = ( {:4.2e} )", dPhaseCapPres_dPhaseVolFrac[ipWater][ipWater] ); + phaseVolFraction[ipGas] = 1.0 - phaseVolFraction[ipWater]; } GEOS_HOST_DEVICE diff --git a/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressure.cpp b/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressure.cpp index 2304238b540..0471bacb6a8 100644 --- a/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressure.cpp +++ b/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressure.cpp @@ -66,6 +66,10 @@ TableCapillaryPressure::TableCapillaryPressure( std::string const & name, registerWrapper( viewKeyStruct::capPresWrappersString(), &m_capPresKernelWrappers ). setSizedFromParent( 0 ). setRestartFlags( RestartFlags::NO_WRITE ); + + registerWrapper( viewKeyStruct::inverseCapPresWrappersString(), &m_inverseCapPresWrappers ). + setSizedFromParent( 0 ). + setRestartFlags( RestartFlags::NO_WRITE ); } void TableCapillaryPressure::postInputInitialization() @@ -148,23 +152,63 @@ void TableCapillaryPressure::createAllTableKernelWrappers() // we want to make sure that the wrappers are always up-to-date, so we recreate them everytime m_capPresKernelWrappers.clear(); + m_inverseCapPresWrappers.clear(); + if( numPhases == 2 ) { TableFunction const & capPresTable = functionManager.getGroup< TableFunction >( m_wettingNonWettingCapPresTableName ); m_capPresKernelWrappers.emplace_back( capPresTable.createKernelWrapper() ); + + auto const & satArrayView = capPresTable.getCoordinates()[0]; + auto const & capPresArrayView = capPresTable.getValues(); + + std::vector< real64 > satVec( satArrayView.size() ); + std::vector< real64 > pcVec( capPresArrayView.size() ); + + std::copy( satArrayView.begin(), satArrayView.end(), satVec.begin() ); + std::copy( capPresArrayView.begin(), capPresArrayView.end(), pcVec.begin() ); + + // Reverse both arrays (if original J is decreasing in S) + std::reverse( pcVec.begin(), pcVec.end() ); + std::reverse( satVec.begin(), satVec.end() ); + + + auto inverseTable = std::make_shared< TableFunction >( "inverseJFunc", this ); + + real64_array invPcVec( pcVec.size() ); + real64_array invSatVec( satVec.size() ); + std::copy( pcVec.begin(), pcVec.end(), invPcVec.data() ); + std::copy( satVec.begin(), satVec.end(), invSatVec.data() ); + + array1d< real64_array > coordinates; + coordinates.emplace_back( std::move( invPcVec ) ); + + + std::vector< units::Unit > dimUnits = { units::Unknown }; // or actual unit if available + + inverseTable->setTableCoordinates( coordinates, dimUnits ); + inverseTable->setTableValues( std::move( invSatVec ), units::Unknown ); + inverseTable->setInterpolationMethod( TableFunction::InterpolationType::Linear ); + + m_inverseCapPresWrappers.emplace_back( inverseTable->createKernelWrapper() ); + m_inverseTables.emplace_back( std::move( inverseTable ) ); + } else if( numPhases == 3 ) { TableFunction const & capPresTableWI = functionManager.getGroup< TableFunction >( m_wettingIntermediateCapPresTableName ); m_capPresKernelWrappers.emplace_back( capPresTableWI.createKernelWrapper() ); + m_inverseCapPresWrappers.emplace_back( capPresTableWI.createKernelWrapper() ); TableFunction const & capPresTableNWI = functionManager.getGroup< TableFunction >( m_nonWettingIntermediateCapPresTableName ); m_capPresKernelWrappers.emplace_back( capPresTableNWI.createKernelWrapper() ); + m_inverseCapPresWrappers.emplace_back( capPresTableNWI.createKernelWrapper() ); } } TableCapillaryPressure::KernelWrapper:: KernelWrapper( arrayView1d< TableFunction::KernelWrapper const > const & capPresKernelWrappers, + arrayView1d< TableFunction::KernelWrapper const > const & inverseCapPresWrappers, arrayView1d< integer const > const & phaseTypes, arrayView1d< integer const > const & phaseOrder, arrayView3d< real64, cappres::USD_CAPPRES > const & phaseCapPres, @@ -173,7 +217,8 @@ TableCapillaryPressure::KernelWrapper:: phaseOrder, phaseCapPres, dPhaseCapPres_dPhaseVolFrac ), - m_capPresKernelWrappers( capPresKernelWrappers ) + m_capPresKernelWrappers( capPresKernelWrappers ), + m_inverseCapPresWrappers( inverseCapPresWrappers ) {} TableCapillaryPressure::KernelWrapper @@ -181,6 +226,7 @@ TableCapillaryPressure::createKernelWrapper() { createAllTableKernelWrappers(); return KernelWrapper( m_capPresKernelWrappers, + m_inverseCapPresWrappers, m_phaseTypes, m_phaseOrder, m_phaseCapPressure, diff --git a/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressure.hpp b/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressure.hpp index 602946c55de..949d431792a 100644 --- a/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressure.hpp +++ b/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressure.hpp @@ -55,6 +55,7 @@ class TableCapillaryPressure : public CapillaryPressureBase public: KernelWrapper( arrayView1d< TableFunction::KernelWrapper const > const & capPresKernelWrappers, + arrayView1d< TableFunction::KernelWrapper const > const & inverseCapPresWrappers, arrayView1d< integer const > const & phaseTypes, arrayView1d< integer const > const & phaseOrder, arrayView3d< real64, cappres::USD_CAPPRES > const & phaseCapPres, @@ -67,8 +68,8 @@ class TableCapillaryPressure : public CapillaryPressureBase GEOS_HOST_DEVICE void computeInv( arraySlice1d< real64, compflow::USD_PHASE - 1 > const & phaseVolFraction, - arraySlice1d< real64 const, cappres::USD_CAPPRES - 2 > const & phaseCapPres, - arraySlice2d< real64, cappres::USD_CAPPRES_DS - 2 > const & dPhaseCapPres_dPhaseVolFrac ) const; + arraySlice1d< real64 const, cappres::USD_CAPPRES - 2 > const & phaseCapPres, + arraySlice2d< real64, cappres::USD_CAPPRES_DS - 2 > const & dPhaseCapPres_dPhaseVolFrac ) const; GEOS_HOST_DEVICE @@ -81,6 +82,7 @@ class TableCapillaryPressure : public CapillaryPressureBase /// Array of kernel wrappers for the capillary pressures /// Is of size 1 for two-phase flow, and of size 2 for three-phase flow arrayView1d< TableFunction::KernelWrapper const > const m_capPresKernelWrappers; + arrayView1d< TableFunction::KernelWrapper const > const m_inverseCapPresWrappers; }; @@ -97,6 +99,7 @@ class TableCapillaryPressure : public CapillaryPressureBase static constexpr char const * wettingIntermediateCapPresTableNameString() { return "wettingIntermediateCapPressureTableName"; } static constexpr char const * nonWettingIntermediateCapPresTableNameString() { return "nonWettingIntermediateCapPressureTableName"; } static constexpr char const * capPresWrappersString() { return "capPresWrappers"; } + static constexpr char const * inverseCapPresWrappersString() { return "inverseCapPresWrappers"; } }; @@ -122,6 +125,9 @@ class TableCapillaryPressure : public CapillaryPressureBase /// Capillary pressure kernel wrapper for the first pair (wetting-intermediate if NP=3, wetting-non-wetting otherwise) array1d< TableFunction::KernelWrapper > m_capPresKernelWrappers; + array1d< TableFunction::KernelWrapper > m_inverseCapPresWrappers; + + std::vector< std::shared_ptr > m_inverseTables; }; @@ -183,24 +189,33 @@ GEOS_HOST_DEVICE inline void TableCapillaryPressure::KernelWrapper:: computeInv( arraySlice1d< real64, compflow::USD_PHASE - 1 > const & phaseVolFraction, - arraySlice1d< real64 const, cappres::USD_CAPPRES - 2 > const & phaseCapPres, - arraySlice2d< real64, cappres::USD_CAPPRES_DS - 2 > const & dPhaseCapPres_dPhaseVolFrac ) const + arraySlice1d< real64 const, cappres::USD_CAPPRES - 2 > const & phaseCapPres, + arraySlice2d< real64, cappres::USD_CAPPRES_DS - 2 > const & dPhaseCapPres_dPhaseVolFrac ) const { LvArray::forValuesInSlice( dPhaseCapPres_dPhaseVolFrac, []( real64 & val ){ val = 0.0; } ); using PT = CapillaryPressureBase::PhaseType; integer const ipWater = m_phaseOrder[PT::WATER]; - // integer const ipOil = m_phaseOrder[PT::OIL]; - // integer const ipGas = m_phaseOrder[PT::GAS]; + integer const ipOil = m_phaseOrder[PT::OIL]; + integer const ipGas = m_phaseOrder[PT::GAS]; - // put capillary pressure on the wetting phase + // put capillary pressure on the wetting phase + real64 capPresWater = phaseCapPres[ipWater]; + array1d input(1); + input[0] = capPresWater; + auto inputSlice = input.toSliceConst(); - phaseVolFraction[ipWater] = - m_capPresKernelWrappers[0].compute( &(phaseCapPres)[ipWater], - &(dPhaseCapPres_dPhaseVolFrac)[ipWater][ipWater] ); + phaseVolFraction[ipWater] = + m_capPresKernelWrappers[0].compute( &(phaseCapPres)[ipWater], + &(dPhaseCapPres_dPhaseVolFrac)[ipWater][ipWater] ); + phaseVolFraction[ipWater] = + m_inverseCapPresWrappers[0].compute( inputSlice, + &(dPhaseCapPres_dPhaseVolFrac)[ipWater][ipWater] ); + phaseVolFraction[ipGas] = 1.0 - phaseVolFraction[ipWater]; } + GEOS_HOST_DEVICE inline void TableCapillaryPressure::KernelWrapper:: diff --git a/src/coreComponents/constitutive/capillaryPressure/VanGenuchtenCapillaryPressure.hpp b/src/coreComponents/constitutive/capillaryPressure/VanGenuchtenCapillaryPressure.hpp index 14944dd980b..d068bfd6543 100644 --- a/src/coreComponents/constitutive/capillaryPressure/VanGenuchtenCapillaryPressure.hpp +++ b/src/coreComponents/constitutive/capillaryPressure/VanGenuchtenCapillaryPressure.hpp @@ -56,6 +56,11 @@ class VanGenuchtenCapillaryPressureUpdate final : public CapillaryPressureBaseUp void compute( arraySlice1d< real64 const, compflow::USD_PHASE - 1 > const & phaseVolFraction, arraySlice1d< real64, cappres::USD_CAPPRES - 2 > const & phaseCapPres, arraySlice2d< real64, cappres::USD_CAPPRES_DS - 2 > const & dPhaseCapPres_dPhaseVolFrac ) const; + + GEOS_HOST_DEVICE + void computeInv( arraySlice1d< real64 const, compflow::USD_PHASE - 1 > const & phaseVolFraction, + arraySlice1d< real64, cappres::USD_CAPPRES - 2 > const & phaseCapPres, + arraySlice2d< real64, cappres::USD_CAPPRES_DS - 2 > const & dPhaseCapPres_dPhaseVolFrac ) const; GEOS_HOST_DEVICE virtual void update( localIndex const k, @@ -191,6 +196,69 @@ VanGenuchtenCapillaryPressureUpdate:: } } +GEOS_HOST_DEVICE +inline void +VanGenuchtenCapillaryPressureUpdate:: + computeInv( arraySlice1d< real64 const, compflow::USD_PHASE - 1 > const & phaseVolFraction, + arraySlice1d< real64, cappres::USD_CAPPRES - 2 > const & phaseCapPres, + arraySlice2d< real64, cappres::USD_CAPPRES_DS - 2 > const & dPhaseCapPres_dPhaseVolFrac ) const +{ + LvArray::forValuesInSlice( dPhaseCapPres_dPhaseVolFrac, []( real64 & val ){ val = 0.0; } ); + + // the VanGenuchten model does not support volFracScaled = 0 and = 1 + // hence we need an epsilon value to avoid a division by zero + // TODO: for S < epsilon and S > 1 - epsilon, replace the original unbounded VG curve with a bounded power-law + // extension + real64 const eps = m_capPressureEpsilon; + real64 const volFracScaleInv = 1.0 / m_volFracScale; + + // compute first water-oil capillary pressure as a function of water-phase vol fraction + integer const ip_water = m_phaseOrder[CapillaryPressureBase::PhaseType::WATER]; + if( ip_water >= 0 ) + { + + real64 const volFracScaled = (phaseVolFraction[ip_water] - m_phaseMinVolumeFraction[ip_water]) * volFracScaleInv; + real64 const exponentInv = m_phaseCapPressureExponentInv[ip_water]; // div by 0 taken care of by initialization + // check + real64 const multiplier = m_phaseCapPressureMultiplier[ip_water]; + + real64 const scaledWettingVolFrac = volFracScaled; + real64 const dScaledWettingPhaseVolFrac_dVolFrac = volFracScaleInv; + + evaluateVanGenuchtenFunction( scaledWettingVolFrac, + dScaledWettingPhaseVolFrac_dVolFrac, + exponentInv, + multiplier, + eps, + phaseCapPres[ip_water], + dPhaseCapPres_dPhaseVolFrac[ip_water][ip_water] ); + + } + + + // then compute the oil-gas capillary pressure as a function of gas-phase vol fraction + integer const ip_gas = m_phaseOrder[CapillaryPressureBase::PhaseType::GAS]; + if( ip_gas >= 0 ) + { + real64 const volFracScaled = (phaseVolFraction[ip_gas] - m_phaseMinVolumeFraction[ip_gas]) * volFracScaleInv; + real64 const exponentInv = m_phaseCapPressureExponentInv[ip_gas]; // div by 0 taken care of by initialization + // check + real64 const multiplier = -m_phaseCapPressureMultiplier[ip_gas]; // for gas capillary pressure, take the opposite + // of the VG function + + real64 const scaledWettingVolFrac = 1-volFracScaled; + real64 const dScaledWettingPhaseVolFrac_dVolFrac = -volFracScaleInv; + + evaluateVanGenuchtenFunction( scaledWettingVolFrac, + dScaledWettingPhaseVolFrac_dVolFrac, + exponentInv, + multiplier, + eps, + phaseCapPres[ip_gas], + dPhaseCapPres_dPhaseVolFrac[ip_gas][ip_gas] ); + } +} + GEOS_HOST_DEVICE GEOS_FORCE_INLINE void diff --git a/src/coreComponents/constitutive/unitTests/FluidModelTest_impl.hpp b/src/coreComponents/constitutive/unitTests/FluidModelTest_impl.hpp index 72cfec6501c..ce731e6b775 100644 --- a/src/coreComponents/constitutive/unitTests/FluidModelTest_impl.hpp +++ b/src/coreComponents/constitutive/unitTests/FluidModelTest_impl.hpp @@ -35,7 +35,7 @@ template< typename FLUID_TYPE, integer NUM_COMP, integer NUM_PHASE > FluidModelTest< FLUID_TYPE, NUM_COMP, NUM_PHASE >::FluidModelTest(): m_parent( "parent", m_node ) { - createFunctionManager(); + // createFunctionManager(); } template< typename FLUID_TYPE, integer NUM_COMP, integer NUM_PHASE > diff --git a/src/coreComponents/finiteVolume/CellElementStencilTPFA.hpp b/src/coreComponents/finiteVolume/CellElementStencilTPFA.hpp index 391d614baba..5c468d293cf 100644 --- a/src/coreComponents/finiteVolume/CellElementStencilTPFA.hpp +++ b/src/coreComponents/finiteVolume/CellElementStencilTPFA.hpp @@ -71,19 +71,19 @@ class CellElementStencilTPFAWrapper : public StencilWrapperBase< TwoPointStencil real64 ( &weight )[1][2], real64 ( &dWeight_dVar )[1][2] ) const; /** - * @brief Compute half weights and derivatives w.r.t to one variable. - * @param[in] iconn connection index - * @param[in] coefficient view accessor to the coefficient used to compute the weights - * @param[in] dCoeff_dVar view accessor to the derivative of the coefficient w.r.t to the variable - * @param[out] weight view weights - * @param[out] dWeight_dVar derivative of the weights w.r.t to the variable - */ + * @brief Compute half weights and derivatives w.r.t to one variable. + * @param[in] iconn connection index + * @param[in] coefficient view accessor to the coefficient used to compute the weights + * @param[in] dCoeff_dVar view accessor to the derivative of the coefficient w.r.t to the variable + * @param[out] weight view weights + * @param[out] dWeight_dVar derivative of the weights w.r.t to the variable + */ GEOS_HOST_DEVICE void computeHalfWeights( localIndex const iconn, - CoefficientAccessor< arrayView3d< real64 const > > const & coefficient, - CoefficientAccessor< arrayView3d< real64 const > > const & dCoeff_dVar, - real64 ( &weight )[1][2], - real64 ( &dWeight_dVar )[1][2] ) const; + CoefficientAccessor< arrayView3d< real64 const > > const & coefficient, + CoefficientAccessor< arrayView3d< real64 const > > const & dCoeff_dVar, + real64 ( &weight )[1][2], + real64 ( &dWeight_dVar )[1][2] ) const; /** * @brief Compute weights and derivatives w.r.t to one variable without coefficient @@ -311,10 +311,10 @@ GEOS_HOST_DEVICE inline void CellElementStencilTPFAWrapper:: computeHalfWeights( localIndex const iconn, - CoefficientAccessor< arrayView3d< real64 const > > const & coefficient, - CoefficientAccessor< arrayView3d< real64 const > > const & dCoeff_dVar, - real64 (& weight)[1][2], - real64 (& dWeight_dVar )[1][2] ) const + CoefficientAccessor< arrayView3d< real64 const > > const & coefficient, + CoefficientAccessor< arrayView3d< real64 const > > const & dCoeff_dVar, + real64 (& weight)[1][2], + real64 (& dWeight_dVar )[1][2] ) const { real64 halfWeight[2]; real64 dHalfWeight_dVar[2]; @@ -371,8 +371,10 @@ CellElementStencilTPFAWrapper:: // real64 dHarmonicWeight_dVar[2]; // real64 dArithmeticWeight_dVar[2]; - // dHarmonicWeight_dVar[0] = sum > 0 ? (dHalfWeight_dVar[0]*sum*halfWeight[1] - dHalfWeight_dVar[0]*halfWeight[0]*halfWeight[1]) / ( sum*sum ) : 0.0; - // dHarmonicWeight_dVar[1] = sum > 0 ? (dHalfWeight_dVar[1]*sum*halfWeight[0] - dHalfWeight_dVar[1]*halfWeight[1]*halfWeight[0]) / ( sum*sum ) : 0.0; + // dHarmonicWeight_dVar[0] = sum > 0 ? (dHalfWeight_dVar[0]*sum*halfWeight[1] - dHalfWeight_dVar[0]*halfWeight[0]*halfWeight[1]) / ( + // sum*sum ) : 0.0; + // dHarmonicWeight_dVar[1] = sum > 0 ? (dHalfWeight_dVar[1]*sum*halfWeight[0] - dHalfWeight_dVar[1]*halfWeight[1]*halfWeight[0]) / ( + // sum*sum ) : 0.0; // dArithmeticWeight_dVar[0] = dHalfWeight_dVar[0] / 2; // dArithmeticWeight_dVar[1] = dHalfWeight_dVar[1] / 2; diff --git a/src/coreComponents/finiteVolume/EmbeddedSurfaceToCellStencil.hpp b/src/coreComponents/finiteVolume/EmbeddedSurfaceToCellStencil.hpp index 27462c5b516..4a191ca7614 100644 --- a/src/coreComponents/finiteVolume/EmbeddedSurfaceToCellStencil.hpp +++ b/src/coreComponents/finiteVolume/EmbeddedSurfaceToCellStencil.hpp @@ -109,10 +109,10 @@ class EmbeddedSurfaceToCellStencilWrapper : public StencilWrapperBase< TwoPointS GEOS_HOST_DEVICE void computeHalfWeights( localIndex const iconn, - CoefficientAccessor< arrayView3d< real64 const > > const & coefficient, - CoefficientAccessor< arrayView3d< real64 const > > const & dCoeff_dVar, - real64 ( &weight )[1][2], - real64 ( &dWeight_dVar )[1][2] ) const; + CoefficientAccessor< arrayView3d< real64 const > > const & coefficient, + CoefficientAccessor< arrayView3d< real64 const > > const & dCoeff_dVar, + real64 ( &weight )[1][2], + real64 ( &dWeight_dVar )[1][2] ) const; /** * @brief Compute weigths and derivatives w.r.t to one variable without coefficient @@ -263,10 +263,10 @@ GEOS_HOST_DEVICE inline void EmbeddedSurfaceToCellStencilWrapper:: computeHalfWeights( localIndex iconn, - CoefficientAccessor< arrayView3d< real64 const > > const & coefficient, - CoefficientAccessor< arrayView3d< real64 const > > const & dCoeff_dVar, - real64 ( & weight )[1][2], - real64 ( & dWeight_dVar )[1][2] ) const + CoefficientAccessor< arrayView3d< real64 const > > const & coefficient, + CoefficientAccessor< arrayView3d< real64 const > > const & dCoeff_dVar, + real64 ( & weight )[1][2], + real64 ( & dWeight_dVar )[1][2] ) const { localIndex const er0 = m_elementRegionIndices[iconn][0]; localIndex const esr0 = m_elementSubRegionIndices[iconn][0]; diff --git a/src/coreComponents/finiteVolume/FaceElementToCellStencil.hpp b/src/coreComponents/finiteVolume/FaceElementToCellStencil.hpp index a01a4541e85..2376fd89ccf 100644 --- a/src/coreComponents/finiteVolume/FaceElementToCellStencil.hpp +++ b/src/coreComponents/finiteVolume/FaceElementToCellStencil.hpp @@ -107,19 +107,19 @@ class FaceElementToCellStencilWrapper : public StencilWrapperBase< TwoPointStenc real64 ( &dWeight_dVar )[1][2] ) const; /** - * @brief Compute half weigths and derivatives w.r.t to one variable. - * @param[in] iconn connection index - * @param[in] coefficient view accessor to the coefficient used to compute the weights - * @param[in] dCoeff_dVar view accessor to the derivative of the coefficient w.r.t to the variable - * @param[out] weight view weights - * @param[out] dWeight_dVar derivative of the weigths w.r.t to the variable - */ + * @brief Compute half weigths and derivatives w.r.t to one variable. + * @param[in] iconn connection index + * @param[in] coefficient view accessor to the coefficient used to compute the weights + * @param[in] dCoeff_dVar view accessor to the derivative of the coefficient w.r.t to the variable + * @param[out] weight view weights + * @param[out] dWeight_dVar derivative of the weigths w.r.t to the variable + */ GEOS_HOST_DEVICE void computeHalfWeights( localIndex iconn, - CoefficientAccessor< arrayView3d< real64 const > > const & coefficient, - CoefficientAccessor< arrayView3d< real64 const > > const & dCoeff_dVar, - real64 ( &weight )[1][2], - real64 ( &dWeight_dVar )[1][2] ) const; + CoefficientAccessor< arrayView3d< real64 const > > const & coefficient, + CoefficientAccessor< arrayView3d< real64 const > > const & dCoeff_dVar, + real64 ( &weight )[1][2], + real64 ( &dWeight_dVar )[1][2] ) const; /** * @brief Compute weigths and derivatives w.r.t to one variable without coefficient @@ -307,10 +307,10 @@ inline void FaceElementToCellStencilWrapper:: GEOS_HOST_DEVICE inline void FaceElementToCellStencilWrapper:: computeHalfWeights( localIndex const iconn, - CoefficientAccessor< arrayView3d< real64 const > > const & coefficient, - CoefficientAccessor< arrayView3d< real64 const > > const & dCoeff_dVar, - real64 ( & weight )[1][2], - real64 ( & dWeight_dVar )[1][2] ) const + CoefficientAccessor< arrayView3d< real64 const > > const & coefficient, + CoefficientAccessor< arrayView3d< real64 const > > const & dCoeff_dVar, + real64 ( & weight )[1][2], + real64 ( & dWeight_dVar )[1][2] ) const { localIndex const er0 = m_elementRegionIndices[iconn][0]; localIndex const esr0 = m_elementSubRegionIndices[iconn][0]; diff --git a/src/coreComponents/finiteVolume/SurfaceElementStencil.hpp b/src/coreComponents/finiteVolume/SurfaceElementStencil.hpp index 2f0feb536fd..4c982dbef4a 100644 --- a/src/coreComponents/finiteVolume/SurfaceElementStencil.hpp +++ b/src/coreComponents/finiteVolume/SurfaceElementStencil.hpp @@ -120,10 +120,10 @@ class SurfaceElementStencilWrapper : public StencilWrapperBase< SurfaceElementSt */ GEOS_HOST_DEVICE void computeHalfWeights( localIndex iconn, - CoefficientAccessor< arrayView3d< real64 const > > const & coefficient, - CoefficientAccessor< arrayView3d< real64 const > > const & dCoeff_dVar, - real64 ( &weight )[maxNumConnections][2], - real64 ( &dWeight_dVar )[maxNumConnections][2] ) const; + CoefficientAccessor< arrayView3d< real64 const > > const & coefficient, + CoefficientAccessor< arrayView3d< real64 const > > const & dCoeff_dVar, + real64 ( &weight )[maxNumConnections][2], + real64 ( &dWeight_dVar )[maxNumConnections][2] ) const; /** * @brief Compute weights and derivatives w.r.t to one variable without coefficient @@ -383,10 +383,10 @@ GEOS_HOST_DEVICE inline void SurfaceElementStencilWrapper:: computeHalfWeights( localIndex iconn, - CoefficientAccessor< arrayView3d< real64 const > > const & coefficient, - CoefficientAccessor< arrayView3d< real64 const > > const & dCoeff_dVar, - real64 ( & weight )[maxNumConnections][2], - real64 ( & dWeight_dVar )[maxNumConnections][2] ) const + CoefficientAccessor< arrayView3d< real64 const > > const & coefficient, + CoefficientAccessor< arrayView3d< real64 const > > const & dCoeff_dVar, + real64 ( & weight )[maxNumConnections][2], + real64 ( & dWeight_dVar )[maxNumConnections][2] ) const { real64 sumOfTrans = 0.0; diff --git a/src/coreComponents/integrationTests/fluidFlowTests/testImmiscibleInterfaceConditions.cpp b/src/coreComponents/integrationTests/fluidFlowTests/testImmiscibleInterfaceConditions.cpp new file mode 100644 index 00000000000..95431c366a4 --- /dev/null +++ b/src/coreComponents/integrationTests/fluidFlowTests/testImmiscibleInterfaceConditions.cpp @@ -0,0 +1,677 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 TotalEnergies + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2023-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ +#define phase0MinSat1 0.0 +#define phase1MinSat1 0.0 +#define phase0MinSat2 0.0 +#define phase1MinSat2 0.0 + + +#include +#include + +#include "mainInterface/initialization.hpp" +#include "mainInterface/GeosxState.hpp" +#include "constitutive/fluid/twophaseimmisciblefluid/TwoPhaseImmiscibleFluid.hpp" +#include "physicsSolvers/PhysicsSolverManager.hpp" +#include "physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp" +#include "unitTests/fluidFlowTests/testCompFlowUtils.hpp" +#include "constitutive/unitTests/FluidModelTest.hpp" +#include "constitutive/unitTests/FluidModelTest_impl.hpp" +#include "common/initializeEnvironment.hpp" +#include "unitTests/constitutiveTests/constitutiveTestHelpers.hpp" +#include "functions/FunctionManager.hpp" +#include "constitutive/capillaryPressure/CapillaryPressureFields.hpp" + +#include + + + +using namespace geos; +using namespace geos::dataRepository; +using namespace geos::constitutive; +using namespace geos::testing; + +CommandLineOptions g_commandLineOptions; + +TwoPhaseImmiscibleFluid * makeTwoPhaseImmiscibleFluid( TwoPhaseImmiscibleFluid & fluid ) +{ + + FunctionManager & functionManager = FunctionManager::getInstance(); + + // 1D table with linear interpolation + localIndex constexpr Naxis = 6; + localIndex constexpr NaxisSingle = 1; + + real64_array densityCoordPhase0; + // fill( densityCoordPhase0, Feed< Naxis >{ 0.22, 0.3, 0.5, 0.6, 0.8, 1.0 } ); + for (auto v : {0.0}) + densityCoordPhase0.emplace_back(v); + real64_array densityValuesPhase0; + // fill( densityValuesPhase0, Feed< Naxis >{ 0.00603, 0.04224, 0.04224, 0.22423, 0.31311, 0.40203 } ); + for (auto v : {1000.0}) + densityValuesPhase0.emplace_back(v); + + real64_array densityCoordPhase1; + // fill( densityCoordPhase1, Feed< Naxis >{ 1.22, 1.3, 1.5, 1.6, 1.8, 2.0 } ); + for (auto v : {0.0}) + densityCoordPhase1.emplace_back(v); + real64_array densityValuesPhase1; + // fill( densityValuesPhase1, Feed< Naxis >{ 0.00603, 0.04224, 0.04224, 0.22423, 0.31311, 0.40203 } ); + for (auto v : {100.0}) + densityValuesPhase1.emplace_back(v); + + real64_array viscosityCoordPhase0; + // fill( viscosityCoordPhase0, Feed< Naxis >{ 0.22, 0.3, 0.5, 0.6, 0.8, 1.0 } ); + for (auto v : {0.0}) + viscosityCoordPhase0.emplace_back(v); + real64_array viscosityValuesPhase0; + // fill( viscosityValuesPhase0, Feed< Naxis >{ 40203, 31311, 22423, 15011, 4224, 603 } ); + for (auto v : {0.001}) + viscosityValuesPhase0.emplace_back(v); + + real64_array viscosityCoordPhase1; + // fill( viscosityCoordPhase1, Feed< NaxisSingle >{ 0.22 } ); + for (auto v : {0.0}) + viscosityCoordPhase1.emplace_back(v); + + real64_array viscosityValuesPhase1; + // fill( viscosityValuesPhase1, Feed< NaxisSingle >{ 45 } ); + for (auto v : {0.001}) + viscosityValuesPhase1.emplace_back(v); + + TableFunction & table_density0 = dynamicCast< TableFunction & >( *functionManager.createChild( "TableFunction", "densityTablePhase0" ) ); + array1d coords_density0; + coords_density0.emplace_back(densityCoordPhase0); + table_density0.setTableCoordinates( coords_density0, { units::Dimensionless } ); + table_density0.setTableValues( densityValuesPhase0, units::Dimensionless ); + table_density0.reInitializeFunction(); + + table_density0.setInterpolationMethod( TableFunction::InterpolationType::Linear ); + + TableFunction & table_density1 = dynamicCast< TableFunction & >( *functionManager.createChild( "TableFunction", "densityTablePhase1" ) ); + array1d coords_density1; + coords_density1.emplace_back(densityCoordPhase1); + table_density1.setTableCoordinates( coords_density1, { units::Dimensionless } ); + table_density1.setTableValues( densityValuesPhase1, units::Dimensionless ); + table_density1.reInitializeFunction(); + + table_density1.setInterpolationMethod( TableFunction::InterpolationType::Linear ); + + TableFunction & table_viscosity0 = dynamicCast< TableFunction & >( *functionManager.createChild( "TableFunction", "viscosityTablePhase0" ) ); + array1d coords_viscosity0; + coords_viscosity0.emplace_back(viscosityCoordPhase0); + table_viscosity0.setTableCoordinates( coords_viscosity0, { units::Dimensionless } ); + table_viscosity0.setTableValues( viscosityValuesPhase0, units::Dimensionless ); + table_viscosity0.reInitializeFunction(); + + table_viscosity0.setInterpolationMethod( TableFunction::InterpolationType::Linear ); + + TableFunction & table_viscosity1 = dynamicCast< TableFunction & >( *functionManager.createChild( "TableFunction", "viscosityTablePhase1" ) ); + array1d coords_viscosity1; + coords_viscosity1.emplace_back(viscosityCoordPhase1); + table_viscosity1.setTableCoordinates( coords_viscosity1, { units::Dimensionless } ); + table_viscosity1.setTableValues( viscosityValuesPhase1, units::Dimensionless ); + table_viscosity1.reInitializeFunction(); + + table_viscosity1.setInterpolationMethod( TableFunction::InterpolationType::Linear ); + + + // createTable( "densityTablePhase0", densityCoordPhase0, densityValuesPhase0 ); + // createTable( "densityTablePhase1", densityCoordPhase1, densityValuesPhase1 ); + // createTable( "viscosityTablePhase0", viscosityCoordPhase0, viscosityValuesPhase0 ); + // createTable( "viscosityTablePhase1", viscosityCoordPhase1, viscosityValuesPhase1 ); + + // 2) Set up the constitutive model + + string_array & phaseNames = fluid.getReference< string_array >( TwoPhaseImmiscibleFluid::viewKeyStruct::phaseNamesString() ); + phaseNames.emplace_back( "water" ); + phaseNames.emplace_back( "gas" ); + + string_array & densityTableNames = fluid.getReference< string_array >( TwoPhaseImmiscibleFluid::viewKeyStruct::densityTableNamesString() ); + densityTableNames.emplace_back( "densityTablePhase0" ); + densityTableNames.emplace_back( "densityTablePhase1" ); + + string_array & viscosityTableNames = fluid.getReference< string_array >( TwoPhaseImmiscibleFluid::viewKeyStruct::viscosityTableNamesString() ); + viscosityTableNames.emplace_back( "viscosityTablePhase0" ); + viscosityTableNames.emplace_back( "viscosityTablePhase1" ); + + fluid.postInputInitializationRecursive(); + fluid.initialize(); // to test all the checks + + return &fluid; +} + +CapillaryPressureBase & makeJFunctionCapPressureTwoPhase( string const & name, Group & parent ) +{ + FunctionManager & functionManager = FunctionManager::getInstance(); + + // 1) First, define the tables + + // // 1D table, various interpolation methods + // localIndex const Naxis = 12; + + // // Setup table + // array1d< real64_array > coordinates; + // coordinates.resize( 1 ); + // coordinates[0].resize( Naxis ); + + // coordinates[0][0] = 0.0; + // coordinates[0][1] = 0.05; + // coordinates[0][2] = 0.15; + // coordinates[0][3] = 0.25; + // coordinates[0][4] = 0.35; + // coordinates[0][5] = 0.45; + // coordinates[0][6] = 0.55; + // coordinates[0][7] = 0.65; + // coordinates[0][8] = 0.75; + // coordinates[0][9] = 0.85; + // coordinates[0][10] = 0.95; + // coordinates[0][11] = 1.0; + + // real64_array values( Naxis ); + // values[0] = 4.331729359; + // values[1] = 3.523266264; + // values[2] = 2.677103439; + // values[3] = 2.356150157; + // values[4] = 2.166062360; + // values[5] = 2.034158727; + // values[6] = 1.934627222; + // values[7] = 1.855494313; + // values[8] = 1.790286970; + // values[9] = 1.735134860; + // values[10] = 1.687551617; + // values[11] = 1.666049754; + + + localIndex const Naxis = 2; + + // Setup table + array1d< real64_array > coordinates; + coordinates.resize( 1 ); + coordinates[0].resize( Naxis ); + + coordinates[0][0] = 0.0; + coordinates[0][1] = 1.0; + + real64_array values( Naxis ); + values[0] = 4.331729359; + values[1] = 1.666049754; + + + TableFunction & table_w = dynamicCast< TableFunction & >( *functionManager.createChild( "TableFunction", "water_jFunction" ) ); + table_w.setTableCoordinates( coordinates, { units::Dimensionless } ); + table_w.setTableValues( values, units::Dimensionless ); + table_w.reInitializeFunction(); + + table_w.setInterpolationMethod( TableFunction::InterpolationType::Linear ); + + // 2) Then set up the constitutive model + + JFunctionCapillaryPressure & capPressure = parent.registerGroup< JFunctionCapillaryPressure >( name ); + + string_array & phaseNames = capPressure.getReference< string_array >( CapillaryPressureBase::viewKeyStruct::phaseNamesString() ); + phaseNames.resize( 2 ); + phaseNames[0] = "water"; phaseNames[1] = "gas"; + + auto & waterTableName = capPressure.getReference< string >( JFunctionCapillaryPressure::viewKeyStruct::wettingNonWettingJFuncTableNameString() ); + waterTableName = "water_jFunction"; + + auto & surfaceTension = capPressure.getReference< real64 >( JFunctionCapillaryPressure::viewKeyStruct::wettingNonWettingSurfaceTensionString() ); + //surfaceTension = 23.86955676433857e-3; + surfaceTension = 0.02; + + auto & permeabilityDirection = + capPressure.getReference< JFunctionCapillaryPressure::PermeabilityDirection >( JFunctionCapillaryPressure::viewKeyStruct::permeabilityDirectionString() ); + permeabilityDirection = JFunctionCapillaryPressure::PermeabilityDirection::XY; + + capPressure.postInputInitializationRecursive(); + capPressure.initialize(); // to test all the checks + + return capPressure; +} + +CapillaryPressureBase & makeTableCapPressureTwoPhase1( string const & name, Group & parent ) +{ + FunctionManager & functionManager = FunctionManager::getInstance(); + + // 1) First, define the tables + + // 1D table, various interpolation methods + localIndex Naxis = 12; + + // Setup table + array1d< real64_array > coordinates; + coordinates.resize( 1 ); + coordinates[0].resize( Naxis ); + coordinates[0][0] = 0.0; + coordinates[0][1] = 0.05; + coordinates[0][2] = 0.15; + coordinates[0][3] = 0.25; + coordinates[0][4] = 0.35; + coordinates[0][5] = 0.45; + coordinates[0][6] = 0.55; + coordinates[0][7] = 0.65; + coordinates[0][8] = 0.75; + coordinates[0][9] = 0.85; + coordinates[0][10] = 0.95; + coordinates[0][11] = 1.0; + + real64_array values( Naxis ); + values[0] = 130000.0; + values[1] = 90572.79; + values[2] = 49307.11; + values[3] = 33654.85; + values[4] = 24384.64; + values[5] = 17951.96; + values[6] = 13098; + values[7] = 9238.84; + values[8] = 6058.81; + values[9] = 3369.14; + values[10] = 1048.6; + values[11] = 0.0; + + // localIndex const Naxis = 2; + + // // Setup table + // array1d< real64_array > coordinates; + // coordinates.resize( 1 ); + // coordinates[0].resize( Naxis ); + + // coordinates[0][0] = 0.0; + // coordinates[0][1] = 1.0; + + // real64_array values( Naxis ); + // values[0] = 129999.999994362; + // values[1] = 50000.0000139914; + + + TableFunction & table_w = dynamicCast< TableFunction & >( *functionManager.createChild( "TableFunction", "water_pc" ) ); + table_w.setTableCoordinates( coordinates, { units::Dimensionless } ); + table_w.setTableValues( values, units::Pressure ); + table_w.reInitializeFunction(); + + table_w.setInterpolationMethod( TableFunction::InterpolationType::Linear ); + + // 2) Then set up the constitutive model + + TableCapillaryPressure & capPressure = parent.registerGroup< TableCapillaryPressure >( name ); + + string_array & phaseNames = capPressure.getReference< string_array >( CapillaryPressureBase::viewKeyStruct::phaseNamesString() ); + phaseNames.resize( 2 ); + phaseNames[0] = "water"; phaseNames[1] = "gas"; + + auto & waterTableName = capPressure.getReference< string >( TableCapillaryPressure::viewKeyStruct::wettingNonWettingCapPresTableNameString() ); + waterTableName = "water_pc"; + + capPressure.postInputInitializationRecursive(); + capPressure.initialize(); // to test all the checks + return capPressure; +} + +CapillaryPressureBase & makeTableCapPressureTwoPhase2( string const & name, Group & parent ) +{ + FunctionManager & functionManager = FunctionManager::getInstance(); + + // 1) First, define the tables + + // 1D table, various interpolation methods + localIndex Naxis = 12; + + // Setup table + array1d< real64_array > coordinates; + coordinates.resize( 1 ); + coordinates[0].resize( Naxis ); + coordinates[0][0] = 0.0; + coordinates[0][1] = 0.05; + coordinates[0][2] = 0.15; + coordinates[0][3] = 0.25; + coordinates[0][4] = 0.35; + coordinates[0][5] = 0.45; + coordinates[0][6] = 0.55; + coordinates[0][7] = 0.65; + coordinates[0][8] = 0.75; + coordinates[0][9] = 0.85; + coordinates[0][10] = 0.95; + coordinates[0][11] = 1.0; + + real64_array values( Naxis ); + values[0] = 195000.0; + values[1] = 135859.25; + values[2] = 73960.67; + values[3] = 50482.28; + values[4] = 36576.96; + values[5] = 26927.94; + values[6] = 19647; + values[7] = 13858.26; + values[8] = 9088.2; + values[9] = 5053.72; + values[10] = 1572.9; + values[11] = 0.0; + + // localIndex const Naxis = 2; + + // // Setup table + // array1d< real64_array > coordinates; + // coordinates.resize( 1 ); + // coordinates[0].resize( Naxis ); + + // coordinates[0][0] = 0.0; + // coordinates[0][1] = 1.0; + + // real64_array values( Naxis ); + // values[0] = 129999.999994362; + // values[1] = 50000.0000139914; + + + TableFunction & table_w = dynamicCast< TableFunction & >( *functionManager.createChild( "TableFunction", "water_pc" ) ); + table_w.setTableCoordinates( coordinates, { units::Dimensionless } ); + table_w.setTableValues( values, units::Pressure ); + table_w.reInitializeFunction(); + + table_w.setInterpolationMethod( TableFunction::InterpolationType::Linear ); + + // 2) Then set up the constitutive model + + TableCapillaryPressure & capPressure = parent.registerGroup< TableCapillaryPressure >( name ); + + string_array & phaseNames = capPressure.getReference< string_array >( CapillaryPressureBase::viewKeyStruct::phaseNamesString() ); + phaseNames.resize( 2 ); + phaseNames[0] = "water"; phaseNames[1] = "gas"; + + auto & waterTableName = capPressure.getReference< string >( TableCapillaryPressure::viewKeyStruct::wettingNonWettingCapPresTableNameString() ); + waterTableName = "water_pc"; + + capPressure.postInputInitializationRecursive(); + capPressure.initialize(); // to test all the checks + return capPressure; +} + +CapillaryPressureBase & makeBrooksCoreyCapPressureTwoPhase1( string const & name, Group & parent ) +{ + BrooksCoreyCapillaryPressure & capPressure = parent.registerGroup< BrooksCoreyCapillaryPressure >( name ); + + string_array & phaseNames = capPressure.getReference< string_array >( CapillaryPressureBase::viewKeyStruct::phaseNamesString() ); + phaseNames.resize( 2 ); + phaseNames[0] = "water"; phaseNames[1] = "gas"; + + array1d< real64 > & phaseMinSat = capPressure.getReference< array1d< real64 > >( BrooksCoreyCapillaryPressure::viewKeyStruct::phaseMinVolumeFractionString() ); + phaseMinSat.resize( 2 ); + phaseMinSat[0] = phase0MinSat1; phaseMinSat[1] = phase1MinSat1; + + array1d< real64 > & phaseCapPressureExpInv = + capPressure.getReference< array1d< real64 > >( BrooksCoreyCapillaryPressure::viewKeyStruct::phaseCapPressureExponentInvString() ); + phaseCapPressureExpInv.resize( 2 ); + phaseCapPressureExpInv[0] = 4; phaseCapPressureExpInv[1] = 1; + + array1d< real64 > & phaseEntryPressure = capPressure.getReference< array1d< real64 > >( BrooksCoreyCapillaryPressure::viewKeyStruct::phaseEntryPressureString() ); + phaseEntryPressure.resize( 2 ); + phaseEntryPressure[0] = 0.75e5; phaseEntryPressure[1] = 0; + + real64 & capPressureEpsilon = capPressure.getReference< real64 >( BrooksCoreyCapillaryPressure::viewKeyStruct::capPressureEpsilonString() ); + capPressureEpsilon = 1.0e-8; + + capPressure.postInputInitializationRecursive(); + return capPressure; +} + +CapillaryPressureBase & makeBrooksCoreyCapPressureTwoPhase2( string const & name, Group & parent ) +{ + BrooksCoreyCapillaryPressure & capPressure = parent.registerGroup< BrooksCoreyCapillaryPressure >( name ); + + string_array & phaseNames = capPressure.getReference< string_array >( CapillaryPressureBase::viewKeyStruct::phaseNamesString() ); + phaseNames.resize( 2 ); + phaseNames[0] = "water"; phaseNames[1] = "gas"; + + array1d< real64 > & phaseMinSat = capPressure.getReference< array1d< real64 > >( BrooksCoreyCapillaryPressure::viewKeyStruct::phaseMinVolumeFractionString() ); + phaseMinSat.resize( 2 ); + phaseMinSat[0] = phase0MinSat2; phaseMinSat[1] = phase1MinSat2; + + array1d< real64 > & phaseCapPressureExpInv = + capPressure.getReference< array1d< real64 > >( BrooksCoreyCapillaryPressure::viewKeyStruct::phaseCapPressureExponentInvString() ); + phaseCapPressureExpInv.resize( 2 ); + phaseCapPressureExpInv[0] = 4; phaseCapPressureExpInv[1] = 1; + + array1d< real64 > & phaseEntryPressure = capPressure.getReference< array1d< real64 > >( BrooksCoreyCapillaryPressure::viewKeyStruct::phaseEntryPressureString() ); + phaseEntryPressure.resize( 2 ); + phaseEntryPressure[0] = 0.5e5; phaseEntryPressure[1] = 0; + + real64 & capPressureEpsilon = capPressure.getReference< real64 >( BrooksCoreyCapillaryPressure::viewKeyStruct::capPressureEpsilonString() ); + capPressureEpsilon = 1e-8; + + capPressure.postInputInitializationRecursive(); + return capPressure; +} + +RelativePermeabilityBase & makeBrooksCoreyRelPerm( string const & name, Group & parent ) +{ + BrooksCoreyRelativePermeability & relPerm = parent.registerGroup< BrooksCoreyRelativePermeability >( name ); + + string_array & phaseNames = relPerm.getReference< string_array >( RelativePermeabilityBase::viewKeyStruct::phaseNamesString() ); + phaseNames.resize( 2 ); + phaseNames[0] = "water"; phaseNames[1] = "gas"; + + array1d< real64 > & phaseMinSat = relPerm.getReference< array1d< real64 > >( BrooksCoreyRelativePermeability::viewKeyStruct::phaseMinVolumeFractionString() ); + phaseMinSat.resize( 2 ); + phaseMinSat[0] = phase0MinSat1; phaseMinSat[1] = phase1MinSat1; + + array1d< real64 > & phaseRelPermExp = relPerm.getReference< array1d< real64 > >( BrooksCoreyRelativePermeability::viewKeyStruct::phaseRelPermExponentString() ); + phaseRelPermExp.resize( 2 ); + phaseRelPermExp[0] = 2.0; phaseRelPermExp[1] = 2.0; + + array1d< real64 > & phaseRelPermMaxVal = relPerm.getReference< array1d< real64 > >( BrooksCoreyRelativePermeability::viewKeyStruct::phaseRelPermMaxValueString() ); + phaseRelPermMaxVal.resize( 2 ); + phaseRelPermMaxVal[0] = 1.0; phaseRelPermMaxVal[1] = 1.0; + + relPerm.postInputInitializationRecursive(); + return relPerm; +} + +class ImmiscibleInterfaceConditionsTest : public FluidModelTest< TwoPhaseImmiscibleFluid, 2 > +{ +public: + ImmiscibleInterfaceConditionsTest(): state( std::make_unique< CommandLineOptions >( g_commandLineOptions )), + m_parent( "TestParentGroup", m_node ) + + {} + +protected: + + static real64 constexpr time = 0.0; + static real64 constexpr dt = 1e4; + static real64 constexpr eps = std::numeric_limits< real64 >::epsilon(); + + GeosxState state; + ImmiscibleMultiphaseFlow *solver; + conduit::Node m_node; + dataRepository::Group m_parent; +}; + +real64 constexpr ImmiscibleInterfaceConditionsTest::time; +real64 constexpr ImmiscibleInterfaceConditionsTest::dt; +real64 constexpr ImmiscibleInterfaceConditionsTest::eps; + + + +TEST_F( ImmiscibleInterfaceConditionsTest, LocalNonlinearSolverConvergence ) +{ + + // using Base = FluidModelTest< TwoPhaseImmiscibleFluid, 2 >; + createFluid( "fluid", [this]( TwoPhaseImmiscibleFluid & fluid ){ + makeTwoPhaseImmiscibleFluid( fluid ); + + // getting constitutive models: + RelativePermeabilityBase & relPerm = makeBrooksCoreyRelPerm( "relPerm" , this->m_parent); + RelativePermeabilityBase * relPermPtr = &relPerm; + // CapillaryPressureBase & capPressure0 = makeJFunctionCapPressureTwoPhase( "capPressure0", this->m_parent ); + // CapillaryPressureBase * capPressurePtr0 = &capPressure0; + + CapillaryPressureBase & capPressure0 = makeTableCapPressureTwoPhase1( "capPressure0", this->m_parent ); + CapillaryPressureBase * capPressurePtr0 = &capPressure0; + + CapillaryPressureBase & capPressure1 = makeTableCapPressureTwoPhase2( "capPressure1", this->m_parent ); + CapillaryPressureBase * capPressurePtr1 = &capPressure1; + // CapillaryPressureBase & capPressure0 = makeBrooksCoreyCapPressureTwoPhase1( "capPressure0", this->m_parent ); + // CapillaryPressureBase * capPressurePtr0 = &capPressure0; + + // CapillaryPressureBase & capPressure1 = makeBrooksCoreyCapPressureTwoPhase2( "capPressure1", this->m_parent ); + // CapillaryPressureBase * capPressurePtr1 = &capPressure1; + + std::vector< RelativePermeabilityBase * > relPerms = {relPermPtr, relPermPtr}; + std::vector< CapillaryPressureBase * > capPressures = {capPressurePtr0, capPressurePtr1}; + std::vector< TwoPhaseImmiscibleFluid * > fluids = { &fluid, &fluid }; + // real64 uT = 3.2864545889999906e-05; + + // real64 uT = -3.3e-5; + real64 uT = 1e-17; +// real64 uT = 1e-7; + stdVector< real64 > saturations = {0.2, 0.4}; + stdVector< real64 > trappedSats1 = {phase0MinSat1, phase1MinSat1}; + stdVector< real64 > trappedSats2 = {phase0MinSat2, phase1MinSat2}; + stdVector< real64 > pressures = {1e7, 1e7}; + stdVector< real64 > JFMultipliers = {45016.662822296035, 30011.108548197357}; + stdVector< real64 > transHats = {1.9738466000000002e-12, 4.4411548500000007e-12}; + stdVector< real64 > dTransHats_dP = {0.0, 0.0}; + stdVector< real64 > gravCoefHats = {490.5, 490.5}; + stdVector< real64 > gravCoefs = {465.97500000000002, 515.02499999999998}; + + + stdVector< real64 > phi = {0.0, 0.0}; + stdVector< real64 > grad_phi = {0.0, 0.0, 0.0, 0.0}; + + std::ofstream outFile( "local_solver_results.csv" ); + + + // Write data to the file + outFile << "Si"; + outFile << ","; + outFile << "Sj"; + outFile << ","; + outFile << "Fw_alpha"; + outFile << ","; + outFile << "Fn_alpha"; + outFile << ","; + outFile << "Residual_initial"; + outFile << ","; + outFile << "Pc_int"; + outFile << ","; + outFile << "Residual"; + outFile << ","; + outFile << "newton"; + outFile << std::endl; + + real64 const start_sat = 0.0; + real64 const end_sat = 1.0; + real64 const dS = 1e-2; + real64 Si = 0.0; + real64 Sj = 0.9; + + // for( real64 Si = start_sat; Si <= end_sat + 1e-8; Si += dS ) + // { + // for( real64 Sj = start_sat; Sj <= end_sat + 1e-8; Sj += dS ) + // { + saturations[0] = Si; + saturations[1] = Sj; + + auto t0 = std::chrono::high_resolution_clock::now(); + +// Call the GEOS local solver + geos::immiscibleMultiphaseKernels::local_solver( uT, saturations, pressures, JFMultipliers, trappedSats1, trappedSats2, transHats, dTransHats_dP, gravCoefHats, gravCoefs, + relPerms, capPressures, fluids, phi, grad_phi ); + +auto t1 = std::chrono::high_resolution_clock::now(); +std::chrono::duration elapsed = t1 - t0; +std::cout << "Local solver time: " << elapsed.count() << " s" << std::endl; + + + // Write data to the file + outFile << GEOS_FMT( "{:10.10e}", saturations[0] ); + outFile << GEOS_FMT( ",{:10.10e}", saturations[1] ); + outFile << GEOS_FMT( ",{:10.10e}", phi[0] ); + outFile << GEOS_FMT( ",{:10.10e}", phi[1] ); + outFile << GEOS_FMT( ",{:10.10e}", grad_phi[0] ); + outFile << GEOS_FMT( ",{:10.10e}", grad_phi[1] ); + outFile << GEOS_FMT( ",{:10.10e}", grad_phi[2] ); + outFile << GEOS_FMT( ",{:10.10e}", grad_phi[3] ); + outFile << std::endl; + phi[0] = 0; + phi[1] = 0; + grad_phi[0] = 0; + grad_phi[1] = 0; + grad_phi[2] = 0; + grad_phi[3] = 0; + +// } +// } + + outFile.close(); + +} ); +} + +int main( int argc, char * *argv ) +{ + ::testing::InitGoogleTest( &argc, argv ); + g_commandLineOptions = *geos::basicSetup( argc, argv ); + int const result = RUN_ALL_TESTS(); + geos::basicCleanup(); + return result; +} + +// maybe needed later on +// TEST_F( CapillaryPressureTest, numericalDerivatives_jFunctionCapPressureTwoPhase ) +// { +// initialize( makeJFunctionCapPressureTwoPhase( "capPressure", m_parent ) ); + +// // here, we have to apply a special treatment to this test +// // to make sure that the J-function multiplier is initialized using initializeRockState +// // this requires calling allocateConstitutiveData in advance (it will be called again later, in the "test" function) + +// // setup some values for porosity and permeability +// array2d< real64 > porosity; +// porosity.resize( 1, 1 ); +// porosity[0][0] = 0.13496794266569806; +// array3d< real64 > permeability; +// permeability.resize( 1, 1, 3 ); +// permeability[0][0][0] = 0.1722194e-15; +// permeability[0][0][1] = 0.3423156e-15; +// permeability[0][0][2] = 0.2324191e-15; + +// // initialize the J-function multiplier (done on GPU if GPU is available) +// m_model->allocateConstitutiveData( m_parent, 1 ); +// m_model->initializeRockState( porosity.toViewConst(), permeability.toViewConst() ); + +// // move the multiplier back to the CPU since the test is performed on the CPU +// auto & jFuncMultiplier = +// m_model->getReference< array2d< real64 > >( fields::cappres::jFuncMultiplier::key() ); +// jFuncMultiplier.move( hostMemorySpace, false ); + +// // we are ready to proceed to the test + +// real64 const eps = std::sqrt( std::numeric_limits< real64 >::epsilon() ); +// real64 const tol = 1e-4; + +// real64 const start_sat = 0.3; +// real64 const end_sat = 0.9; +// real64 const dS = 1e-1; +// array1d< real64 > sat( 2 ); +// sat[0] = start_sat; sat[1] = 1-sat[0]; +// while( sat[0] <= end_sat ) +// { +// test( sat, eps, tol ); +// sat[0] += dS; +// sat[1] = 1 - sat[0]; +// } + +// } \ No newline at end of file diff --git a/src/coreComponents/integrationTests/wellsTests/CMakeLists.txt b/src/coreComponents/integrationTests/wellsTests/CMakeLists.txt index 5a30f2fe376..2a6063f14c2 100644 --- a/src/coreComponents/integrationTests/wellsTests/CMakeLists.txt +++ b/src/coreComponents/integrationTests/wellsTests/CMakeLists.txt @@ -1,6 +1,23 @@ # Specify list of tests set( gtest_geosx_tests +<<<<<<< HEAD:src/coreComponents/unitTests/fluidFlowTests/CMakeLists.txt + testSinglePhaseMobilityKernel.cpp + testThermalCompMultiphaseFlow.cpp + testThermalSinglePhaseFlow.cpp + testFlowStatistics.cpp + testTransmissibility.cpp + testImmiscibleMultiphaseFlow.cpp + testImmiscibleInterfaceConditions.cpp ) + +if( ENABLE_PVTPackage ) + list( APPEND gtest_geosx_tests + testCompMultiphaseFlow.cpp + testCompMultiphaseFlowHybrid.cpp + testReactiveCompositionalMultiphaseOBL.cpp ) +endif() +======= testReservoirSinglePhaseMSWells.cpp ) +>>>>>>> develop:src/coreComponents/integrationTests/wellsTests/CMakeLists.txt set( tplDependencyList ${parallelDeps} gtest ) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index 624c8960033..00162bb1129 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -24,12 +24,9 @@ #include "physicsSolvers/PhysicsSolverBaseKernels.hpp" #include "physicsSolvers/fluidFlow/CompositionalMultiphaseUtilities.hpp" #include "physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp" -#include "physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/CapillaryPressureUpdateKernel.hpp" -#include "physicsSolvers/fluidFlow/kernels/compositional/ThermalAccumulationKernel.hpp" #include "physicsSolvers/fluidFlow/kernels/compositional/RelativePermeabilityUpdateKernel.hpp" -#include "constitutive/ConstitutiveManager.hpp" -#include "constitutive/capillaryPressure/CapillaryPressureFields.hpp" -#include "constitutive/capillaryPressure/capillaryPressureSelector.hpp" +#include "physicsSolvers/fluidFlow/kernels/compositional/CapillaryPressureUpdateKernel.hpp" +#include "constitutive/capillaryPressure/CapillaryPressureSelector.hpp" #include "constitutive/relativePermeability/RelativePermeabilitySelector.hpp" #include "fieldSpecification/EquilibriumInitialCondition.hpp" @@ -268,8 +265,7 @@ void ImmiscibleMultiphaseFlow::updateCapPressureModel( ObjectManagerBase & dataG { typename TYPEOFREF( castedCapPres ) ::KernelWrapper capPresWrapper = castedCapPres.createKernelWrapper(); - // isothermalCompositionalMultiphaseBaseKernels:: - immiscibleMultiphaseKernels:: + isothermalCompositionalMultiphaseBaseKernels:: CapillaryPressureUpdateKernel:: launch< parallelDevicePolicy<> >( dataGroup.size(), capPresWrapper, @@ -586,7 +582,7 @@ void ImmiscibleMultiphaseFlow::assembleAccumulationTerm( DomainPartition & domai } void ImmiscibleMultiphaseFlow::assembleFluxTerms( real64 const dt, - DomainPartition & domain, + DomainPartition const & domain, DofManager const & dofManager, CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) const @@ -599,75 +595,30 @@ void ImmiscibleMultiphaseFlow::assembleFluxTerms( real64 const dt, string const & dofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, - MeshLevel & mesh, - string_array const & regionNames ) + MeshLevel const & mesh, + string_array const & ) { - if( m_hasCapPressure ) - { - mesh.getElemManager().forElementSubRegions( regionNames, - [&]( localIndex const, - ElementSubRegionBase & subRegion ) // Check if you need this. - { - // Capillary pressure wrapper - string const & cappresName = subRegion.getReference< string >( viewKeyStruct::capPressureNamesString() ); - JFunctionCapillaryPressure & capPressure = getConstitutiveModel< JFunctionCapillaryPressure >( subRegion, cappresName ); - JFunctionCapillaryPressure::KernelWrapper capPresWrapper = capPressure.createKernelWrapper(); - - // Relative permeability wrapper - string const & relPermName = subRegion.getReference< string >( viewKeyStruct::relPermNamesString() ); - BrooksCoreyRelativePermeability & relPerm = getConstitutiveModel< BrooksCoreyRelativePermeability >( subRegion, relPermName ); - BrooksCoreyRelativePermeability::KernelWrapper relPermWrapper = relPerm.createKernelWrapper(); - - fluxApprox.forAllStencils( mesh, [&]( auto & stencil ) - { - typename TYPEOFREF( stencil ) ::KernelWrapper stencilWrapper = stencil.createKernelWrapper(); - immiscibleMultiphaseKernels:: - FluxComputeKernelFactory::createAndLaunch< parallelDevicePolicy<> >( m_numPhases, - dofManager.rankOffset(), - dofKey, - m_hasCapPressure, - m_useTotalMassEquation, - m_gravityDensityScheme == GravityDensityScheme::PhasePresence, - getName(), - mesh.getElemManager(), - stencilWrapper, - capPresWrapper, - relPermWrapper, - subRegion, - dt, - localMatrix.toViewConstSizes(), - localRhs.toView() ); - } ); - } ); - } - else + fluxApprox.forAllStencils( mesh, [&]( auto & stencil ) { - fluxApprox.forAllStencils( mesh, [&]( auto & stencil ) - { - typename TYPEOFREF( stencil ) ::KernelWrapper stencilWrapper = stencil.createKernelWrapper(); - immiscibleMultiphaseKernels:: + typename TYPEOFREF( stencil ) ::KernelWrapper stencilWrapper = stencil.createKernelWrapper(); + immiscibleMultiphaseKernels:: FluxComputeKernelFactory::createAndLaunch< parallelDevicePolicy<> >( m_numPhases, - dofManager.rankOffset(), - dofKey, - m_hasCapPressure, - m_useTotalMassEquation, - m_gravityDensityScheme == GravityDensityScheme::PhasePresence, - getName(), - mesh.getElemManager(), - stencilWrapper, - dt, - localMatrix.toViewConstSizes(), - localRhs.toView() ); - } ); - } - + dofManager.rankOffset(), + dofKey, + m_hasCapPressure, + m_useTotalMassEquation, + m_gravityDensityScheme == GravityDensityScheme::PhasePresence, + getName(), + mesh.getElemManager(), + stencilWrapper, + dt, + localMatrix.toViewConstSizes(), + localRhs.toView() ); + } ); } ); } -// Ryan: Looks like this will need to be overwritten as well... -// I have left the CompositionalMultiphaseFVM implementation for reference void ImmiscibleMultiphaseFlow::setupDofs( DomainPartition const & domain, DofManager & dofManager ) const { diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp index b1df16899d6..b3769837600 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp @@ -27,6 +27,12 @@ namespace geos { + +namespace constitutive +{ +class ConstitutiveBase; +} // namespace constitutive + //START_SPHINX_INCLUDE_00 /** * @class ImmiscibleMultiphaseFlow @@ -214,6 +220,10 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase struct viewKeyStruct : public FlowSolverBase::viewKeyStruct { // inputs + static constexpr char const * capPressureNamesString() { return "capPressureNames"; } + static constexpr char const * relPermNamesString() { return "relPermNames"; } + static constexpr char const * elemDofFieldString() { return "elemDofField"; } + static constexpr char const * interfaceFaceSetNamesString() { return "interfaceFaceSetNames"; } // density averaging scheme static constexpr char const * gravityDensitySchemeString() { return "gravityDensityScheme"; } @@ -227,9 +237,9 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase static constexpr char const * maxRelativePresChangeString() { return "maxRelativePressureChange"; } static constexpr char const * useTotalMassEquationString() { return "useTotalMassEquation"; } - static constexpr char const * capPressureNamesString() { return "capillary_pressure"; } - static constexpr char const * relPermNamesString() { return "relative_permeability"; } - static constexpr char const * elemDofFieldString() { return "elemDofField"; } +// static constexpr char const * capPressureNamesString() { return "capillary_pressure"; } +// static constexpr char const * relPermNamesString() { return "relative_permeability"; } +// static constexpr char const * elemDofFieldString() { return "elemDofField"; } }; @@ -299,6 +309,15 @@ class ImmiscibleMultiphaseFlow : public FlowSolverBase /// damping factor for solution change targets real64 m_solutionChangeScalingFactor; + string_array m_interfaceFaceSetNames; + + stdVector< std::array< std::tuple< constitutive::RelativePermeabilityBase *, + constitutive::CapillaryPressureBase *, + constitutive::TwoPhaseImmiscibleFluid * >, 2 > > m_interfaceConstitutivePairs; + + unordered_map< localIndex, localIndex > m_interfaceRegionByConnector; + unordered_map< localIndex, localIndex > m_connectorIndicesByInterfaceRegion; + private: diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp index a60814d80d9..25399a7ebc8 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp @@ -20,38 +20,47 @@ #ifndef GEOS_PHYSICSSOLVERS_FLUIDFLOW_MULTIPHASEKERNELS_HPP #define GEOS_PHYSICSSOLVERS_FLUIDFLOW_MULTIPHASEKERNELS_HPP -#define Pe_max 5000000.0 -#include "codingUtilities/Utilities.hpp" -#include "common/DataLayouts.hpp" -#include "common/DataTypes.hpp" -#include "common/GEOS_RAJA_Interface.hpp" + + #include "codingUtilities/Utilities.hpp" + #include "common/DataLayouts.hpp" + #include "common/DataTypes.hpp" + #include "common/GEOS_RAJA_Interface.hpp" + #include "constitutive/fluid/twophaseimmisciblefluid/TwoPhaseImmiscibleFluid.hpp" + #include "constitutive/solid/CoupledSolidBase.hpp" + #include "constitutive/fluid/twophaseimmisciblefluid/TwoPhaseImmiscibleFluidFields.hpp" + #include "constitutive/capillaryPressure/CapillaryPressureFields.hpp" + #include "constitutive/capillaryPressure/CapillaryPressureBase.hpp" + #include "constitutive/capillaryPressure/JFunctionCapillaryPressure.hpp" + #include "constitutive/capillaryPressure/TableCapillaryPressure.hpp" + #include "constitutive/permeability/PermeabilityBase.hpp" + #include "constitutive/permeability/PermeabilityFields.hpp" + #include "constitutive/relativePermeability/RelativePermeabilityBase.hpp" + #include "constitutive/relativePermeability/RelativePermeabilityFields.hpp" + #include "constitutive/ConstitutiveManager.hpp" +#include "constitutive/capillaryPressure/capillaryPressureSelector.hpp" +#include "constitutive/relativePermeability/RelativePermeabilitySelector.hpp" + +#include "constitutive/ConstitutivePassThru.hpp" #include "constitutive/fluid/twophaseimmisciblefluid/TwoPhaseImmiscibleFluid.hpp" -#include "constitutive/solid/CoupledSolidBase.hpp" -#include "constitutive/fluid/twophaseimmisciblefluid/TwoPhaseImmiscibleFluidFields.hpp" -#include "constitutive/capillaryPressure/CapillaryPressureFields.hpp" -#include "constitutive/capillaryPressure/CapillaryPressureBase.hpp" -#include "constitutive/capillaryPressure/JFunctionCapillaryPressure.hpp" -#include "constitutive/capillaryPressure/TableCapillaryPressure.hpp" -#include "constitutive/permeability/PermeabilityBase.hpp" -#include "constitutive/permeability/PermeabilityFields.hpp" -#include "constitutive/relativePermeability/RelativePermeabilityBase.hpp" -#include "constitutive/relativePermeability/RelativePermeabilityFields.hpp" -#include "fieldSpecification/AquiferBoundaryCondition.hpp" -#include "finiteVolume/BoundaryStencil.hpp" -#include "finiteVolume/CellElementStencilTPFA.hpp" -#include "finiteVolume/FluxApproximationBase.hpp" -#include "linearAlgebra/interfaces/InterfaceTypes.hpp" -#include "physicsSolvers/PhysicsSolverBaseKernels.hpp" -#include "physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp" -#include "physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp" -#include "physicsSolvers/fluidFlow/CompositionalMultiphaseUtilities.hpp" -#include "physicsSolvers/fluidFlow/StencilAccessors.hpp" -#include "physicsSolvers/fluidFlow/kernels/compositional/RelativePermeabilityUpdateKernel.hpp" -#include "physicsSolvers/fluidFlow/kernels/compositional/CapillaryPressureUpdateKernel.hpp" -#include "physicsSolvers/PhysicsSolverBaseKernels.hpp" -#include "physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/KernelLaunchSelectors.hpp" -#include "physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/KernelLaunchSelectors.hpp" + + + #include "fieldSpecification/AquiferBoundaryCondition.hpp" + #include "finiteVolume/BoundaryStencil.hpp" + #include "finiteVolume/CellElementStencilTPFA.hpp" + #include "finiteVolume/FluxApproximationBase.hpp" + #include "linearAlgebra/interfaces/InterfaceTypes.hpp" + #include "physicsSolvers/PhysicsSolverBaseKernels.hpp" + #include "physicsSolvers/fluidFlow/FlowSolverBaseFields.hpp" + #include "physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp" + #include "physicsSolvers/fluidFlow/CompositionalMultiphaseUtilities.hpp" + #include "physicsSolvers/fluidFlow/StencilAccessors.hpp" + #include "physicsSolvers/fluidFlow/kernels/compositional/RelativePermeabilityUpdateKernel.hpp" + #include "physicsSolvers/fluidFlow/kernels/compositional/CapillaryPressureUpdateKernel.hpp" + #include "physicsSolvers/PhysicsSolverBaseKernels.hpp" + #include "physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/KernelLaunchSelectors.hpp" + #include "physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/KernelLaunchSelectors.hpp" + namespace geos { @@ -60,6 +69,1249 @@ namespace immiscibleMultiphaseKernels using namespace constitutive; +GEOS_HOST_DEVICE +inline +static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< real64 > pressures, stdVector< real64 > JFMultipliers, stdVector< real64 > trappedSats1, + stdVector< real64 > trappedSats2, stdVector< real64 > transHat, stdVector< real64 > dTransHat_dP, stdVector< real64 > gravCoefHat, stdVector< real64 > gravCoef, + stdVector< real64 > cellCenterDuT, stdVector< real64 > cellCenterDens, stdVector< real64 > cellCenterDens_dP, + std::vector< RelativePermeabilityBase * > relPerms, std::vector< CapillaryPressureBase * > capPressures, + std::vector< TwoPhaseImmiscibleFluid * > fluids, std::vector< real64 > &phi, std::vector< real64 > &grad_phi_P, std::vector< real64 > &grad_phi_S, bool &converged ) +{ + + // getting wrappers: + + constitutive::constitutiveUpdatePassThru( *capPressures[0], [&] ( auto & castedCapPres1 ) + { + auto capPresWrapper1 = castedCapPres1.createKernelWrapper(); + + + constitutive::constitutiveUpdatePassThru( *capPressures[1], [&] ( auto & castedCapPres2 ) + { + auto capPresWrapper2 = castedCapPres2.createKernelWrapper(); + + + constitutive::constitutiveUpdatePassThru( *relPerms[0], [&] ( auto & castedRelPerm1 ) + { + auto relPermWrapper1 = castedRelPerm1.createKernelWrapper(); + + + constitutive::constitutiveUpdatePassThru( *relPerms[1], [&] ( auto & castedRelPerm2 ) + { + auto relPermWrapper2 = castedRelPerm2.createKernelWrapper(); + + auto fluidWrapper1 = fluids[0]->createKernelWrapper(); + auto fluidWrapper2 = fluids[1]->createKernelWrapper(); + + // Create an output file stream object (ofstream) for analyzing the local solver's performance + std::ofstream outFile( "iterations2.csv" ); + + + // Write data to the file + outFile << "Jacobian"; + outFile << ","; + outFile << "residual"; + outFile << ","; + outFile << "Fw_alpha"; + outFile << ","; + outFile << "Fw_beta"; + outFile << ","; + outFile << "Pc_int"; + outFile << ","; + outFile << "Pc_int1"; + outFile << ","; + outFile << "Pc_int2"; + outFile << ","; + outFile << "Fn_alpha"; + outFile << ","; + outFile << "Fn_beta"; + outFile << ","; + outFile << "Vw_alpha"; + outFile << ","; + outFile << "Vn_alpha"; + outFile << ","; + outFile << "Vw_beta"; + outFile << ","; + outFile << "Vn_beta"; + outFile << ","; + outFile << "Gw_alpha"; + outFile << ","; + outFile << "Gn_alpha"; + outFile << ","; + outFile << "Gw_beta"; + outFile << ","; + outFile << "Gn_beta"; + outFile << ","; + outFile << "Cw_alpha"; + outFile << ","; + outFile << "Cn_alpha"; + outFile << ","; + outFile << "Cw_beta"; + outFile << ","; + outFile << "Cn_beta"; + outFile << ","; + outFile << "Pc1_ip0"; + outFile << ","; + outFile << "Pc1_ip1"; + outFile << ","; + outFile << "S_alpha"; + outFile << ","; + outFile << "S_beta"; + outFile << std::endl; + + // nonlinear solver's parameters + real64 tol = 1.0e-9; + int max_iter = 50; + converged = 0; + bool damping = true; + bool bisection = false; + bool lineSearch = false; + bool newton_path = false; + + // Local newton loop: + + // Use of the capillary pressure kernel wrapper + + StackArray< real64, 2, 2, immiscibleFlow::LAYOUT_PHASE > phaseVolFrac1( 1, 2 ); + StackArray< real64, 3, 2, constitutive::cappres::LAYOUT_CAPPRES > capPres1( 1, 1, 2 ); + StackArray< real64, 4, 4, constitutive::cappres::LAYOUT_CAPPRES_DS > dPhaseVolFrac_dCapPres1( 1, 1, 2, 2 ); + StackArray< real64, 4, 4, constitutive::cappres::LAYOUT_CAPPRES_DS > dCapPres1_dPhaseVolFrac( 1, 1, 2, 2 ); + StackArray< real64, 2, 2, immiscibleFlow::LAYOUT_PHASE > facePhaseVolFrac1( 1, 2 ); + StackArray< real64, 3, 2, constitutive::cappres::LAYOUT_CAPPRES > faceCapPres1( 1, 1, 2 ); + StackArray< real64, 4, 4, constitutive::cappres::LAYOUT_CAPPRES_DS > dfacePhaseVolFrac_dCapPres1( 1, 1, 2, 2 ); + StackArray< real64, 4, 4, constitutive::cappres::LAYOUT_CAPPRES_DS > dCapPres1_dfacePhaseVolFrac( 1, 1, 2, 2 ); + StackArray< real64, 2, 2, immiscibleFlow::LAYOUT_PHASE > phaseVolFrac2( 1, 2 ); + StackArray< real64, 3, 2, constitutive::cappres::LAYOUT_CAPPRES > capPres2( 1, 1, 2 ); + StackArray< real64, 4, 4, constitutive::cappres::LAYOUT_CAPPRES_DS > dPhaseVolFrac_dCapPres2( 1, 1, 2, 2 ); + StackArray< real64, 4, 4, constitutive::cappres::LAYOUT_CAPPRES_DS > dCapPres2_dPhaseVolFrac( 1, 1, 2, 2 ); + StackArray< real64, 2, 2, immiscibleFlow::LAYOUT_PHASE > facePhaseVolFrac2( 1, 2 ); + StackArray< real64, 3, 2, constitutive::cappres::LAYOUT_CAPPRES > faceCapPres2( 1, 1, 2 ); + StackArray< real64, 4, 4, constitutive::cappres::LAYOUT_CAPPRES_DS > dfacePhaseVolFrac_dCapPres2( 1, 1, 2, 2 ); + StackArray< real64, 4, 4, constitutive::cappres::LAYOUT_CAPPRES_DS > dCapPres2_dfacePhaseVolFrac( 1, 1, 2, 2 ); + StackArray< real64, 1, 2 > JFunc1( 2 ); + StackArray< real64, 1, 2 > JFunc2( 2 ); + + phaseVolFrac1[0][0] = saturations[0]; + phaseVolFrac1[0][1] = 1.0 - saturations[0]; + + phaseVolFrac2[0][0] = saturations[1]; + phaseVolFrac2[0][1] = 1.0 - saturations[1]; + + real64 Pc1_min = 0.0; + real64 Pc2_min = 0.0; + real64 Pc1_max = 0.0; + real64 Pc2_max = 0.0; + + real64 density2[2]{}; + real64 dDens_dP2[2][2]{}; + + density2[0] = cellCenterDens[0]; + density2[1] = cellCenterDens[1]; + + dDens_dP2[0][0] = cellCenterDens_dP[0]; + dDens_dP2[0][1] = cellCenterDens_dP[1]; + dDens_dP2[1][0] = cellCenterDens_dP[2]; + dDens_dP2[1][1] = cellCenterDens_dP[3]; + + JFunc1[0] = JFMultipliers[0]; + JFunc2[0] = JFMultipliers[1]; + + using T1 = std::decay_t< decltype(castedCapPres1) >; + if constexpr (std::is_same_v< T1, JFunctionCapillaryPressure >) { + capPresWrapper1.compute( phaseVolFrac1[0], + JFunc1.toSliceConst(), + capPres1[0][0], + dCapPres1_dPhaseVolFrac[0][0] ); + + facePhaseVolFrac1[0][1] = 0.0; + facePhaseVolFrac1[0][0] = 1.0; + capPresWrapper1.compute( facePhaseVolFrac1[0], + JFunc1.toSliceConst(), + faceCapPres1[0][0], + dCapPres1_dfacePhaseVolFrac[0][0] ); + Pc1_min = faceCapPres1[0][0][0]; + facePhaseVolFrac1[0][1] = 1.0; + facePhaseVolFrac1[0][0] = 0.0; + capPresWrapper1.compute( facePhaseVolFrac1[0], + JFunc1.toSliceConst(), + faceCapPres1[0][0], + dCapPres1_dfacePhaseVolFrac[0][0] ); + Pc1_max = faceCapPres1[0][0][0]; + + } + else + { + capPresWrapper1.compute( phaseVolFrac1[0], + capPres1[0][0], + dCapPres1_dPhaseVolFrac[0][0] ); + + facePhaseVolFrac1[0][1] = 0.0; + facePhaseVolFrac1[0][0] = 1.0; + capPresWrapper1.compute( facePhaseVolFrac1[0], + faceCapPres1[0][0], + dCapPres1_dfacePhaseVolFrac[0][0] ); + Pc1_min = faceCapPres1[0][0][0]; + facePhaseVolFrac1[0][1] = 1.0; + facePhaseVolFrac1[0][0] = 0.0; + capPresWrapper1.compute( facePhaseVolFrac1[0], + faceCapPres1[0][0], + dCapPres1_dfacePhaseVolFrac[0][0] ); + Pc1_max = faceCapPres1[0][0][0]; + } + + using T2 = std::decay_t< decltype(castedCapPres2) >; + if constexpr (std::is_same_v< T2, JFunctionCapillaryPressure >) { + // evaluating cell-center Pc: + + capPresWrapper2.compute( phaseVolFrac2[0], + JFunc2.toSliceConst(), + capPres2[0][0], + dCapPres2_dPhaseVolFrac[0][0] ); + +// finding endpoints: + + facePhaseVolFrac2[0][1] = 0.0; + facePhaseVolFrac2[0][0] = 1.0; + capPresWrapper2.compute( facePhaseVolFrac2[0], + JFunc2.toSliceConst(), + faceCapPres2[0][0], + dCapPres2_dfacePhaseVolFrac[0][0] ); + Pc2_min = faceCapPres2[0][0][0]; + facePhaseVolFrac2[0][1] = 1.0; + facePhaseVolFrac2[0][0] = 0.0; + capPresWrapper2.compute( facePhaseVolFrac2[0], + JFunc2.toSliceConst(), + faceCapPres2[0][0], + dCapPres2_dfacePhaseVolFrac[0][0] ); + Pc2_max = faceCapPres2[0][0][0]; + + } + else + { + // evaluating cell-center Pc: + + capPresWrapper2.compute( phaseVolFrac2[0], + capPres2[0][0], + dCapPres2_dPhaseVolFrac[0][0] ); + +// finding endpoints: + + facePhaseVolFrac2[0][1] = 0.0; + facePhaseVolFrac2[0][0] = 1.0; + capPresWrapper2.compute( facePhaseVolFrac2[0], + faceCapPres2[0][0], + dCapPres2_dfacePhaseVolFrac[0][0] ); + Pc2_min = faceCapPres2[0][0][0]; + facePhaseVolFrac2[0][1] = 1.0; + facePhaseVolFrac2[0][0] = 0.0; + capPresWrapper2.compute( facePhaseVolFrac2[0], + faceCapPres2[0][0], + dCapPres2_dfacePhaseVolFrac[0][0] ); + Pc2_max = faceCapPres2[0][0][0]; + } + + // Use of the relative permeability kernel wrapper + + StackArray< real64, 3, 2, constitutive::relperm::LAYOUT_RELPERM > faceTrappedVolFrac1( 1, 1, 2 ); + StackArray< real64, 3, 2, constitutive::relperm::LAYOUT_RELPERM > faceRelPerm1( 1, 1, 2 ); + StackArray< real64, 4, 4, constitutive::relperm::LAYOUT_RELPERM_DS > dfacePhaseRelPerm1_dPhaseVolFrac( 1, 1, 2, 2 ); + StackArray< real64, 3, 2, constitutive::relperm::LAYOUT_RELPERM > trappedVolFrac1( 1, 1, 2 ); + StackArray< real64, 3, 2, constitutive::relperm::LAYOUT_RELPERM > relPerm1( 1, 1, 2 ); + StackArray< real64, 4, 4, constitutive::relperm::LAYOUT_RELPERM_DS > dPhaseRelPerm1_dPhaseVolFrac( 1, 1, 2, 2 ); + StackArray< real64, 3, 2, constitutive::relperm::LAYOUT_RELPERM > faceTrappedVolFrac2( 1, 1, 2 ); + StackArray< real64, 3, 2, constitutive::relperm::LAYOUT_RELPERM > faceRelPerm2( 1, 1, 2 ); + StackArray< real64, 4, 4, constitutive::relperm::LAYOUT_RELPERM_DS > dfacePhaseRelPerm2_dPhaseVolFrac( 1, 1, 2, 2 ); + StackArray< real64, 3, 2, constitutive::relperm::LAYOUT_RELPERM > trappedVolFrac2( 1, 1, 2 ); + StackArray< real64, 3, 2, constitutive::relperm::LAYOUT_RELPERM > relPerm2( 1, 1, 2 ); + StackArray< real64, 4, 4, constitutive::relperm::LAYOUT_RELPERM_DS > dPhaseRelPerm2_dPhaseVolFrac( 1, 1, 2, 2 ); + + StackArray< real64, 2, 2, immiscibleFlow::LAYOUT_PHASE > phaseMaxHistoricalVolFraction1( 1, 2 ); + StackArray< real64, 2, 2, immiscibleFlow::LAYOUT_PHASE > phaseMinHistoricalVolFraction1( 1, 2 ); + StackArray< real64, 2, 2, immiscibleFlow::LAYOUT_PHASE > phaseMaxHistoricalVolFraction2( 1, 2 ); + StackArray< real64, 2, 2, immiscibleFlow::LAYOUT_PHASE > phaseMinHistoricalVolFraction2( 1, 2 ); + + // compute relative permeability for both cell centers: + + trappedVolFrac1[0][0][0] = trappedSats1[0]; + trappedVolFrac1[0][0][1] = trappedSats1[1]; + + trappedVolFrac2[0][0][0] = trappedSats2[0]; + trappedVolFrac2[0][0][1] = trappedSats2[1]; + + faceTrappedVolFrac1[0][0][0] = trappedSats1[0]; + faceTrappedVolFrac1[0][0][1] = trappedSats1[1]; + + faceTrappedVolFrac2[0][0][0] = trappedSats2[0]; + faceTrappedVolFrac2[0][0][1] = trappedSats2[1]; + + using T5 = std::decay_t< decltype(castedRelPerm1) >; + if constexpr (std::is_same_v< T5, constitutive::TableRelativePermeabilityHysteresis >) { + relPermWrapper1.compute( phaseVolFrac1[0], + phaseMaxHistoricalVolFraction1[0], + phaseMinHistoricalVolFraction1[0], + trappedVolFrac1[0][0], + relPerm1[0][0], + dPhaseRelPerm1_dPhaseVolFrac[0][0] ); + + } + else + { + + relPermWrapper1.compute( phaseVolFrac1[0], + trappedVolFrac1[0][0], + relPerm1[0][0], + dPhaseRelPerm1_dPhaseVolFrac[0][0] ); + } + + using T6 = std::decay_t< decltype(castedRelPerm2) >; + if constexpr (std::is_same_v< T6, constitutive::TableRelativePermeabilityHysteresis >) { + relPermWrapper2.compute( phaseVolFrac2[0], + phaseMaxHistoricalVolFraction2[0], + phaseMinHistoricalVolFraction2[0], + trappedVolFrac2[0][0], + relPerm2[0][0], + dPhaseRelPerm2_dPhaseVolFrac[0][0] ); + + } + else + { + + relPermWrapper2.compute( phaseVolFrac2[0], + trappedVolFrac2[0][0], + relPerm2[0][0], + dPhaseRelPerm2_dPhaseVolFrac[0][0] ); + } + + + // Use of the fluid model kernel wrapper + StackArray< real64, 3, 2, constitutive::multifluid::LAYOUT_PHASE > phaseDensity1( 1, 1, 2 ); + StackArray< real64, 3, 2, constitutive::multifluid::LAYOUT_PHASE > phaseViscosity1( 1, 1, 2 ); + StackArray< real64, 4, 4, constitutive::multifluid::LAYOUT_PHASE_DC > dPhaseDens1_dP( 1, 1, 2, 2 ); + StackArray< real64, 4, 4, constitutive::multifluid::LAYOUT_PHASE_DC > dPhaseVisc1_dP( 1, 1, 2, 2 ); + StackArray< real64, 3, 2, constitutive::multifluid::LAYOUT_PHASE > phaseDensity2( 1, 1, 2 ); + StackArray< real64, 3, 2, constitutive::multifluid::LAYOUT_PHASE > phaseViscosity2( 1, 1, 2 ); + StackArray< real64, 4, 4, constitutive::multifluid::LAYOUT_PHASE_DC > dPhaseDens2_dP( 1, 1, 2, 2 ); + StackArray< real64, 4, 4, constitutive::multifluid::LAYOUT_PHASE_DC > dPhaseVisc2_dP( 1, 1, 2, 2 ); + + // Declare the MultiFluidVar (PhaseProp) type + TwoPhaseImmiscibleFluid::PhaseProp phaseDensity_temp1; + TwoPhaseImmiscibleFluid::PhaseProp phaseViscosity_temp1; + phaseDensity_temp1.value.resize( 1, 1, 2 ); // or whatever sizes you need + phaseDensity_temp1.derivs.resize( 1, 1, 2, 2 ); // make sure all dims > 0 + phaseViscosity_temp1.value.resize( 1, 1, 2 ); // or whatever sizes you need + phaseViscosity_temp1.derivs.resize( 1, 1, 2, 2 ); // make sure all dims > 0 + + auto phaseDensitySlice0 = TwoPhaseImmiscibleFluid::PhaseProp::SliceType( + phaseDensity_temp1.value[0][0], phaseDensity_temp1.derivs[0][0] ); + auto phaseViscositySlice0 = TwoPhaseImmiscibleFluid::PhaseProp::SliceType( + phaseViscosity_temp1.value[0][0], phaseViscosity_temp1.derivs[0][0] ); + fluidWrapper1.compute( pressures[0], phaseDensitySlice0, phaseViscositySlice0 ); + + // Temporary: + phaseDensity1[0][0][0] = phaseDensitySlice0.value[0]; + phaseDensity1[0][0][1] = phaseDensitySlice0.value[1]; + dPhaseDens1_dP[0][0][0][0] = phaseDensitySlice0.derivs[0][0]; + dPhaseDens1_dP[0][0][0][1] = 0; + dPhaseDens1_dP[0][0][1][0] = phaseDensitySlice0.derivs[1][0]; + dPhaseDens1_dP[0][0][1][1] = 0; + + phaseViscosity1[0][0][0] = phaseViscositySlice0.value[0]; + phaseViscosity1[0][0][1] = phaseViscositySlice0.value[1]; + dPhaseVisc1_dP[0][0][0][0] = phaseViscositySlice0.derivs[0][0]; + dPhaseVisc1_dP[0][0][0][1] = 0; + dPhaseVisc1_dP[0][0][1][0] = phaseViscositySlice0.derivs[1][0]; + dPhaseVisc1_dP[0][0][1][1] = 0; + + auto phaseDensitySlice1 = TwoPhaseImmiscibleFluid::PhaseProp::SliceType( + phaseDensity_temp1.value[0][0], phaseDensity_temp1.derivs[0][0] ); + auto phaseViscositySlice1 = TwoPhaseImmiscibleFluid::PhaseProp::SliceType( + phaseViscosity_temp1.value[0][0], phaseViscosity_temp1.derivs[0][0] ); + fluidWrapper2.compute( pressures[1], phaseDensitySlice1, phaseViscositySlice1 ); + + + phaseDensity2[0][0][0] = phaseDensitySlice1.value[0]; + phaseDensity2[0][0][1] = phaseDensitySlice1.value[1]; + dPhaseDens2_dP[0][0][0][0] = phaseDensitySlice1.derivs[0][0]; + dPhaseDens2_dP[0][0][0][1] = 0; + dPhaseDens2_dP[0][0][1][0] = phaseDensitySlice1.derivs[1][0]; + dPhaseDens2_dP[0][0][1][1] = 0; + + phaseViscosity2[0][0][0] = phaseViscositySlice1.value[0]; + phaseViscosity2[0][0][1] = phaseViscositySlice1.value[1]; + dPhaseVisc2_dP[0][0][0][0] = phaseViscositySlice1.derivs[0][0]; + dPhaseVisc2_dP[0][0][0][1] = 0; + dPhaseVisc2_dP[0][0][1][0] = phaseViscositySlice1.derivs[1][0]; + dPhaseVisc2_dP[0][0][1][1] = 0; + + // clear working arrays + real64 halfFluxVal[2][2]{}; + real64 dhalfFlux1_dP[2][2]{}; + real64 dhalfFlux1_dS[2][2]{}; + real64 dhalfFlux2_dP[2][2]{}; + real64 dhalfFlux2_dS[2][2]{}; + real64 dhalfFlux_duT[2][2]{}; + real64 dhalfFlux_dpc[2][2]{}; + + //new + real64 fluxVal[2]{}; + real64 dFlux_dP[2][2]{}; + real64 dFlux_dS[2][2]{}; + + real64 duT_dP[2]{}; + real64 duT_dS[2]{}; + + duT_dP[0] = cellCenterDuT[0]; + duT_dP[1] = cellCenterDuT[1]; + + duT_dS[0] = cellCenterDuT[2]; + duT_dS[1] = cellCenterDuT[3]; + + // initial guess: + + real64 const Pc1 = capPres1[0][0][0]; + real64 const Pc2 = capPres2[0][0][0]; + + real64 Pc_int = ( Pc1 + Pc2 ) / 2.0; + + real64 Pc_min_all = fmax( Pc1_min, Pc2_min ); + real64 Pc_max_all = fmin( Pc1_max, Pc2_max ); + + if( Pc_int < Pc_min_all || Pc_int > Pc_max_all ) + { + Pc_int = ( Pc_min_all + Pc_max_all ) / 2.0; + } + + // While loop (newton loop) + int iter = 0; + int div = 0; + int ext_iter0 = 0; + int ext_iter1 = 0; + real64 next_Pc_int = 0.0; + real64 old_Pc_int = 0.0; + real64 old_residual = 0.0; + + if (bisection) { + Pc_int = fmax( Pc1_max, Pc2_max ); + next_Pc_int = fmin( Pc1_min, Pc2_min ); + } + + if (newton_path){ + Pc_int = fmax( Pc1_max, Pc2_max ); + Pc_int = 2.0e5; + next_Pc_int = (fmax( Pc1_max, Pc2_max ) - fmin( Pc1_min, Pc2_min )) / (max_iter - 1); + next_Pc_int = (2.0e5 - 5.0e4) / (max_iter - 1); + } + + real64 Pc_int_iterate = Pc_int; + + while( iter < max_iter ) + { + + Pc_int_iterate = Pc_int; + + // clear working arrays + real64 density[2]{}; + real64 dDens_dP[2][2]{}; + real64 gravityCof[2]{}; + real64 viscosity[2]{}; + real64 dVisc_dP[2][2]{}; + + real64 viscous[2][2]{}; + real64 bouyancy[2][2]{}; + real64 capillarity[2][2]{}; + + real64 dV1_dS[2][2]{}; + real64 dG1_dS[2][2]{}; + real64 dC1_dS[2][2]{}; + real64 dV2_dS[2][2]{}; + real64 dG2_dS[2][2]{}; + real64 dC2_dS[2][2]{}; + real64 dV1_dpc[2][2]{}; + real64 dG1_dpc[2][2]{}; + real64 dC1_dpc[2][2]{}; + real64 dV2_dpc[2][2]{}; + real64 dG2_dpc[2][2]{}; + real64 dC2_dpc[2][2]{}; + + real64 local_residual = 0; + real64 local_jacobian = 0; + + // truncate the capillary pressure iterate (ensures the inverse will compute a saturation bounded between 0 and 1): + + Pc_int = fmin( fmax( Pc1_max, Pc2_max ), fmax( Pc_int, fmin( Pc1_min, Pc2_min ) )); + + faceCapPres1[0][0][0] = fmin( Pc1_max, fmax( Pc_int, Pc1_min)); + faceCapPres2[0][0][0] = fmin( Pc2_max, fmax( Pc_int, Pc2_min)); + + // Compute the inverse: + + JFunc1[0] = JFMultipliers[0]; + JFunc2[0] = JFMultipliers[1]; + + using T3 = std::decay_t< decltype(castedCapPres1) >; + if constexpr (std::is_same_v< T3, JFunctionCapillaryPressure >) { + capPresWrapper1.computeInv( facePhaseVolFrac1[0], + JFunc1.toSliceConst(), + faceCapPres1[0][0], + dfacePhaseVolFrac_dCapPres1[0][0] ); + facePhaseVolFrac1[0][0] = fmin( 1.0, fmax( facePhaseVolFrac1[0][0], 0.0 )); + facePhaseVolFrac1[0][1] = fmin( 1.0, fmax( facePhaseVolFrac1[0][1], 0.0 )); + //get derivatives: + capPresWrapper1.compute( facePhaseVolFrac1[0], + JFunc1.toSliceConst(), + faceCapPres1[0][0], + dCapPres1_dfacePhaseVolFrac[0][0] ); + + } + else + { + capPresWrapper1.computeInv( facePhaseVolFrac1[0], + faceCapPres1[0][0], + dfacePhaseVolFrac_dCapPres1[0][0] ); + facePhaseVolFrac1[0][0] = fmin( 1.0, fmax( facePhaseVolFrac1[0][0], 0.0 )); + facePhaseVolFrac1[0][1] = fmin( 1.0, fmax( facePhaseVolFrac1[0][1], 0.0 )); + //get derivatives: + capPresWrapper1.compute( facePhaseVolFrac1[0], + faceCapPres1[0][0], + dCapPres1_dfacePhaseVolFrac[0][0] ); + } + + using T4 = std::decay_t< decltype(castedCapPres2) >; + if constexpr (std::is_same_v< T4, JFunctionCapillaryPressure >) { + // evaluating cell-center Pc: + capPresWrapper2.computeInv( facePhaseVolFrac2[0], + JFunc2.toSliceConst(), + faceCapPres2[0][0], + dfacePhaseVolFrac_dCapPres2[0][0] ); + facePhaseVolFrac2[0][0] = fmin( 1.0, fmax( facePhaseVolFrac2[0][0], 0.0 )); + facePhaseVolFrac2[0][1] = fmin( 1.0, fmax( facePhaseVolFrac2[0][1], 0.0 )); + +//get derivatives: + + capPresWrapper2.compute( facePhaseVolFrac2[0], + JFunc2.toSliceConst(), + faceCapPres2[0][0], + dCapPres2_dfacePhaseVolFrac[0][0] ); + + } + else + { + // evaluating cell-center Pc: + capPresWrapper2.computeInv( facePhaseVolFrac2[0], + faceCapPres2[0][0], + dfacePhaseVolFrac_dCapPres2[0][0] ); + facePhaseVolFrac2[0][0] = fmin( 1.0, fmax( facePhaseVolFrac2[0][0], 0.0 )); + facePhaseVolFrac2[0][1] = fmin( 1.0, fmax( facePhaseVolFrac2[0][1], 0.0 )); + +//get derivatives: + + capPresWrapper2.compute( facePhaseVolFrac2[0], + faceCapPres2[0][0], + dCapPres2_dfacePhaseVolFrac[0][0] ); + } + + // compute relative permeability for both faces: + + using T7 = std::decay_t< decltype(castedRelPerm1) >; + if constexpr (std::is_same_v< T7, constitutive::TableRelativePermeabilityHysteresis >) { + + relPermWrapper1.compute( facePhaseVolFrac1[0], + phaseMaxHistoricalVolFraction1[0], + phaseMinHistoricalVolFraction1[0], + faceTrappedVolFrac1[0][0], + faceRelPerm1[0][0], + dfacePhaseRelPerm1_dPhaseVolFrac[0][0] ); + + } + else + { + + relPermWrapper1.compute( facePhaseVolFrac1[0], + faceTrappedVolFrac1[0][0], + faceRelPerm1[0][0], + dfacePhaseRelPerm1_dPhaseVolFrac[0][0] ); + } + + using T8 = std::decay_t< decltype(castedRelPerm2) >; + if constexpr (std::is_same_v< T8, constitutive::TableRelativePermeabilityHysteresis >) { + + relPermWrapper2.compute( facePhaseVolFrac2[0], + phaseMaxHistoricalVolFraction2[0], + phaseMinHistoricalVolFraction2[0], + faceTrappedVolFrac2[0][0], + faceRelPerm2[0][0], + dfacePhaseRelPerm2_dPhaseVolFrac[0][0] ); + + } + else + { + + relPermWrapper2.compute( facePhaseVolFrac2[0], + faceTrappedVolFrac2[0][0], + faceRelPerm2[0][0], + dfacePhaseRelPerm2_dPhaseVolFrac[0][0] ); + } + + + // Brenier and Jaffre's PPU upwinding: + bool check = false; + bool k_up_0_w = 1; + bool k_up_1_w = 1; + bool k_up_0_n = 1; + bool k_up_1_n = 1; + + if( uT < 0.0 ) + { + k_up_0_w = 0; + k_up_1_w = 0; + k_up_0_n = 0; + k_up_1_n = 0; + } + + if( std::fabs( uT ) < 1e-20 ) + { + k_up_0_w = 1; + k_up_1_w = 1; + k_up_0_n = 0; + k_up_1_n = 0; + } + + + localIndex k_up_0[2] = {static_cast< localIndex >(!k_up_0_w), static_cast< localIndex >(!k_up_0_n)}; + localIndex k_up_1[2] = {static_cast< localIndex >(k_up_1_w), static_cast< localIndex >(k_up_1_n)}; + bool k_up_0_check[2] = {false, false}; + bool k_up_1_check[2] = {false, false}; + + while( !check ) + { + k_up_0_check[0] = false; + k_up_0_check[1] = false; + k_up_1_check[0] = false; + k_up_1_check[1] = false; + for( integer ix = 0; ix < 2; ++ix ) // for loop over each half flux + { + + // clear working arrays for each half flux: + real64 densMean[2]{}; + real64 dDensMean_dP[2][2]{}; + + real64 presGrad[2]{}; + real64 dPresGrad_dP[2][2]{}; + + real64 gravHead[2]{}; + real64 dGravHead_dP[2][2]{}; + + real64 capGrad[2]{}; + real64 capPresIC[2][2]{}; + real64 jFMultiplier[2][2]{}; + real64 dCapGrad_dP[2][2]{}; + real64 dCapGrad_dS[2][2]{}; + + real64 mobility[2]{}; + real64 dMob_dP[2][2]{}; + real64 dMob_dS[2][2]{}; + + real64 total_mobility = 0; + gravityCof[0] = 0; + gravityCof[1] = 0; + + for( integer ip = 0; ip < 2; ++ip ) // loop over phases + { + // calculate quantities on primary connected cells + if( ix == 0 ) + { + density[ip] = phaseDensity1[0][0][ip]; + dDens_dP[ip][ix] = dPhaseDens1_dP[0][0][ip][ip]; + + viscosity[ip] = phaseViscosity1[0][0][ip]; + dVisc_dP[ip][ix] = dPhaseVisc1_dP[0][0][ip][ip]; + } + else + { + density[ip] = phaseDensity2[0][0][ip]; + dDens_dP[ip][ix] = dPhaseDens2_dP[0][0][ip][ip]; + + viscosity[ip] = phaseViscosity2[0][0][ip]; + dVisc_dP[ip][ix] = dPhaseVisc2_dP[0][0][ip][ip]; + } + + densMean[ip] = density[ip]; + dDensMean_dP[ip][0] = dDens_dP[ip][ix]; + dDensMean_dP[ip][1] = dDens_dP[ip][ix]; + + //***** calculation of flux ***** + + // compute potential difference + real64 potScale = 0.0; + real64 dPresGrad_dTrans = 0.0; + real64 dGravHead_dTrans = 0.0; + real64 dCapGrad_dTrans = 0.0; + constexpr int signPotDiff[2] = {1, -1}; + constexpr int signTix[2] = {1, -1}; + + for( integer ke = 0; ke < 2; ++ke ) + { + + real64 const pressure = pressures[ix]; + presGrad[ip] += signTix[ke] * transHat[ix] * pressure; + dPresGrad_dTrans += signPotDiff[ke] * pressure; + dPresGrad_dP[ip][ke] = signTix[ke] * transHat[ix]; + + real64 gravD = 0.0; + + if( ke == 0 ) + { + gravD += signTix[ke] * transHat[ix] * gravCoef[ix]; + } + else + { + gravD += signTix[ke] * transHat[ix] * gravCoefHat[ix]; + } + + real64 pot = signTix[ke] * transHat[ix] * pressure - densMean[ip] * gravD; + + gravHead[ip] += densMean[ip] * gravD; + gravityCof[ip] += gravD; + + dGravHead_dTrans += signPotDiff[ke] * densMean[ip] * gravCoefHat[ix]; + + for( integer i = 0; i < 2; ++i ) + { + dGravHead_dP[ip][i] += dDensMean_dP[ip][i] * gravD; + } + + real64 capPres = capPres1[0][0][ip]; + + if( ke == 1 && ix == 0 ) + { + capPres = faceCapPres1[0][0][ip]; + } + else if( ke == 1 && ix == 1 ) + { + capPres = faceCapPres2[0][0][ip]; + } + else if( ke == 0 && ix == 1 ) + { + + capPres = capPres2[0][0][ip]; + } + + dCapGrad_dTrans -= signPotDiff[ke] * capPres; + pot -= signTix[ke] * transHat[ix] * capPres; + + capGrad[ip] -= signTix[ke] * transHat[ix] * capPres; + + potScale = fmax( potScale, fabs( pot ) ); + } + + for( integer ke = 0; ke < 2; ++ke ) + { + dPresGrad_dP[ip][ke] += signTix[ke] * dTransHat_dP[ix] * dPresGrad_dTrans; + + dGravHead_dP[ip][ke] += signTix[ke] * dTransHat_dP[ix] * dGravHead_dTrans; + + real64 constexpr eps = 1e-18; + real64 dCapPres_dS = dCapPres1_dPhaseVolFrac[0][0][ip][ip]; + + if( ke == 1 && ix == 0 ) + { + dCapPres_dS = dCapPres1_dfacePhaseVolFrac[0][0][ip][ip]; + } + else if( ke == 1 && ix == 1 ) + { + dCapPres_dS = dCapPres2_dfacePhaseVolFrac[0][0][ip][ip]; + } + else if( ke == 0 && ix == 1 ) + { + dCapPres_dS = dCapPres2_dPhaseVolFrac[0][0][ip][ip]; + } + + dCapGrad_dP[ip][ke] += signTix[ke] * dTransHat_dP[ix] * dCapGrad_dTrans; + dCapGrad_dS[ip][ke] -= signTix[ke] * transHat[ix] * dCapPres_dS; + } + + // *** upwinding *** + // compute potential gradient + real64 potGrad = presGrad[ip] - gravHead[ip]; + + potGrad += capGrad[ip]; + + // choose upstream cell + constexpr int sign[2] = {1, -1}; + + if( k_up_0[ip] == 1 && ix == 0 ) + { + mobility[ip] = faceRelPerm1[0][0][ip] / viscosity[ip]; + dMob_dP[ip][k_up_0[ip]] = mobility[ip] * (-dVisc_dP[ip][ix] / viscosity[ip]); + + dMob_dS[ip][k_up_0[ip]] = sign[ip] * dfacePhaseRelPerm1_dPhaseVolFrac[0][0][ip][ip] / viscosity[ip]; + } + else if( k_up_1[ip] == 0 && ix == 1 ) + { + mobility[ip] = relPerm2[0][0][ip] / viscosity[ip]; + dMob_dP[ip][0] = mobility[ip] * (-dVisc_dP[ip][ix] / viscosity[ip]); + dMob_dS[ip][0] = sign[ip] * dPhaseRelPerm2_dPhaseVolFrac[0][0][ip][ip] / viscosity[ip]; + } + else if( k_up_1[ip] == 1 && ix == 1 ) + { + mobility[ip] = faceRelPerm2[0][0][ip] / viscosity[ip]; + dMob_dP[ip][1] = mobility[ip] * (-dVisc_dP[ip][ix] / viscosity[ip]); + dMob_dS[ip][1] = sign[ip] * dfacePhaseRelPerm2_dPhaseVolFrac[0][0][ip][ip] / viscosity[ip]; + } + else + { + mobility[ip] = relPerm1[0][0][ip] / viscosity[ip]; + dMob_dP[ip][ix] = mobility[ip] * (-dVisc_dP[ip][ix] / viscosity[ip]); + dMob_dS[ip][ix] = sign[ip] * dPhaseRelPerm1_dPhaseVolFrac[0][0][ip][ip] / viscosity[ip]; + } + real64 constexpr eps = 0.0; + total_mobility += mobility[ip] + eps; + } // loop over phases + + /// Three Forces Flux Contribution: 1- Viscous 2- Gravitational 3- Capillary + constexpr int sign[2] = {1, -1}; + real64 constexpr eps = 0.0; + + // loop over phases + for( integer ip = 0; ip < 2; ++ip ) + { + // 1- Viscous: pressure gradient depends on all points in the stencil + viscous[ip][ix] = mobility[ip] / total_mobility * uT; + halfFluxVal[ip][ix] = viscous[ip][ix]; + + for( integer ke = 0; ke < 2; ++ke ) + { + real64 dV_dP = sign[ip] * (dMob_dP[0][ke] * mobility[1] - dMob_dP[1][ke] * mobility[0]) / (total_mobility * total_mobility) * uT; + real64 dV_dS = sign[ip] * (dMob_dS[0][ke] * mobility[1] - dMob_dS[1][ke] * mobility[0]) / (total_mobility * total_mobility) * uT; + real64 dV_du = mobility[ip] / total_mobility; + + if( ix == 0 ) + { + dV1_dS[ip][ke] = dV_dS; + dhalfFlux1_dP[ip][ke] = dV_dP; + dhalfFlux1_dS[ip][ke] = dV1_dS[ip][ke]; + dhalfFlux_duT[ip][ix] = dV_du; + dV1_dpc[ip][ke] = dV1_dS[ip][ke] * dfacePhaseVolFrac_dCapPres1[0][0][0][0]; + // GEOS_UNUSED_VAR( dV1_dpc[ip][ke] ); + GEOS_UNUSED_VAR( dhalfFlux_duT[ip][ix] ); + } + else + { + dV2_dS[ip][ke] = dV_dS; + dhalfFlux2_dP[ip][ke] = dV_dP; + dhalfFlux2_dS[ip][ke] = dV2_dS[ip][ke]; + dhalfFlux_duT[ip][ix]= dV_du; + dV2_dpc[ip][ke] = dV2_dS[ip][ke] * dfacePhaseVolFrac_dCapPres2[0][0][0][0]; + // GEOS_UNUSED_VAR( dV2_dpc[ip][ke] ); + GEOS_UNUSED_VAR( dhalfFlux_duT[ip][ix] ); + } + } + + // 2- Gravitational: gravitational head depends only on the two cells connected (same as mean density) + bouyancy[ip][ix] = -1.0 * sign[ix] * sign[ip] * mobility[0] * mobility[1] / total_mobility * gravityCof[0] * (density[0] - density[1]); + halfFluxVal[ip][ix] += bouyancy[ip][ix]; + + for( integer ke = 0; ke < 2; ++ke ) + { + real64 dG_dP = sign[ix] * sign[ip] * (dMob_dP[0][ke] * mobility[1] * mobility[1] + dMob_dP[1][ke] * mobility[0] * mobility[0]) / (total_mobility * total_mobility) * gravityCof[0] * + (density[0] - density[1]) + + sign[ix] * (mobility[0] * mobility[1]) / total_mobility * (dDens_dP[0][ix] - dDens_dP[1][ix]); + + real64 dG_dS = sign[ix] * sign[ip] * (dMob_dS[0][ke] * mobility[1] * mobility[1] + dMob_dS[1][ke] * mobility[0] * mobility[0]) / (total_mobility * total_mobility) * + gravityCof[0] * (density[0] - density[1]); + + if( ix == 0 ) + { + dG1_dS[ip][ke] = dG_dS; + dhalfFlux1_dP[ip][ke] -= dG_dP; + dhalfFlux1_dS[ip][ke] -= dG1_dS[ip][ke]; + dG1_dpc[ip][ke] = dG1_dS[ip][ke] * dfacePhaseVolFrac_dCapPres1[0][0][0][0]; + // GEOS_UNUSED_VAR( dG1_dpc[ip][ke] ); + } + else + { + dG2_dS[ip][ke] = dG_dS; + dhalfFlux2_dP[ip][ke] -= dG_dP; + dhalfFlux2_dS[ip][ke] -= dG2_dS[ip][ke]; + dG2_dpc[ip][ke] = dG2_dS[ip][ke] * dfacePhaseVolFrac_dCapPres2[0][0][0][0]; + // GEOS_UNUSED_VAR( dG2_dpc[ip][ke] ); + } + } + + // 3- Capillary: capillary pressure contribution + capillarity[ip][ix] = -1.0 * sign[ix] * sign[ip] * mobility[0] * mobility[1] / total_mobility * (capGrad[1] -capGrad[0]); + halfFluxVal[ip][ix] += capillarity[ip][ix]; + + for( integer ke = 0; ke < 2; ++ke ) + { + real64 dC_dP = sign[ix] * sign[ip] * (dMob_dP[0][ke] * mobility[1] * mobility[1] + dMob_dP[1][ke] * mobility[0] * mobility[0]) / (total_mobility * total_mobility) * + (capGrad[1] -capGrad[0]) + + sign[ix] * sign[ip] * mobility[0] * mobility[1] / total_mobility * (dCapGrad_dP[1][ke] - dCapGrad_dP[0][ke]); + + real64 dC_dS_term1 = sign[ix] * sign[ip] * (dMob_dS[0][ke] * mobility[1] * mobility[1] + dMob_dS[1][ke] * mobility[0] * mobility[0]) / (total_mobility * total_mobility) * + (capGrad[1] -capGrad[0]); + + real64 dC_dS_term2 = sign[ix] * sign[ip] * (mobility[0] * mobility[1]) / total_mobility; + + real64 dC_dS_term3 = (dCapGrad_dS[1][ke] - dCapGrad_dS[0][ke]); + + if( ix == 0 ) + { + dC1_dS[ip][ke] = dC_dS_term1 + dC_dS_term2 * dC_dS_term3; + dhalfFlux1_dP[ip][ke] -= dC_dP; + dhalfFlux1_dS[ip][ke] -= dC1_dS[ip][ke]; + // if (std::fabs(facePhaseVolFrac1[0][0] - 1.0) > 1e-8){ + dC1_dpc[ip][ke] = dC1_dS[ip][ke] * dfacePhaseVolFrac_dCapPres1[0][0][0][0]; + // } else { + // dC1_dpc[ip][ke] = dC_dS_term1 * dfacePhaseVolFrac_dCapPres1[0][0][0][0]; + // } + + // GEOS_UNUSED_VAR( dC1_dpc[ip][ke] ); + } + else + { + dC2_dS[ip][ke] = dC_dS_term1 + dC_dS_term2 * dC_dS_term3; + dhalfFlux2_dP[ip][ke] -= dC_dP; + dhalfFlux2_dS[ip][ke] -= dC2_dS[ip][ke]; + // if (std::fabs(facePhaseVolFrac2[0][0] - 1.0) > 1e-8){ + dC2_dpc[ip][ke] = dC2_dS[ip][ke] * dfacePhaseVolFrac_dCapPres2[0][0][0][0]; + // } else { + // dC2_dpc[ip][ke] = dC_dS_term1 * dfacePhaseVolFrac_dCapPres2[0][0][0][0]; + // } + // GEOS_UNUSED_VAR( dC2_dpc[ip][ke] ); + } + + } + + + if( halfFluxVal[ip][0] > 0.0 ) + { + k_up_0_check[ip] = true; + } + if( halfFluxVal[ip][1] > 0.0 ) + { + k_up_1_check[ip] = true; + } + + } // loop over phases + + } // loop over half fluxes + + check = true; + + // Brenier and Jaffre's PPU check: + bool flip0[2] = {0, 0}; + bool flip0_k_up[2] = {0, 0}; + bool flip1[2] = {0, 0}; + bool flip1_k_up[2] = {0, 0}; + // loop over phases + for( integer ip = 0; ip < 2; ++ip ) + { + bool k_up_0_b = !static_cast< bool >(k_up_0[ip]); + bool k_up_1_b = static_cast< bool >(k_up_1[ip]); + flip0_k_up[ip] = k_up_0_b; + flip1_k_up[ip] = k_up_1_b; + + if( std::fabs( uT ) < 1e-20 ) + { + + if((std::fabs( halfFluxVal[ip][0] ) < 1e-20) && (std::fabs( halfFluxVal[ip][1] ) < 1e-20)) + { + k_up_0_check[ip] = !k_up_0_b; + k_up_1_check[ip] = !k_up_1_b; + } + else + { + k_up_0_check[ip] = k_up_0_b; + k_up_1_check[ip] = k_up_1_b; + } + + if( k_up_0_check[ip] != k_up_0_b ) + { + flip0[ip] = 1; + check = false; + } + + if( k_up_1_check[ip] != k_up_1_b ) + { + flip1[ip] = 1; + check = false; + } + + } + else + { + if( std::fabs( halfFluxVal[ip][0] ) < 1e-20 ) + { + k_up_0_check[ip] = k_up_0_b; + } + + if( std::fabs( halfFluxVal[ip][1] ) < 1e-20 ) + { + k_up_1_check[ip] = k_up_1_b; + } + + if( k_up_0_check[ip] != k_up_0_b ) + { + k_up_0[ip] = static_cast< localIndex >(k_up_0_b); + check = false; + } + + if( k_up_1_check[ip] != k_up_1_b ) + { + k_up_1[ip] = static_cast< localIndex >(!k_up_1_b); + check = false; + } + } + + } + + if( flip0[0] || flip0[1] ) + { + k_up_0[0] = static_cast< localIndex >(flip0_k_up[0]); + k_up_0[1] = static_cast< localIndex >(flip0_k_up[1]); + } + + if( flip1[0] || flip1[1] ) + { + k_up_1[0] = static_cast< localIndex >(!flip1_k_up[0]); + k_up_1[1] = static_cast< localIndex >(!flip1_k_up[1]); + } + + } // while check for BJ PPU + + real64 constexpr eps2 = 1.0e-18; + // newton update + dhalfFlux_dpc[0][0] = dhalfFlux1_dS[0][1]*dfacePhaseVolFrac_dCapPres1[0][0][0][0]; + real64 dhalfFlux_dpc00 = dV1_dpc[0][1] - dG1_dpc[0][1] - dC1_dpc[0][1]; + dhalfFlux_dpc[0][1] = dhalfFlux2_dS[0][1]*dfacePhaseVolFrac_dCapPres2[0][0][0][0]; + real64 dhalfFlux_dpc01 = dV2_dpc[0][1] - dG2_dpc[0][1] - dC2_dpc[0][1]; + + dhalfFlux_dpc[1][0] = dhalfFlux1_dS[1][1]*dfacePhaseVolFrac_dCapPres1[0][0][0][0]; + real64 dhalfFlux_dpc10 = dV1_dpc[1][1] - dG1_dpc[1][1] - dC1_dpc[1][1]; + dhalfFlux_dpc[1][1] = dhalfFlux2_dS[1][1]*dfacePhaseVolFrac_dCapPres2[0][0][0][0]; + real64 dhalfFlux_dpc11 = dV2_dpc[1][1] - dG2_dpc[1][1] - dC2_dpc[1][1]; + + dhalfFlux_dpc[0][0] = dhalfFlux_dpc00; + dhalfFlux_dpc[0][1] = dhalfFlux_dpc01; + dhalfFlux_dpc[1][0] = dhalfFlux_dpc10; + dhalfFlux_dpc[1][1] = dhalfFlux_dpc11; + + local_jacobian = dhalfFlux_dpc[0][0] - dhalfFlux_dpc[0][1] + eps2; + local_residual = halfFluxVal[0][0] - halfFluxVal[0][1]; + + // if (iter == 1) { + // grad_phi[0] = local_residual; + // } + + // Check convergence + if( std::fabs( local_residual ) < tol ) + { + converged = 1; + break; // Converged + } + // converged = 0; + if( (!converged) && ( iter > (max_iter - 2)) ) + { + if( div == 0 ) + { + iter = 0; + div++; + Pc_int = Pc_min_all; + } + else if( div == 1 ) + { + iter = 0; + div++; + Pc_int = Pc_max_all; + } + else if( div > 1 ) + { + local_jacobian = 0.0; + std::cout << "**********************Diverged*******************" << std::endl; + iter = max_iter; + } + } + else + { + + real64 deltaPc = local_residual/local_jacobian; + + // if (std::fabs(facePhaseVolFrac1[0][0] - 1.0) < 1e-5 && (std::fabs(deltaPc * dfacePhaseVolFrac_dCapPres2[0][0][0][0]) < 0.05)){ + // ext_iter0++; + // } + // if (std::fabs(facePhaseVolFrac2[0][0] - 1.0) < 1e-5 && (std::fabs(deltaPc * dfacePhaseVolFrac_dCapPres1[0][0][0][0]) < 0.05)){ + // ext_iter1++; + // } + + // if (ext_iter0 > 20){ + // halfFluxVal[0][1] = halfFluxVal[0][0]; + // halfFluxVal[1][1] = halfFluxVal[1][0]; + // local_residual = halfFluxVal[0][0] - halfFluxVal[0][1]; + // } + + // if (ext_iter1 > 20){ + // halfFluxVal[0][0] = halfFluxVal[0][1]; + // halfFluxVal[1][0] = halfFluxVal[1][1]; + // local_residual = halfFluxVal[0][0] - halfFluxVal[0][1]; + // } + + if( std::fabs( local_residual ) < tol ) + { + converged = 1; + break; // Converged + } + + // Damping option: + if (damping) { + real64 max_dpc = fmax( fabs(dCapPres1_dfacePhaseVolFrac[0][0][0][0]), fabs(dCapPres2_dfacePhaseVolFrac[0][0][0][0])); + + real64 sign = std::copysign(1.0, deltaPc); + + deltaPc = fmin( fabs(deltaPc), max_dpc * 0.2 ); + deltaPc *= sign; + + } + + if (bisection && iter < 7){ + if ( iter == 0 ){ + + old_Pc_int = Pc_int; + Pc_int = next_Pc_int; + old_residual = local_residual; + + } else if (old_residual * local_residual < 0.0 ) { + + Pc_int = (next_Pc_int + old_Pc_int) / 2.0; + old_residual = local_residual; + old_Pc_int = next_Pc_int; + next_Pc_int = Pc_int; + + } else if (old_residual * local_residual > 0.0 ) { + + Pc_int = old_Pc_int; + old_residual = local_residual; + old_Pc_int = next_Pc_int; + next_Pc_int = Pc_int; + + } else { + + Pc_int = old_Pc_int; + old_residual = local_residual; + old_Pc_int = next_Pc_int; + next_Pc_int = Pc_int; + + } + + } else if (newton_path){ + Pc_int -= next_Pc_int; + + } else { + + Pc_int -= deltaPc; + + } + + + // truncate the updated capillary pressure (extended capillary pressure condition) for reporting/plotting: + + real64 faceCapPres1_plot = fmin( Pc1_max, fmax( Pc_int, Pc1_min )); + real64 faceCapPres2_plot = fmin( Pc2_max, fmax( Pc_int, Pc2_min )); + faceCapPres1_plot = fmin( Pc2_max, fmax( faceCapPres1_plot, Pc2_min )); + faceCapPres2_plot = fmin( Pc1_max, fmax( faceCapPres2_plot, Pc1_min )); + + // Write data to the file + outFile << GEOS_FMT( "{:10.10e}", local_jacobian ); + outFile << GEOS_FMT( ",{:10.10e}", local_residual ); + outFile << GEOS_FMT( ",{:10.10e}", halfFluxVal[0][0] ); + outFile << GEOS_FMT( ",{:10.10e}", halfFluxVal[0][1] ); + outFile << GEOS_FMT( ",{:10.10e}", Pc_int_iterate ); + outFile << GEOS_FMT( ",{:10.10e}", faceCapPres1[0][0][0] ); + outFile << GEOS_FMT( ",{:10.10e}", faceCapPres2[0][0][0] ); + outFile << GEOS_FMT( ",{:10.10e}", halfFluxVal[1][0] ); + outFile << GEOS_FMT( ",{:10.10e}", halfFluxVal[1][1] ); + outFile << GEOS_FMT( ",{:10.10e}", viscous[0][0] ); + outFile << GEOS_FMT( ",{:10.10e}", viscous[1][0] ); + outFile << GEOS_FMT( ",{:10.10e}", viscous[0][1] ); + outFile << GEOS_FMT( ",{:10.10e}", viscous[1][1] ); + outFile << GEOS_FMT( ",{:10.10e}", bouyancy[0][0] ); + outFile << GEOS_FMT( ",{:10.10e}", bouyancy[1][0] ); + outFile << GEOS_FMT( ",{:10.10e}", bouyancy[0][1] ); + outFile << GEOS_FMT( ",{:10.10e}", bouyancy[1][1] ); + outFile << GEOS_FMT( ",{:10.10e}", capillarity[0][0] ); + outFile << GEOS_FMT( ",{:10.10e}", capillarity[1][0] ); + outFile << GEOS_FMT( ",{:10.10e}", capillarity[0][1] ); + outFile << GEOS_FMT( ",{:10.10e}", capillarity[1][1] ); + outFile << GEOS_FMT( ",{:10.10e}", capPres1[0][0][0] ); + outFile << GEOS_FMT( ",{:10.10e}", capPres1[0][0][1] ); + outFile << GEOS_FMT( ",{:10.10e}", facePhaseVolFrac1[0][0] ); + outFile << GEOS_FMT( ",{:10.10e}", facePhaseVolFrac2[0][0] ); + outFile << std::endl; + + iter++; + + } + + + } // while loop + + if( converged ) + { + + // Global derivatives: + real64 constexpr eps3 = 1.0e-18; + + real64 const dPc_int_dS1 =(-1.0) * (dhalfFlux1_dS[0][0] + dhalfFlux_duT[0][0] * duT_dS[0] - dhalfFlux_duT[0][1] * duT_dS[0]) / (dhalfFlux_dpc[0][0] - dhalfFlux_dpc[0][1] + eps3); + real64 const dPc_int_dS2 =(-1.0) * (dhalfFlux_duT[0][0] * duT_dS[1] - dhalfFlux2_dS[0][0] - dhalfFlux_duT[0][1] * duT_dS[1]) / (dhalfFlux_dpc[0][0] - dhalfFlux_dpc[0][1] + eps3); + real64 const dPc_int_du =(-1.0) * (dhalfFlux_duT[0][0] - dhalfFlux_duT[0][1]) / (dhalfFlux_dpc[0][0] - dhalfFlux_dpc[0][1] + eps3); + + dFlux_dP[0][0] = (dhalfFlux_duT[0][0] * duT_dP[0] + dhalfFlux_dpc[0][0] * dPc_int_du * duT_dP[0]) * density2[0] + halfFluxVal[0][0] * dDens_dP2[0][0]; + dFlux_dS[0][0] = (dhalfFlux1_dS[0][0] + dhalfFlux_duT[0][0] * duT_dS[0] + dhalfFlux_dpc[0][0] * dPc_int_dS1) * density2[0]; + + dFlux_dP[0][1] = (dhalfFlux_duT[0][1] * duT_dP[1] + dhalfFlux_dpc[0][1] * dPc_int_du * duT_dP[1]) * density2[0] + halfFluxVal[0][1] * dDens_dP2[0][1]; + dFlux_dS[0][1] = (dhalfFlux2_dS[0][0] + dhalfFlux_duT[0][1] * duT_dS[1] + dhalfFlux_dpc[0][1] * dPc_int_dS2) * density2[0]; + + dFlux_dP[1][0] = (dhalfFlux_duT[1][0] * duT_dP[0] + dhalfFlux_dpc[1][0] * dPc_int_du * duT_dP[0]) * density2[1] + halfFluxVal[1][0] * dDens_dP2[1][0]; + dFlux_dS[1][0] = (dhalfFlux1_dS[1][0] + dhalfFlux_duT[1][0] * duT_dS[0] + dhalfFlux_dpc[1][0] * dPc_int_dS1) * density2[1]; + + dFlux_dP[1][1] = (dhalfFlux_duT[1][1] * duT_dP[1] + dhalfFlux_dpc[1][1] * dPc_int_du * duT_dP[1]) * density2[1] + halfFluxVal[1][1] * dDens_dP2[1][1]; + dFlux_dS[1][1] = (dhalfFlux2_dS[1][0] + dhalfFlux_duT[1][1] * duT_dS[1] + dhalfFlux_dpc[1][1] * dPc_int_dS2) * density2[1]; + + fluxVal[0] = halfFluxVal[0][0] * density2[0]; + fluxVal[1] = halfFluxVal[1][0] * density2[1]; + + } else { + std::cout << "**********************Diverged*******************" << std::endl; + + } + + phi[0] = fluxVal[0]; + phi[1] = fluxVal[1]; + + grad_phi_P[0] = dFlux_dP[0][0]; + grad_phi_P[1] = dFlux_dP[0][1]; + grad_phi_P[2] = dFlux_dP[1][0]; + grad_phi_P[3] = dFlux_dP[1][1]; + + grad_phi_S[0] = dFlux_dS[0][0]; + grad_phi_S[1] = dFlux_dS[0][1]; + grad_phi_S[2] = dFlux_dS[1][0]; + grad_phi_S[3] = dFlux_dS[1][1]; + + converged = 1; + GEOS_UNUSED_VAR( converged ); +// Close the file after writing + outFile.close(); + + } ); + + } ); + + } ); + + } ); + + +} /******************************** FluxComputeKernelBase ********************************/ @@ -68,7 +1320,6 @@ using namespace constitutive; * on template parameters (like stencil type and number of dofs). */ class FluxComputeKernelBase - { public: @@ -269,33 +1520,33 @@ class FluxComputeKernel : public FluxComputeKernelBase * @param[in] hasCapPressure flags for capillary pressure * @param[in] useTotalMassEquation flags for using total velocity formulation */ -FluxComputeKernel( integer const numPhases, - globalIndex const rankOffset, - STENCILWRAPPER const & stencilWrapper, - DofNumberAccessor const & dofNumberAccessor, - ImmiscibleMultiphaseFlowAccessors const & multiPhaseFlowAccessors, - MultiphaseFluidAccessors const & fluidAccessors, - CapPressureAccessors const & capPressureAccessors, - PermeabilityAccessors const & permeabilityAccessors, - real64 const & dt, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs, - integer const hasCapPressure, - integer const useTotalMassEquation, - integer const checkPhasePresenceInGravity ) - : FluxComputeKernelBase( numPhases, - rankOffset, - dofNumberAccessor, - multiPhaseFlowAccessors, - fluidAccessors, - capPressureAccessors, - permeabilityAccessors, - dt, - localMatrix, - localRhs, - hasCapPressure, - useTotalMassEquation, - checkPhasePresenceInGravity ), + FluxComputeKernel( integer const numPhases, + globalIndex const rankOffset, + STENCILWRAPPER const & stencilWrapper, + DofNumberAccessor const & dofNumberAccessor, + ImmiscibleMultiphaseFlowAccessors const & multiPhaseFlowAccessors, + MultiphaseFluidAccessors const & fluidAccessors, + CapPressureAccessors const & capPressureAccessors, + PermeabilityAccessors const & permeabilityAccessors, + real64 const & dt, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs, + integer const hasCapPressure, + integer const useTotalMassEquation, + integer const checkPhasePresenceInGravity ) + : FluxComputeKernelBase( numPhases, + rankOffset, + dofNumberAccessor, + multiPhaseFlowAccessors, + fluidAccessors, + capPressureAccessors, + permeabilityAccessors, + dt, + localMatrix, + localRhs, + hasCapPressure, + useTotalMassEquation, + checkPhasePresenceInGravity ), m_stencilWrapper( stencilWrapper ), m_seri( stencilWrapper.getElementRegionIndices() ), m_sesri( stencilWrapper.getElementSubRegionIndices() ), @@ -402,7 +1653,7 @@ FluxComputeKernel( integer const numPhases, * @param[inout] stack the stack variables * @param[in] NoOpFunc the function used to customize the computation of the flux */ - template< typename FUNC = NoOpFunc > // should change to multiphase + template< typename FUNC = NoOpFunc > // should change to multiphase GEOS_HOST_DEVICE void computeFlux( localIndex const iconn, StackVariables & stack, @@ -467,22 +1718,22 @@ FluxComputeKernel( integer const numPhases, continue; } - real64 const density = m_dens[seri[ke]][sesri[ke]][sei[ke]][0][ip]; // r = rho1 || rho2 - real64 const dDens_dP = m_dDens_dPres[seri[ke]][sesri[ke]][sei[ke]][0][ip][Deriv::dP]; // dr/dP = dr1/dP1 || dr2/dP + real64 const density = m_dens[seri[ke]][sesri[ke]][sei[ke]][0][ip]; // r = rho1 || rho2 + real64 const dDens_dP = m_dDens_dPres[seri[ke]][sesri[ke]][sei[ke]][0][ip][Deriv::dP]; // dr/dP = dr1/dP1 || dr2/dP // average density and derivatives - densMean[ip] += density; // rho = (rho1 + rho2) - dDensMean_dP[ip][ke] = dDens_dP; // drho/dP = { (dr1/dP1) , (dr2/dP2) } + densMean[ip] += density; // rho = (rho1 + rho2) + dDensMean_dP[ip][ke] = dDens_dP; // drho/dP = { (dr1/dP1) , (dr2/dP2) } denom++; } if( denom > 1 ) { - densMean[ip] /= denom; // rho = (rho1 + rho2) / denom + densMean[ip] /= denom; // rho = (rho1 + rho2) / denom for( integer ke = 0; ke < 2; ++ke ) { - dDensMean_dP[ip][ke] /= denom; // drho/dP = { (dr1/dP1) / denom , (dr2/dP2) / denom } + dDensMean_dP[ip][ke] /= denom; // drho/dP = { (dr1/dP1) / denom , (dr2/dP2) / denom } } } @@ -501,106 +1752,114 @@ FluxComputeKernel( integer const numPhases, localIndex const esr = sesri[ke]; localIndex const ei = sei[ke]; - real64 const pressure = m_pres[er][esr][ei]; // P = P1 || P2 - presGrad[ip] += trans[ke] * pressure; // DPv = T (P1 - P2) - dPresGrad_dTrans += signPotDiff[ke] * pressure; // dDPv/dT = (P1 - P2) - dPresGrad_dP[ip][ke] = trans[ke]; // dDPv/dP = { T , -T } + real64 const pressure = m_pres[er][esr][ei]; // P = P1 || P2 + presGrad[ip] += trans[ke] * pressure; // DPv = T (P1 - P2) + dPresGrad_dTrans += signPotDiff[ke] * pressure; // dDPv/dT = (P1 - P2) + dPresGrad_dP[ip][ke] = trans[ke]; // dDPv/dP = { T , -T } - real64 const gravD = trans[ke] * m_gravCoef[er][esr][ei]; // D = T g z1 || -T g z2 - real64 pot = trans[ke] * pressure - densMean[ip] * gravD; // Phi = T P1 - rho T g z1 || -T P2 + rho T g z2 + real64 const gravD = trans[ke] * m_gravCoef[er][esr][ei]; // D = T g z1 || -T g z2 + real64 pot = trans[ke] * pressure - densMean[ip] * gravD; // Phi = T P1 - rho T g z1 || -T P2 + rho T g z2 - gravHead[ip] += densMean[ip] * gravD; // DPg = rho (T g z1 - T g z2) = T rho g (z1 - z2) - dGravHead_dTrans += signPotDiff[ke] * densMean[ip] * m_gravCoef[er][esr][ei]; // dDPg/dT = rho g z1 - rho g z2 = rho g (z1 - z2) + gravHead[ip] += densMean[ip] * gravD; // DPg = rho (T g z1 - T g z2) = T rho g (z1 - + // z2) + dGravHead_dTrans += signPotDiff[ke] * densMean[ip] * m_gravCoef[er][esr][ei]; // dDPg/dT = rho g z1 - rho g z2 = rho g (z1 - + // z2) for( integer i = 0; i < 2; ++i ) { - dGravHead_dP[ip][i] += dDensMean_dP[ip][i] * gravD; // dDPg/dP = {drho/dP1 * T g (z1 - z2) , drho/dP2 * T g (z1 - z2)} + dGravHead_dP[ip][i] += dDensMean_dP[ip][i] * gravD; // dDPg/dP = {drho/dP1 * T g (z1 - z2) , drho/dP2 * T g (z1 - z2)} } - if( m_hasCapPressure ) // check sign convention + if( m_hasCapPressure ) // check sign convention { - real64 const capPres = m_phaseCapPressure[er][esr][ei][0][ip]; // Pc = Pc1 || Pc2 - dCapGrad_dTrans -= signPotDiff[ke] * capPres; // dDPc/dT = (-Pc1 + Pc2) - pot -= trans[ke] * capPres; // Phi = T P1 - rho T g z1 - T Pc1 || -T P2 + rho T g z2 + T - // Pc2 - capGrad[ip] -= trans[ke] * capPres; // DPc = T (-Pc1 + Pc2) + real64 const capPres = m_phaseCapPressure[er][esr][ei][0][ip]; // Pc = Pc1 || Pc2 + dCapGrad_dTrans -= signPotDiff[ke] * capPres; // dDPc/dT = (-Pc1 + Pc2) + pot -= trans[ke] * capPres; // Phi = T P1 - rho T g z1 - T Pc1 || -T P2 + rho T g z2 + T + // Pc2 + capGrad[ip] -= trans[ke] * capPres; // DPc = T (-Pc1 + Pc2) } - potScale = fmax( potScale, fabs( pot ) ); // maxPhi = Phi1 > Phi2 ? Phi1 : Phi2 + potScale = fmax( potScale, fabs( pot ) ); // maxPhi = Phi1 > Phi2 ? Phi1 : Phi2 } for( integer ke = 0; ke < 2; ++ke ) { - dPresGrad_dP[ip][ke] += dTrans_dP[ke] * dPresGrad_dTrans; // dDPv/dP = { T + dT/dP1 * (P1 - P2) , -T + dT/dP2 * (P1 - P2)} - dGravHead_dP[ip][ke] += dTrans_dP[ke] * dGravHead_dTrans; // dDPg/dP = { drho/dP1 * T g (z1 - z2) + dT/dP1 * rho g (z1 - z2) , - // drho/dP2 * T g (z1 - z2) + dT/dP2 * rho g (z1 - z2) } + dPresGrad_dP[ip][ke] += dTrans_dP[ke] * dPresGrad_dTrans; // dDPv/dP = { T + dT/dP1 * (P1 - P2) , -T + dT/dP2 * (P1 - P2)} + dGravHead_dP[ip][ke] += dTrans_dP[ke] * dGravHead_dTrans; // dDPg/dP = { drho/dP1 * T g (z1 - z2) + dT/dP1 * rho g (z1 - z2) + // , + // drho/dP2 * T g (z1 - z2) + dT/dP2 * rho g (z1 - z2) + // } if( m_hasCapPressure ) { - real64 const dCapPres_dS = m_dPhaseCapPressure_dPhaseVolFrac[seri[ke]][sesri[ke]][sei[ke]][0][ip][ip]; // dPc/dS = dPc1/dS1 || - // dPc2/dS2 - dCapGrad_dP[ip][ke] += dTrans_dP[ke] * dCapGrad_dTrans; // dDPc/dP = { dT/dP1 * - // (-Pc1 + Pc2) , - // dT/dP2 * - // (-Pc1 + Pc2) } - dCapGrad_dS[ip][ke] -= trans[ke] * dCapPres_dS; // dDPc/dS = { -T * - // dPc1/dS1 , T * - // dPc2/dS2 } + real64 const dCapPres_dS = m_dPhaseCapPressure_dPhaseVolFrac[seri[ke]][sesri[ke]][sei[ke]][0][ip][ip]; // dPc/dS = dPc1/dS1 + // || + // dPc2/dS2 + dCapGrad_dP[ip][ke] += dTrans_dP[ke] * dCapGrad_dTrans; // dDPc/dP = { dT/dP1 + // * + // (-Pc1 + Pc2) , + // dT/dP2 + // * + // (-Pc1 + Pc2) } + dCapGrad_dS[ip][ke] -= trans[ke] * dCapPres_dS; // dDPc/dS = { -T * + // dPc1/dS1 , T * + // dPc2/dS2 } } } // *** upwinding *** // compute potential gradient - real64 potGrad = presGrad[ip] - gravHead[ip]; // DPhi = T (P1 - P2) - T rho g (z1 - z2) + real64 potGrad = presGrad[ip] - gravHead[ip]; // DPhi = T (P1 - P2) - T rho g (z1 - z2) if( m_hasCapPressure ) { - potGrad += capGrad[ip]; // DPhi = T (P1 - P2) - T rho g (z1 - z2) + T (-Pc1 + Pc2) + potGrad += capGrad[ip]; // DPhi = T (P1 - P2) - T rho g (z1 - z2) + T (-Pc1 + Pc2) } // compute upwinding tolerance real64 constexpr upwRelTol = 1e-8; - real64 const upwAbsTol = fmax( potScale * upwRelTol, LvArray::NumericLimits< real64 >::epsilon ); // abstol = maxPhi * tol > eps ? - // maxPhi * tol : eps + real64 const upwAbsTol = fmax( potScale * upwRelTol, LvArray::NumericLimits< real64 >::epsilon ); // abstol = maxPhi * tol > eps + // ? + // maxPhi * tol : eps // decide mobility coefficients - smooth variation in [-upwAbsTol; upwAbsTol] - real64 const alpha = ( potGrad + upwAbsTol ) / ( 2 * upwAbsTol ); // alpha = (DPhi + abstol) / abstol / 2 + real64 const alpha = ( potGrad + upwAbsTol ) / ( 2 * upwAbsTol ); // alpha = (DPhi + abstol) / abstol / 2 // choose upstream cell - if( alpha <= 0.0 || alpha >= 1.0 ) // no smoothing needed + if( alpha <= 0.0 || alpha >= 1.0 ) // no smoothing needed { - localIndex const k_up = 1 - localIndex( fmax( fmin( alpha, 1.0 ), 0.0 ) ); // 1 upwind -> k_up = 0 || 2 upwind -> k_up = 1 + localIndex const k_up = 1 - localIndex( fmax( fmin( alpha, 1.0 ), 0.0 ) ); // 1 upwind -> k_up = 0 || 2 upwind -> k_up = 1 - mobility[ip] = m_mob[seri[k_up]][sesri[k_up]][sei[k_up]][ip]; // M = Mupstream - dMob_dP[ip][k_up] = m_dMob[seri[k_up]][sesri[k_up]][sei[k_up]][ip][Deriv::dP]; // dM/dP = {dM/dP1 , 0} OR {0 , dM/dP2} - dMob_dS[ip][k_up] = m_dMob[seri[k_up]][sesri[k_up]][sei[k_up]][ip][Deriv::dS]; // dM/dS = {dM/dS1 , 0} OR {0 , dM/dS2} + mobility[ip] = m_mob[seri[k_up]][sesri[k_up]][sei[k_up]][ip]; // M = Mupstream + dMob_dP[ip][k_up] = m_dMob[seri[k_up]][sesri[k_up]][sei[k_up]][ip][Deriv::dP]; // dM/dP = {dM/dP1 , 0} OR {0 , dM/dP2} + dMob_dS[ip][k_up] = m_dMob[seri[k_up]][sesri[k_up]][sei[k_up]][ip][Deriv::dS]; // dM/dS = {dM/dS1 , 0} OR {0 , dM/dS2} } - else // perform smoothing + else // perform smoothing { real64 const mobWeights[2] = { alpha, 1.0 - alpha }; for( integer ke = 0; ke < 2; ++ke ) { - mobility[ip] += mobWeights[ke] * m_mob[seri[ke]][sesri[ke]][sei[ke]][ip]; // M = alpha * M1 + (1 - alpha) * M2 - dMob_dP[ip][ke] = mobWeights[ke] * m_dMob[seri[ke]][sesri[ke]][sei[ke]][ip][Deriv::dP]; // dM/dP = {alpha * dM1/dP1 , (1 - - // alpha) * dM2/dP2} - dMob_dS[ip][ke] = mobWeights[ke] * m_dMob[seri[ke]][sesri[ke]][sei[ke]][ip][Deriv::dS]; // dM/dP = {alpha * dM1/dS1 , (1 - - // alpha) * dM2/dS2} + mobility[ip] += mobWeights[ke] * m_mob[seri[ke]][sesri[ke]][sei[ke]][ip]; // M = alpha * M1 + (1 - alpha) * M2 + dMob_dP[ip][ke] = mobWeights[ke] * m_dMob[seri[ke]][sesri[ke]][sei[ke]][ip][Deriv::dP]; // dM/dP = {alpha * dM1/dP1 , (1 - + // alpha) * dM2/dP2} + dMob_dS[ip][ke] = mobWeights[ke] * m_dMob[seri[ke]][sesri[ke]][sei[ke]][ip][Deriv::dS]; // dM/dP = {alpha * dM1/dS1 , (1 - + // alpha) * dM2/dS2} } } // pressure gradient depends on all points in the stencil for( integer ke = 0; ke < 2; ++ke ) { - dFlux_dP[ip][ke] += dPresGrad_dP[ip][ke]; // dF/dP = { T + dT/dP1 * (P1 - P2) , - // -T + dT/dP2 * (P1 - P2) } + dFlux_dP[ip][ke] += dPresGrad_dP[ip][ke]; // dF/dP = { T + dT/dP1 * (P1 - P2) , + // -T + dT/dP2 * (P1 - P2) } } // gravitational head depends only on the two cells connected (same as mean density) for( integer ke = 0; ke < 2; ++ke ) { - dFlux_dP[ip][ke] -= dGravHead_dP[ip][ke]; // dF/dP = { T + dT/dP1 * (P1 - P2) - drho/dP1 * T g (z1 - z2) - dT/dP1 * rho g (z1 - - // z2) , - // -T + dT/dP2 * (P1 - P2) - drho/dP2 * T g (z1 - z2) - dT/dP2 * rho g (z1 - - // z2) } + dFlux_dP[ip][ke] -= dGravHead_dP[ip][ke]; // dF/dP = { T + dT/dP1 * (P1 - P2) - drho/dP1 * T g (z1 - z2) - dT/dP1 * rho g (z1 - + // z2) , + // -T + dT/dP2 * (P1 - P2) - drho/dP2 * T g (z1 - z2) - dT/dP2 * rho g (z1 - + // z2) } } // capillary pressure contribution @@ -608,38 +1867,38 @@ FluxComputeKernel( integer const numPhases, { for( integer ke = 0; ke < 2; ++ke ) { - dFlux_dP[ip][ke] += dCapGrad_dP[ip][ke]; // dF/dP = { T + dT/dP1 * (P1 - P2) - drho/dP1 * T g (z1 - z2) - dT/dP1 * rho g (z1 - // - z2) + dT/dP1 * (-Pc1 + Pc2) , - // -T + dT/dP2 * (P1 - P2) - drho/dP2 * T g (z1 - z2) - dT/dP2 * rho g (z1 - // - z2) + dT/dP2 * (-Pc1 + Pc2) } + dFlux_dP[ip][ke] += dCapGrad_dP[ip][ke]; // dF/dP = { T + dT/dP1 * (P1 - P2) - drho/dP1 * T g (z1 - z2) - dT/dP1 * rho g (z1 + // - z2) + dT/dP1 * (-Pc1 + Pc2) , + // -T + dT/dP2 * (P1 - P2) - drho/dP2 * T g (z1 - z2) - dT/dP2 * rho g (z1 + // - z2) + dT/dP2 * (-Pc1 + Pc2) } - dFlux_dS[ip][ke] += dCapGrad_dS[ip][ke]; // dF/dS = { T * -dPc/dS1 , T * dPc/dS2 } + dFlux_dS[ip][ke] += dCapGrad_dS[ip][ke]; // dF/dS = { T * -dPc/dS1 , T * dPc/dS2 } } } // compute the flux and derivatives using upstream cell mobility - fluxVal[ip] = mobility[ip] * potGrad; // F = M * DPhi + fluxVal[ip] = mobility[ip] * potGrad; // F = M * DPhi for( integer ke = 0; ke < 2; ++ke ) { - dFlux_dP[ip][ke] *= mobility[ip]; // dF/dP = { M [ T + dT/dP1 * (P1 - P2) - drho/dP1 * T g (z1 - z2) - dT/dP1 * rho g (z1 - - // z2) + dT/dP1 * (-Pc1 + Pc2)] , - // M [-T + dT/dP2 * (P1 - P2) - drho/dP2 * T g (z1 - z2) - dT/dP2 * rho g (z1 - - // z2) + dT/dP2 * (-Pc1 + Pc2)] } + dFlux_dP[ip][ke] *= mobility[ip]; // dF/dP = { M [ T + dT/dP1 * (P1 - P2) - drho/dP1 * T g (z1 - z2) - dT/dP1 * rho g (z1 - + // z2) + dT/dP1 * (-Pc1 + Pc2)] , + // M [-T + dT/dP2 * (P1 - P2) - drho/dP2 * T g (z1 - z2) - dT/dP2 * rho g (z1 - + // z2) + dT/dP2 * (-Pc1 + Pc2)] } - dFlux_dS[ip][ke] *= mobility[ip]; // dF/dS = { M [T * -dPc/dS1] , M [T * dPc/dS2] } + dFlux_dS[ip][ke] *= mobility[ip]; // dF/dS = { M [T * -dPc/dS1] , M [T * dPc/dS2] } } // add contribution from upstream cell mobility derivatives for( integer ke = 0; ke < 2; ++ke ) { - dFlux_dP[ip][ke] += dMob_dP[ip][ke] * potGrad; // dF/dP = { M [ T + dT/dP1 * (P1 - P2) - drho1/dP * T g (z1 - z2) - dT/dP1 * - // rho g (z1 - z2) + dT/dP1 * (-Pc1 + Pc2)] + dM/dP1 * DPhi , - // M [-T + dT/dP2 * (P1 - P2) - drho2/dP * T g (z1 - z2) - dT/dP2 * - // rho g (z1 - z2) + dT/dP2 * (-Pc1 + Pc2)] + dM/dP2 * DPhi } + dFlux_dP[ip][ke] += dMob_dP[ip][ke] * potGrad; // dF/dP = { M [ T + dT/dP1 * (P1 - P2) - drho1/dP * T g (z1 - z2) - dT/dP1 * + // rho g (z1 - z2) + dT/dP1 * (-Pc1 + Pc2)] + dM/dP1 * DPhi , + // M [-T + dT/dP2 * (P1 - P2) - drho2/dP * T g (z1 - z2) - dT/dP2 * + // rho g (z1 - z2) + dT/dP2 * (-Pc1 + Pc2)] + dM/dP2 * DPhi } - dFlux_dS[ip][ke] += dMob_dS[ip][ke] * potGrad; // dF/dS = { M [T * -dPc/dS1] + dM/dS1 * DPhi , M [T * dPc/dS2] + dM/dS2 * DPhi - // } + dFlux_dS[ip][ke] += dMob_dS[ip][ke] * potGrad; // dF/dS = { M [T * -dPc/dS1] + dM/dS1 * DPhi , M [T * dPc/dS2] + dM/dS2 * DPhi + // } } // populate local flux vector and derivatives @@ -660,14 +1919,14 @@ FluxComputeKernel( integer const numPhases, } // Customize the kernel with this lambda - kernelOp( k, seri, sesri, sei, connectionIndex, alpha, mobility, potGrad, fluxVal, dFlux_dP, dFlux_dS ); // Not sure what this - // does + kernelOp( k, seri, sesri, sei, connectionIndex, alpha, mobility, potGrad, fluxVal, dFlux_dP, dFlux_dS ); // Not sure what this + // does - } // loop over phases + } // loop over phases connectionIndex++; } - } // loop over connection elements + } // loop over connection elements } /** @@ -675,7 +1934,7 @@ FluxComputeKernel( integer const numPhases, * @param[in] iconn the connection index * @param[inout] stack the stack variables */ - template< typename FUNC = NoOpFunc > // should change to multiphase + template< typename FUNC = NoOpFunc > // should change to multiphase GEOS_HOST_DEVICE void complete( localIndex const iconn, StackVariables & stack, @@ -770,7 +2029,7 @@ FluxComputeKernel( integer const numPhases, * @tparam RELPERMWRAPPER the type of the realtive permeability wrapper * @brief Define the interface for the assembly kernel in charge of flux terms */ -template< integer NUM_EQN, integer NUM_DOF, typename STENCILWRAPPER, typename CAPPRESWRAPPER, typename RELPERMWRAPPER > +template< integer NUM_EQN, integer NUM_DOF, typename STENCILWRAPPER, typename CAPPRESWRAPPER, typename RELPERMWRAPPER > class FluxComputeInterfaceConditionKernel : public FluxComputeKernel< NUM_EQN, NUM_DOF, STENCILWRAPPER > { public: @@ -835,22 +2094,30 @@ class FluxComputeInterfaceConditionKernel : public FluxComputeKernel< NUM_EQN, N * @param[in] useTotalMassEquation flags for using total velocity formulation */ FluxComputeInterfaceConditionKernel( integer const numPhases, - globalIndex const rankOffset, - STENCILWRAPPER const & stencilWrapper, - CAPPRESWRAPPER const & capPressureWrapper, - RELPERMWRAPPER const & relPermWrapper, - DofNumberAccessor const & dofNumberAccessor, - ImmiscibleMultiphaseFlowAccessors const & multiPhaseFlowAccessors, - MultiphaseFluidAccessors const & fluidAccessors, - CapPressureAccessors const & capPressureAccessors, - PermeabilityAccessors const & permeabilityAccessors, - real64 const & dt, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs, - integer const hasCapPressure, - integer const useTotalMassEquation, - integer const checkPhasePresenceInGravity, - localIndex const GEOS_UNUSED_PARAM(domainSize) ) + globalIndex const rankOffset, + STENCILWRAPPER const & stencilWrapper, + CAPPRESWRAPPER const & capPressureWrapper, + RELPERMWRAPPER const & relPermWrapper, + DofNumberAccessor const & dofNumberAccessor, + ImmiscibleMultiphaseFlowAccessors const & multiPhaseFlowAccessors, + MultiphaseFluidAccessors const & fluidAccessors, + CapPressureAccessors const & capPressureAccessors, + PermeabilityAccessors const & permeabilityAccessors, + real64 const & dt, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs, + integer const hasCapPressure, + integer const useTotalMassEquation, + integer const checkPhasePresenceInGravity, + string_array const & interfaceFaceSetNames, + stdVector< std::array< std::tuple< constitutive::RelativePermeabilityBase *, + constitutive::CapillaryPressureBase *, + constitutive::TwoPhaseImmiscibleFluid * >, 2 > > const & interfaceConstitutivePairs, + unordered_map< localIndex, localIndex > const & interfaceRegionByConnector, + std::tuple< constitutive::RelativePermeabilityBase *, + constitutive::CapillaryPressureBase *, + constitutive::TwoPhaseImmiscibleFluid * > const & interfaceConstitutivePairs_temp, + localIndex const GEOS_UNUSED_PARAM( domainSize ) ) : Base( numPhases, rankOffset, stencilWrapper, @@ -866,7 +2133,11 @@ class FluxComputeInterfaceConditionKernel : public FluxComputeKernel< NUM_EQN, N useTotalMassEquation, checkPhasePresenceInGravity ), m_capPressureWrapper( capPressureWrapper ), - m_relPermWrapper( relPermWrapper ) + m_relPermWrapper( relPermWrapper ), + m_interfaceFaceSetNames( interfaceFaceSetNames ), + m_interfaceConstitutivePairs( interfaceConstitutivePairs ), + m_interfaceRegionByConnector( interfaceRegionByConnector ), + m_interfaceConstitutivePairs_temp( interfaceConstitutivePairs_temp ) {} /** @@ -876,15 +2147,30 @@ class FluxComputeInterfaceConditionKernel : public FluxComputeKernel< NUM_EQN, N * @param[inout] stack the stack variables * @param[in] NoOpFunc the function used to customize the computation of the flux */ - - template< typename FUNC = NoOpFunc > // should change to multiphase + + template< typename FUNC = NoOpFunc > // should change to multiphase GEOS_HOST_DEVICE void computeFlux( localIndex const iconn, StackVariables & stack, FUNC && kernelOp = NoOpFunc{} ) const { - // first, compute the transmissibilities at this face // get k and dk/dP from global arrays - // and place in stack + + bool connectorHasInterfaceConditionQ = false; + bool anyInterfaceConditionsQ = not m_interfaceConstitutivePairs.empty(); + if (anyInterfaceConditionsQ) { + connectorHasInterfaceConditionQ = + m_interfaceRegionByConnector.find(iconn) != m_interfaceRegionByConnector.end(); + } + + + // if (connectorHasInterfaceConditionQ){ + // // Improved transmission conditions + // int ammar_code = 0; + // }else{ + // // Regular contribution + // int standard_code = 0; + // } + m_stencilWrapper.computeWeights( iconn, m_permeability, m_dPerm_dPres, @@ -894,30 +2180,14 @@ class FluxComputeInterfaceConditionKernel : public FluxComputeKernel< NUM_EQN, N localIndex k[2]; localIndex connectionIndex = 0; - // // Create an output file stream object (ofstream) - // std::ofstream outFile("iterations.csv"); - - - // // Write data to the file - // outFile << "Jacobian"; - // outFile << ","; - // outFile << "residual"; - // outFile << ","; - // outFile << "F_alpha"; - // outFile << ","; - // outFile << "F_beta"; - // outFile << ","; - // outFile << "Pc"; - // outFile << ","; - // outFile << "newton"; - // outFile << std::endl; - - + // one-sided transmissibility m_stencilWrapper.computeHalfWeights( iconn, - m_permeability, - m_dPerm_dPres, - stack.transmissibilityHat, - stack.dTransHat_dPres ); + m_permeability, + m_dPerm_dPres, + stack.transmissibilityHat, + stack.dTransHat_dPres ); + + for( k[0] = 0; k[0] < stack.numFluxElems; ++k[0] ) { @@ -949,6 +2219,9 @@ class FluxComputeInterfaceConditionKernel : public FluxComputeKernel< NUM_EQN, N real64 density2[numEqn]{}; real64 dDens_dP2[numEqn][2]{}; + real64 viscosity[numEqn]{}; + real64 dVisc_dP[numEqn][2]{}; + real64 gravCoef2[numEqn]{}; real64 gravCoefHat[numEqn]{}; real64 uT = 0; @@ -962,14 +2235,18 @@ class FluxComputeInterfaceConditionKernel : public FluxComputeKernel< NUM_EQN, N real64 const trans[2] = { stack.transmissibility[connectionIndex][0], stack.transmissibility[connectionIndex][1] }; real64 const dTrans_dP[2] = { stack.dTrans_dPres[connectionIndex][0], stack.dTrans_dPres[connectionIndex][1] }; - real64 const transHat[2] = { stack.transmissibilityHat[connectionIndex][0], stack.transmissibilityHat[connectionIndex][1] }; - real64 const dTransHat_dP[2] = { stack.dTransHat_dPres[connectionIndex][0], stack.dTransHat_dPres[connectionIndex][1] }; + real64 const transHat[2] = { stack.transmissibilityHat[connectionIndex][0], stack.transmissibilityHat[connectionIndex][1] * -1.0}; + real64 const dTransHat_dP[2] = { stack.dTransHat_dPres[connectionIndex][0], stack.dTransHat_dPres[connectionIndex][1] * -1.0}; // cell indices localIndex const seri[2] = {m_seri( iconn, k[0] ), m_seri( iconn, k[1] )}; localIndex const sesri[2] = {m_sesri( iconn, k[0] ), m_sesri( iconn, k[1] )}; localIndex const sei[2] = {m_sei( iconn, k[0] ), m_sei( iconn, k[1] )}; + stdVector< real64 > saturations = {m_phaseVolFrac[seri[0]][sesri[0]][sei[0]][0], m_phaseVolFrac[seri[1]][sesri[1]][sei[1]][0] }; + stdVector< real64 > pressures = {m_pres[seri[0]][sesri[0]][sei[0]], m_pres[seri[1]][sesri[1]][sei[1]] }; + bool isJfunction = 1; + // loop over phases for( integer ip = 0; ip < m_numPhases; ++ip ) { @@ -984,13 +2261,11 @@ class FluxComputeInterfaceConditionKernel : public FluxComputeKernel< NUM_EQN, N continue; } - real64 const density = m_dens[seri[ke]][sesri[ke]][sei[ke]][0][ip]; // r = rho1 || rho2 - real64 const dDens_dP = m_dDens_dPres[seri[ke]][sesri[ke]][sei[ke]][0][ip][Deriv::dP]; // dr/dP = dr1/dP1 || dr2/dP - + real64 const density = m_dens[seri[ke]][sesri[ke]][sei[ke]][0][ip]; // r = rho1 || rho2 + real64 const dDens_dP = m_dDens_dPres[seri[ke]][sesri[ke]][sei[ke]][0][ip][Deriv::dP]; // dr/dP = dr1/dP1 || dr2/dP // average density and derivatives - densMean[ip] += density; // rho = (rho1 + rho2) - dDensMean_dP[ip][ke] = dDens_dP; // drho/dP = { (dr1/dP1) , (dr2/dP2) } - + densMean[ip] += density; // rho = (rho1 + rho2) + dDensMean_dP[ip][ke] = dDens_dP; // drho/dP = { (dr1/dP1) , (dr2/dP2) } denom++; } @@ -1020,17 +2295,19 @@ class FluxComputeInterfaceConditionKernel : public FluxComputeKernel< NUM_EQN, N localIndex const esr = sesri[ke]; localIndex const ei = sei[ke]; - real64 const pressure = m_pres[er][esr][ei]; // P = P1 || P2 - presGrad[ip] += trans[ke] * pressure; // DPv = T (P1 - P2) - dPresGrad_dTrans += signPotDiff[ke] * pressure; // dDPv/dT = (P1 - P2) - dPresGrad_dP[ip][ke] = trans[ke]; // dDPv/dP = { T , -T } + real64 const pressure = m_pres[er][esr][ei]; // P = P1 || P2 + presGrad[ip] += trans[ke] * pressure; // DPv = T (P1 - P2) + dPresGrad_dTrans += signPotDiff[ke] * pressure; // dDPv/dT = (P1 - P2) + dPresGrad_dP[ip][ke] = trans[ke]; // dDPv/dP = { T , -T } - real64 const gravD = trans[ke] * m_gravCoef[er][esr][ei]; // D = T g z1 || -T g z2 + real64 const gravD = trans[ke] * m_gravCoef[er][esr][ei]; // D = T g z1 || -T g z2 real64 pot = trans[ke] * pressure - densMean[ip] * gravD; // Phi = T P1 - rho T g z1 || -T P2 + rho T g z2 gravCoefHat[0] += m_gravCoef[er][esr][ei] * 0.5; gravCoefHat[1] += m_gravCoef[er][esr][ei] * 0.5; - gravHead[ip] += densMean[ip] * gravD; // DPg = rho (T g z1 - T g z2) = T rho g (z1 - z2) + gravCoef2[ke] = m_gravCoef[er][esr][ei]; + + gravHead[ip] += densMean[ip] * gravD; // DPg = rho (T g z1 - T g z2) = T rho g (z1 - z2) dGravHead_dTrans += signPotDiff[ke] * densMean[ip] * m_gravCoef[er][esr][ei]; // dDPg/dT = rho g z1 - rho g z2 = rho g (z1 - z2) for( integer i = 0; i < 2; ++i ) @@ -1038,16 +2315,16 @@ class FluxComputeInterfaceConditionKernel : public FluxComputeKernel< NUM_EQN, N dGravHead_dP[ip][i] += dDensMean_dP[ip][i] * gravD; // dDPg/dP = {drho/dP1 * T g (z1 - z2) , drho/dP2 * T g (z1 - z2)} } - if( m_hasCapPressure ) // check sign convention + if( m_hasCapPressure ) // check sign convention { - real64 const capPres = m_phaseCapPressure[er][esr][ei][0][ip]; // Pc = Pc1 || Pc2 - jFMultiplier[ip][ke] = m_jFuncMultiplier[er][esr][ei][0]; + real64 const capPres = m_phaseCapPressure[er][esr][ei][0][ip]; // Pc = Pc1 || Pc2 + jFMultiplier[ip][ke] = m_jFuncMultiplier[er][esr][ei][0]; capPresIC[ip][ke] = capPres; - dCapGrad_dTrans -= signPotDiff[ke] * capPres; // dDPc/dT = (-Pc1 + Pc2) - pot -= trans[ke] * capPres; // Phi = T P1 - rho T g z1 - T Pc1 || -T P2 + rho T g z2 + T - // Pc2 - capGrad[ip] -= trans[ke] * capPres; // DPc = T (-Pc1 + Pc2) + dCapGrad_dTrans -= signPotDiff[ke] * capPres; // dDPc/dT = (-Pc1 + Pc2) + pot -= trans[ke] * capPres; // Phi = T P1 - rho T g z1 - T Pc1 || -T P2 + rho T g z2 + T + // Pc2 + capGrad[ip] -= trans[ke] * capPres; // DPc = T (-Pc1 + Pc2) } potScale = fmax( potScale, fabs( pot ) ); // maxPhi = Phi1 > Phi2 ? Phi1 : Phi2 @@ -1056,25 +2333,24 @@ class FluxComputeInterfaceConditionKernel : public FluxComputeKernel< NUM_EQN, N for( integer ke = 0; ke < 2; ++ke ) { - dPresGrad_dP[ip][ke] += dTrans_dP[ke] * dPresGrad_dTrans; // dDPv/dP = { T + dT/dP1 * (P1 - P2) , -T + dT/dP2 * (P1 - P2)} - dGravHead_dP[ip][ke] += dTrans_dP[ke] * dGravHead_dTrans; // dDPg/dP = { drho/dP1 * T g (z1 - z2) + dT/dP1 * rho g (z1 - z2) , - // drho/dP2 * T g (z1 - z2) + dT/dP2 * rho g (z1 - z2) } + dPresGrad_dP[ip][ke] += dTrans_dP[ke] * dPresGrad_dTrans; // dDPv/dP = { T + dT/dP1 * (P1 - P2) , -T + dT/dP2 * (P1 - P2)} + dGravHead_dP[ip][ke] += dTrans_dP[ke] * dGravHead_dTrans; // dDPg/dP = { drho/dP1 * T g (z1 - z2) + dT/dP1 * rho g (z1 - z2) , + // drho/dP2 * T g (z1 - z2) + dT/dP2 * rho g (z1 - z2) } if( m_hasCapPressure ) { real64 const dCapPres_dS = m_dPhaseCapPressure_dPhaseVolFrac[seri[ke]][sesri[ke]][sei[ke]][0][ip][ip]; // dPc/dS = dPc1/dS1 || - // dPc2/dS2 - dCapGrad_dP[ip][ke] += dTrans_dP[ke] * dCapGrad_dTrans; // dDPc/dP = { dT/dP1 * - // (-Pc1 + Pc2) , - // dT/dP2 * - // (-Pc1 + Pc2) } - dCapGrad_dS[ip][ke] -= trans[ke] * dCapPres_dS; // dDPc/dS = { -T * - // dPc1/dS1 , T * - // dPc2/dS2 } + // dPc2/dS2 + dCapGrad_dP[ip][ke] += dTrans_dP[ke] * dCapGrad_dTrans; // dDPc/dP = { dT/dP1 * + // (-Pc1 + Pc2) , + // dT/dP2 * + // (-Pc1 + Pc2) } + dCapGrad_dS[ip][ke] -= trans[ke] * dCapPres_dS; // dDPc/dS = { -T * + // dPc1/dS1 , T * + // dPc2/dS2 } } } // *** upwinding *** - // compute potential gradient real64 potGrad = presGrad[ip] - gravHead[ip]; // DPhi = T (P1 - P2) - T rho g (z1 - z2) if( m_hasCapPressure ) @@ -1085,35 +2361,39 @@ class FluxComputeInterfaceConditionKernel : public FluxComputeKernel< NUM_EQN, N // compute upwinding tolerance real64 constexpr upwRelTol = 1e-8; real64 const upwAbsTol = fmax( potScale * upwRelTol, LvArray::NumericLimits< real64 >::epsilon ); // abstol = maxPhi * tol > eps ? - // maxPhi * tol : eps + // maxPhi * tol : eps // decide mobility coefficients - smooth variation in [-upwAbsTol; upwAbsTol] - real64 alpha = ( potGrad + upwAbsTol ) / ( 2 * upwAbsTol ); // alpha = (DPhi + abstol) / abstol / 2 + real64 alpha = ( potGrad + upwAbsTol ) / ( 2 * upwAbsTol ); // alpha = (DPhi + abstol) / abstol / 2 // choose upstream cell - if( alpha <= 0.0 || alpha >= 1.0 ) // no smoothing needed + if( alpha <= 0.0 || alpha >= 1.0 ) // no smoothing needed { localIndex const k_up = 1 - localIndex( fmax( fmin( alpha, 1.0 ), 0.0 ) ); // 1 upwind -> k_up = 0 || 2 upwind -> k_up = 1 - mobility[ip] = m_mob[seri[k_up]][sesri[k_up]][sei[k_up]][ip]; // M = Mupstream - density2[ip] = m_dens[seri[k_up]][sesri[k_up]][sei[k_up]][0][ip]; // r = rho1 || rho2 - dDens_dP2[ip][k_up] = m_dDens_dPres[seri[k_up]][sesri[k_up]][sei[k_up]][0][ip][Deriv::dP]; // dr/dP = dr1/dP1 || dr2/dP - dMob_dP[ip][k_up] = m_dMob[seri[k_up]][sesri[k_up]][sei[k_up]][ip][Deriv::dP]; // dM/dP = {dM/dP1 , 0} OR {0 , dM/dP2} - dMob_dS[ip][k_up] = m_dMob[seri[k_up]][sesri[k_up]][sei[k_up]][ip][Deriv::dS]; // dM/dS = {dM/dS1 , 0} OR {0 , dM/dS2} + mobility[ip] = m_mob[seri[k_up]][sesri[k_up]][sei[k_up]][ip]; // M = Mupstream + density2[ip] = m_dens[seri[k_up]][sesri[k_up]][sei[k_up]][0][ip]; // r = rho1 || rho2 + dDens_dP2[ip][k_up] = m_dDens_dPres[seri[k_up]][sesri[k_up]][sei[k_up]][0][ip][Deriv::dP]; // dr/dP = dr1/dP1 || dr2/dP + viscosity[ip] = m_visc[seri[k_up]][sesri[k_up]][sei[k_up]][0][ip]; + dVisc_dP[ip][k_up] = m_dVisc_dPres[seri[k_up]][sesri[k_up]][sei[k_up]][0][ip][Deriv::dP]; + dMob_dP[ip][k_up] = m_dMob[seri[k_up]][sesri[k_up]][sei[k_up]][ip][Deriv::dP]; // dM/dP = {dM/dP1 , 0} OR {0 , dM/dP2} + dMob_dS[ip][k_up] = m_dMob[seri[k_up]][sesri[k_up]][sei[k_up]][ip][Deriv::dS]; // dM/dS = {dM/dS1 , 0} OR {0 , dM/dS2} } - else // perform smoothing + else // perform smoothing { real64 const mobWeights[2] = { alpha, 1.0 - alpha }; for( integer ke = 0; ke < 2; ++ke ) { - mobility[ip] += mobWeights[ke] * m_mob[seri[ke]][sesri[ke]][sei[ke]][ip]; // M = alpha * M1 + (1 - alpha) * M2 - density2[ip] += mobWeights[ke] * m_dens[seri[ke]][sesri[ke]][sei[ke]][0][ip]; // r = rho1 || rho2 - dDens_dP2[ip][ke] = mobWeights[ke] * m_dDens_dPres[seri[ke]][sesri[ke]][sei[ke]][0][ip][Deriv::dP]; // dr/dP = dr1/dP1 || - // dr2/dP + mobility[ip] += mobWeights[ke] * m_mob[seri[ke]][sesri[ke]][sei[ke]][ip]; // M = alpha * M1 + (1 - alpha) * M2 + density2[ip] += mobWeights[ke] * m_dens[seri[ke]][sesri[ke]][sei[ke]][0][ip]; // r = rho1 || rho2 + dDens_dP2[ip][ke] = mobWeights[ke] * m_dDens_dPres[seri[ke]][sesri[ke]][sei[ke]][0][ip][Deriv::dP]; // dr/dP = dr1/dP1 || + // dr2/dP + viscosity[ip] = m_visc[seri[ke]][sesri[ke]][sei[ke]][0][ip]; + dVisc_dP[ip][ke] = m_dVisc_dPres[seri[ke]][sesri[ke]][sei[ke]][0][ip][Deriv::dP]; dMob_dP[ip][ke] = mobWeights[ke] * m_dMob[seri[ke]][sesri[ke]][sei[ke]][ip][Deriv::dP]; // dM/dP = {alpha * dM1/dP1 , (1 - - // alpha) * dM2/dP2} + // alpha) * dM2/dP2} dMob_dS[ip][ke] = mobWeights[ke] * m_dMob[seri[ke]][sesri[ke]][sei[ke]][ip][Deriv::dS]; // dM/dP = {alpha * dM1/dS1 , (1 - - // alpha) * dM2/dS2} + // alpha) * dM2/dS2} } } @@ -1121,16 +2401,16 @@ class FluxComputeInterfaceConditionKernel : public FluxComputeKernel< NUM_EQN, N for( integer ke = 0; ke < 2; ++ke ) { dFlux_dP[ip][ke] += dPresGrad_dP[ip][ke]; // dF/dP = { T + dT/dP1 * (P1 - P2) , - // -T + dT/dP2 * (P1 - P2) } + // -T + dT/dP2 * (P1 - P2) } } // gravitational head depends only on the two cells connected (same as mean density) for( integer ke = 0; ke < 2; ++ke ) { dFlux_dP[ip][ke] -= dGravHead_dP[ip][ke]; // dF/dP = { T + dT/dP1 * (P1 - P2) - drho/dP1 * T g (z1 - z2) - dT/dP1 * rho g (z1 - - // z2) , - // -T + dT/dP2 * (P1 - P2) - drho/dP2 * T g (z1 - z2) - dT/dP2 * rho g (z1 - - // z2) } + // z2) , + // -T + dT/dP2 * (P1 - P2) - drho/dP2 * T g (z1 - z2) - dT/dP2 * rho g (z1 - + // z2) } } // capillary pressure contribution @@ -1138,12 +2418,12 @@ class FluxComputeInterfaceConditionKernel : public FluxComputeKernel< NUM_EQN, N { for( integer ke = 0; ke < 2; ++ke ) { - dFlux_dP[ip][ke] += dCapGrad_dP[ip][ke]; // dF/dP = { T + dT/dP1 * (P1 - P2) - drho/dP1 * T g (z1 - z2) - dT/dP1 * rho g (z1 - // - z2) + dT/dP1 * (-Pc1 + Pc2) , - // -T + dT/dP2 * (P1 - P2) - drho/dP2 * T g (z1 - z2) - dT/dP2 * rho g (z1 - // - z2) + dT/dP2 * (-Pc1 + Pc2) } + dFlux_dP[ip][ke] += dCapGrad_dP[ip][ke]; // dF/dP = { T + dT/dP1 * (P1 - P2) - drho/dP1 * T g (z1 - z2) - dT/dP1 * rho g (z1 + // - z2) + dT/dP1 * (-Pc1 + Pc2) , + // -T + dT/dP2 * (P1 - P2) - drho/dP2 * T g (z1 - z2) - dT/dP2 * rho g (z1 + // - z2) + dT/dP2 * (-Pc1 + Pc2) } - dFlux_dS[ip][ke] += dCapGrad_dS[ip][ke]; // dF/dS = { T * -dPc/dS1 , T * dPc/dS2 } + dFlux_dS[ip][ke] += dCapGrad_dS[ip][ke]; // dF/dS = { T * -dPc/dS1 , T * dPc/dS2 } } } @@ -1152,534 +2432,260 @@ class FluxComputeInterfaceConditionKernel : public FluxComputeKernel< NUM_EQN, N for( integer ke = 0; ke < 2; ++ke ) { - dFlux_dP[ip][ke] *= mobility[ip]; // dF/dP = { M [ T + dT/dP1 * (P1 - P2) - drho/dP1 * T g (z1 - z2) - dT/dP1 * rho g (z1 - - // z2) + dT/dP1 * (-Pc1 + Pc2)] , - // M [-T + dT/dP2 * (P1 - P2) - drho/dP2 * T g (z1 - z2) - dT/dP2 * rho g (z1 - - // z2) + dT/dP2 * (-Pc1 + Pc2)] } + dFlux_dP[ip][ke] *= mobility[ip]; // dF/dP = { M [ T + dT/dP1 * (P1 - P2) - drho/dP1 * T g (z1 - z2) - dT/dP1 * rho g (z1 - + // z2) + dT/dP1 * (-Pc1 + Pc2)] , + // M [-T + dT/dP2 * (P1 - P2) - drho/dP2 * T g (z1 - z2) - dT/dP2 * rho g (z1 - + // z2) + dT/dP2 * (-Pc1 + Pc2)] } - dFlux_dS[ip][ke] *= mobility[ip]; // dF/dS = { M [T * -dPc/dS1] , M [T * dPc/dS2] } + dFlux_dS[ip][ke] *= mobility[ip]; // dF/dS = { M [T * -dPc/dS1] , M [T * dPc/dS2] } } // add contribution from upstream cell mobility derivatives for( integer ke = 0; ke < 2; ++ke ) { - dFlux_dP[ip][ke] += dMob_dP[ip][ke] * potGrad; // dF/dP = { M [ T + dT/dP1 * (P1 - P2) - drho1/dP * T g (z1 - z2) - dT/dP1 * - // rho g (z1 - z2) + dT/dP1 * (-Pc1 + Pc2)] + dM/dP1 * DPhi , - // M [-T + dT/dP2 * (P1 - P2) - drho2/dP * T g (z1 - z2) - dT/dP2 * - // rho g (z1 - z2) + dT/dP2 * (-Pc1 + Pc2)] + dM/dP2 * DPhi } - dFlux_dS[ip][ke] += dMob_dS[ip][ke] * potGrad; // dF/dS = { M [T * -dPc/dS1] + dM/dS1 * DPhi , M [T * dPc/dS2] + dM/dS2 * DPhi - // } + + real64 dMob_dP2 = mobility[ip] / density2[ip] * (-dVisc_dP[ip][ke] / viscosity[ip]); + + duT_dP[ke] += dFlux_dP[ip][ke] / density2[ip] + dMob_dP2 * potGrad; + + dFlux_dP[ip][ke] += dMob_dP[ip][ke] * potGrad; // dF/dP = { M [ T + dT/dP1 * (P1 - P2) - drho1/dP * T g (z1 - z2) - dT/dP1 * + // rho g (z1 - z2) + dT/dP1 * (-Pc1 + Pc2)] + dM/dP1 * DPhi , + // M [-T + dT/dP2 * (P1 - P2) - drho2/dP * T g (z1 - z2) - dT/dP2 * + // rho g (z1 - z2) + dT/dP2 * (-Pc1 + Pc2)] + dM/dP2 * DPhi } + dFlux_dS[ip][ke] += dMob_dS[ip][ke] * potGrad; // dF/dS = { M [T * -dPc/dS1] + dM/dS1 * DPhi , M [T * dPc/dS2] + dM/dS2 * DPhi + // } } + uT += fluxVal[ip] / density2[ip]; // add contribution from upstream cell mobility derivatives for( integer ke = 0; ke < 2; ++ke ) { - duT_dP[ke] += dFlux_dP[ip][ke] - fluxVal[ip] * dDens_dP2[ip][ke] / density2[ip]; - - duT_dP[ke] /= density2[ip]; - duT_dS[ke] += dFlux_dS[ip][ke] / density2[ip]; +// duT_dP[ke] += dFlux_dP[ip][ke] - fluxVal[ip] * dDens_dP2[ip][ke] / density2[ip]; +// // duT_dP[ke] += dFlux_dP[ip][ke]; + +// duT_dP[ke] /= density2[ip]; + + duT_dS[ke] += dFlux_dS[ip][ke] / density2[ip]; + // duT_dS[ke] += dFlux_dS[ip][ke]; + } potGrad_ip[ip] = potGrad; alpha_ip[ip] = alpha; } // loop over phases - // std::cout << GEOS_FMT( " Pc1 = ( {:4.2e} )", capPresIC[1][0] ); - // std::cout << GEOS_FMT( " Pc2 = ( {:4.2e} )", capPresIC[1][1] ); - if (std::fabs(jFMultiplier[0][0] - jFMultiplier[0][1]) < 1e-8 && std::fabs(jFMultiplier[1][0] - jFMultiplier[1][1]) < 1e-8 ) { - for( integer ip = 0; ip < 2; ++ip ) { - // populate local flux vector and derivatives - stack.localFlux[k[0]*numEqn + ip] += m_dt * fluxVal[ip]; - stack.localFlux[k[1]*numEqn + ip] -= m_dt * fluxVal[ip]; - - for( integer ke = 0; ke < 2; ++ke ) + // this determines whether the local solver is needed becuase of heterogeneous capillary pressure regions + bool notOnInterface = std::fabs( jFMultiplier[0][0] - jFMultiplier[0][1] ) < 1 && std::fabs( jFMultiplier[1][0] - jFMultiplier[1][1] ) < 1; + notOnInterface = !connectorHasInterfaceConditionQ; + if( notOnInterface ) + { + for( integer ip = 0; ip < 2; ++ip ) { - // pressure - localIndex const localDofIndexPres = k[ke] * numDof; - stack.localFluxJacobian[k[0]*numEqn + ip][localDofIndexPres] += m_dt * dFlux_dP[ip][ke]; - stack.localFluxJacobian[k[1]*numEqn + ip][localDofIndexPres] -= m_dt * dFlux_dP[ip][ke]; - - // saturation (hard-coded for 2-phase currently) - localIndex const localDofIndexSat = k[ke] * numDof + 1; - stack.localFluxJacobian[k[0]*numEqn + ip][localDofIndexSat] += m_dt * dFlux_dS[ip][ke]; - stack.localFluxJacobian[k[1]*numEqn + ip][localDofIndexSat] -= m_dt * dFlux_dS[ip][ke]; - } + // populate local flux vector and derivatives + stack.localFlux[k[0]*numEqn + ip] += m_dt * fluxVal[ip]; + stack.localFlux[k[1]*numEqn + ip] -= m_dt * fluxVal[ip]; - // Customize the kernel with this lambda - kernelOp( k, seri, sesri, sei, connectionIndex, alpha_ip[ip], mobility, potGrad_ip[ip], fluxVal, dFlux_dP, dFlux_dS ); // Not sure what this - - }// does - } else { + for( integer ke = 0; ke < 2; ++ke ) + { + // pressure + localIndex const localDofIndexPres = k[ke] * numDof; + stack.localFluxJacobian[k[0]*numEqn + ip][localDofIndexPres] += m_dt * dFlux_dP[ip][ke]; + stack.localFluxJacobian[k[1]*numEqn + ip][localDofIndexPres] -= m_dt * dFlux_dP[ip][ke]; + + // saturation + localIndex const localDofIndexSat = k[ke] * numDof + 1; + stack.localFluxJacobian[k[0]*numEqn + ip][localDofIndexSat] += m_dt * dFlux_dS[ip][ke]; + stack.localFluxJacobian[k[1]*numEqn + ip][localDofIndexSat] -= m_dt * dFlux_dS[ip][ke]; + } - - + // Customize the kernel with this lambda + kernelOp( k, seri, sesri, sei, connectionIndex, alpha_ip[ip], mobility, potGrad_ip[ip], fluxVal, dFlux_dP, dFlux_dS ); + } + } + else + { - // -------------------- Here I implement the interface conditions local solver --------------------- // // nonlinear solver's parameters - real64 tol = 1.0e-7; - int max_iter = 20; - - // initial guess: - real64 S_int[numEqn]{}; - real64 const Pc1 = capPresIC[1][0]; - real64 const Pc2 = capPresIC[1][1]; - - real64 Pc_int = ( Pc1 + Pc2 ) / 2; - // std::cout << GEOS_FMT( " Pc_int_old = ( {:4.2e} )", Pc_int ); - // // Local newton loop: + real64 tol = 1.0e-9; + int max_iter = 50; + bool converged = 0; + bool damping = true; + // Local newton loop: // Use of the capillary pressure kernel wrapper - - StackArray< real64, 2, 2, immiscibleFlow::LAYOUT_PHASE > facePhaseVolFrac1( 1, 2 ); - StackArray< real64, 3, 2, constitutive::cappres::LAYOUT_CAPPRES > faceCapPres1( 1, 1, 2 ); - StackArray< real64, 4, 4, constitutive::cappres::LAYOUT_CAPPRES_DS > dfacePhaseVolFrac_dCapPres1( 1, 1, 2, 2 ); - StackArray< real64, 4, 4, constitutive::cappres::LAYOUT_CAPPRES_DS > dCapPres1_dfacePhaseVolFrac( 1, 1, 2, 2 ); - StackArray< real64, 2, 2, immiscibleFlow::LAYOUT_PHASE > facePhaseVolFrac2( 1, 2 ); - StackArray< real64, 3, 2, constitutive::cappres::LAYOUT_CAPPRES > faceCapPres2( 1, 1, 2 ); - StackArray< real64, 4, 4, constitutive::cappres::LAYOUT_CAPPRES_DS > dfacePhaseVolFrac_dCapPres2( 1, 1, 2, 2 ); - StackArray< real64, 4, 4, constitutive::cappres::LAYOUT_CAPPRES_DS > dCapPres2_dfacePhaseVolFrac( 1, 1, 2, 2 ); - StackArray< real64, 1, 4> JFunc1( 2 ); - StackArray< real64, 1, 4> JFunc2( 2 ); - - JFunc1[0] = jFMultiplier[0][0]; - JFunc2[0] = jFMultiplier[0][1]; - - // finding endpoints: - facePhaseVolFrac1[0][0] = 0.0; - facePhaseVolFrac1[0][1] = 1.0; - m_capPressureWrapper.compute( facePhaseVolFrac1[0], - JFunc1.toSliceConst(), - faceCapPres1[0][0], - dCapPres1_dfacePhaseVolFrac[0][0]); - real64 const Pc1_min = faceCapPres1[0][0][1]; - facePhaseVolFrac1[0][0] = 1.0; - facePhaseVolFrac1[0][1] = 0.0; - m_capPressureWrapper.compute( facePhaseVolFrac1[0], - JFunc1.toSliceConst(), - faceCapPres1[0][0], - dCapPres1_dfacePhaseVolFrac[0][0]); - real64 const Pc1_max = faceCapPres1[0][0][1]; - - facePhaseVolFrac2[0][0] = 0.0; - facePhaseVolFrac2[0][1] = 1.0; - m_capPressureWrapper.compute( facePhaseVolFrac2[0], - JFunc2.toSliceConst(), - faceCapPres2[0][0], - dCapPres2_dfacePhaseVolFrac[0][0]); - real64 const Pc2_min = faceCapPres2[0][0][1]; - facePhaseVolFrac2[0][0] = 1.0; - facePhaseVolFrac2[0][1] = 0.0; - m_capPressureWrapper.compute( facePhaseVolFrac2[0], - JFunc2.toSliceConst(), - faceCapPres2[0][0], - dCapPres2_dfacePhaseVolFrac[0][0]); - real64 const Pc2_max = faceCapPres2[0][0][1]; - - - std::cout << GEOS_FMT( " Pc_max1 = ( {:4.2e} )", Pc1_max ); - std::cout << GEOS_FMT( " Pc_min1 = ( {:4.2e} )", Pc1_min ); - std::cout << GEOS_FMT( " Pc_max2 = ( {:4.2e} )", Pc2_max ); - std::cout << GEOS_FMT( " Pc_min2 = ( {:4.2e} )", Pc2_min ); + StackArray< real64, 2, 2, immiscibleFlow::LAYOUT_PHASE > facePhaseVolFrac1( 1, 2 ); + StackArray< real64, 3, 2, constitutive::cappres::LAYOUT_CAPPRES > faceCapPres1( 1, 1, 2 ); + StackArray< real64, 4, 4, constitutive::cappres::LAYOUT_CAPPRES_DS > dfacePhaseVolFrac_dCapPres1( 1, 1, 2, 2 ); + StackArray< real64, 4, 4, constitutive::cappres::LAYOUT_CAPPRES_DS > dCapPres1_dfacePhaseVolFrac( 1, 1, 2, 2 ); + StackArray< real64, 2, 2, immiscibleFlow::LAYOUT_PHASE > facePhaseVolFrac2( 1, 2 ); + StackArray< real64, 3, 2, constitutive::cappres::LAYOUT_CAPPRES > faceCapPres2( 1, 1, 2 ); + StackArray< real64, 4, 4, constitutive::cappres::LAYOUT_CAPPRES_DS > dfacePhaseVolFrac_dCapPres2( 1, 1, 2, 2 ); + StackArray< real64, 4, 4, constitutive::cappres::LAYOUT_CAPPRES_DS > dCapPres2_dfacePhaseVolFrac( 1, 1, 2, 2 ); + StackArray< real64, 1, 2 > JFunc1( 2 ); + StackArray< real64, 1, 2 > JFunc2( 2 ); + + JFunc1[0] = jFMultiplier[0][0]; + JFunc2[0] = jFMultiplier[0][1]; + + // finding endpoints: + facePhaseVolFrac1[0][1] = 0.0; + facePhaseVolFrac1[0][0] = 1.0; + m_capPressureWrapper.compute( facePhaseVolFrac1[0], + JFunc1.toSliceConst(), + faceCapPres1[0][0], + dCapPres1_dfacePhaseVolFrac[0][0] ); + real64 const Pc1_min = faceCapPres1[0][0][0]; + facePhaseVolFrac1[0][1] = 1.0; + facePhaseVolFrac1[0][0] = 0.0; + m_capPressureWrapper.compute( facePhaseVolFrac1[0], + JFunc1.toSliceConst(), + faceCapPres1[0][0], + dCapPres1_dfacePhaseVolFrac[0][0] ); + real64 const Pc1_max = faceCapPres1[0][0][0]; + + facePhaseVolFrac2[0][1] = 0.0; + facePhaseVolFrac2[0][0] = 1.0; + m_capPressureWrapper.compute( facePhaseVolFrac2[0], + JFunc2.toSliceConst(), + faceCapPres2[0][0], + dCapPres2_dfacePhaseVolFrac[0][0] ); + real64 const Pc2_min = faceCapPres2[0][0][0]; + facePhaseVolFrac2[0][1] = 1.0; + facePhaseVolFrac2[0][0] = 0.0; + m_capPressureWrapper.compute( facePhaseVolFrac2[0], + JFunc2.toSliceConst(), + faceCapPres2[0][0], + dCapPres2_dfacePhaseVolFrac[0][0] ); + real64 const Pc2_max = faceCapPres2[0][0][0]; // Use of the relative permeability kernel wrapper - - StackArray< real64, 3, 2, constitutive::relperm::LAYOUT_RELPERM > faceTrappedVolFrac1( 1, 1, 2 ); - StackArray< real64, 3, 2, constitutive::relperm::LAYOUT_RELPERM > faceRelPerm1( 1, 1, 2 ); - StackArray< real64, 4, 4, constitutive::relperm::LAYOUT_RELPERM_DS > dfacePhaseRelPerm1_dPhaseVolFrac( 1, 1, 2, 2 ); - StackArray< real64, 3, 2, constitutive::relperm::LAYOUT_RELPERM > faceTrappedVolFrac2( 1, 1, 2 ); - StackArray< real64, 3, 2, constitutive::relperm::LAYOUT_RELPERM > faceRelPerm2( 1, 1, 2 ); - StackArray< real64, 4, 4, constitutive::relperm::LAYOUT_RELPERM_DS > dfacePhaseRelPerm2_dPhaseVolFrac( 1, 1, 2, 2 ); - - real64 halfFluxVal[numEqn][2]{}; - real64 dhalfFlux_dP[numEqn][4]{}; - real64 dhalfFlux_dS[numEqn][4]{}; - real64 dhalfFlux_duT[numEqn][2]{}; - - // While loop - int iter = 0; - - - while (iter < max_iter) { - - - - - real64 density[numEqn]{}; - real64 dDens_dP[numEqn][2]{}; - real64 viscosity[numEqn]{}; - real64 dVisc_dP[numEqn][2]{}; - - - real64 local_residual = 0; - real64 local_jacobian = 0; - - real64 Pc_int1 = fmin(Pc1_max, fmax(Pc_int, Pc1_min)); - real64 Pc_int2 = fmin(Pc2_max, fmax(Pc_int, Pc2_min)); - - // std::cout << GEOS_FMT( " Pc_int1 = ( {:4.2e} )", Pc_int1 ); - // std::cout << GEOS_FMT( " Pc_int2 = ( {:4.2e} )", Pc_int2 ); - - // Compute the inverse using pc tilde:: - faceCapPres1[0][0][1] = fmin(Pc2_max, fmax(Pc_int1, Pc2_min)); - faceCapPres2[0][0][1] = fmin(Pc1_max, fmax(Pc_int2, Pc1_min)); + StackArray< real64, 3, 2, constitutive::relperm::LAYOUT_RELPERM > faceTrappedVolFrac1( 1, 1, 2 ); + StackArray< real64, 3, 2, constitutive::relperm::LAYOUT_RELPERM > faceRelPerm1( 1, 1, 2 ); + StackArray< real64, 4, 4, constitutive::relperm::LAYOUT_RELPERM_DS > dfacePhaseRelPerm1_dPhaseVolFrac( 1, 1, 2, 2 ); + StackArray< real64, 3, 2, constitutive::relperm::LAYOUT_RELPERM > faceTrappedVolFrac2( 1, 1, 2 ); + StackArray< real64, 3, 2, constitutive::relperm::LAYOUT_RELPERM > faceRelPerm2( 1, 1, 2 ); + StackArray< real64, 4, 4, constitutive::relperm::LAYOUT_RELPERM_DS > dfacePhaseRelPerm2_dPhaseVolFrac( 1, 1, 2, 2 ); + + // clear working arrays + real64 halfFluxVal[numEqn][2]{}; + real64 dhalfFlux1_dP[numEqn][2]{}; + real64 dhalfFlux1_dS[numEqn][2]{}; + real64 dhalfFlux2_dP[numEqn][2]{}; + real64 dhalfFlux2_dS[numEqn][2]{}; + real64 dhalfFlux_duT[numEqn][2]{}; + real64 dhalfFlux_dpc[numEqn][2]{}; + // initial guess: + real64 S_int[numEqn]{}; + real64 const Pc1 = capPresIC[0][0]; + real64 const Pc2 = capPresIC[0][1]; - std::cout << GEOS_FMT( " faceCapPres1[0][0][1] = ( {:4.2e} )", faceCapPres1[0][0][1] ); - std::cout << GEOS_FMT( " faceCapPres2[0][0][1] = ( {:4.2e} )", faceCapPres2[0][0][1] ); - - std::cout << GEOS_FMT( " faceCapPres1[0][0][0] = ( {:4.2e} )", faceCapPres1[0][0][0] ); - std::cout << GEOS_FMT( " faceCapPres2[0][0][0] = ( {:4.2e} )", faceCapPres2[0][0][0] ); - - - - m_capPressureWrapper.computeInv( facePhaseVolFrac1[0], - JFunc1.toSliceConst(), - faceCapPres1[0][0], - dfacePhaseVolFrac_dCapPres1[0][0]); - - m_capPressureWrapper.computeInv( facePhaseVolFrac2[0], - JFunc2.toSliceConst(), - faceCapPres2[0][0], - dfacePhaseVolFrac_dCapPres2[0][0]); - - // compute relative permeability for both cells: - m_relPermWrapper.compute( facePhaseVolFrac1[0], - faceTrappedVolFrac1[0][0], - faceRelPerm1[0][0], - dfacePhaseRelPerm1_dPhaseVolFrac[0][0]); - - m_relPermWrapper.compute( facePhaseVolFrac2[0], - faceTrappedVolFrac2[0][0], - faceRelPerm2[0][0], - dfacePhaseRelPerm2_dPhaseVolFrac[0][0]); - - - // real64 Sw_alpha = facePhaseVolFrac1[0][1]; - // real64 Sw_beta = facePhaseVolFrac2[0][1]; - // // std::cout << GEOS_FMT( " Sw_alpha = ( {:4.2e} )", Sw_alpha ); - // // std::cout << GEOS_FMT( " Sw_beta = ( {:4.2e} )", Sw_beta ); - - // real64 Sn_alpha = facePhaseVolFrac1[0][0]; - // real64 Sn_beta = facePhaseVolFrac2[0][0]; - - - //get derivatives: - m_capPressureWrapper.compute( facePhaseVolFrac1[0], - JFunc1.toSliceConst(), - faceCapPres1[0][0], - dCapPres1_dfacePhaseVolFrac[0][0]); - - m_capPressureWrapper.compute( facePhaseVolFrac2[0], - JFunc1.toSliceConst(), - faceCapPres2[0][0], - dCapPres2_dfacePhaseVolFrac[0][0]); - - - - - - for( integer ix = 0; ix < 2; ++ix ) // for loop over each half flux - { - // loop over phases - // clear arrays: - presGrad[0] = 0; - presGrad[1] = 0; - gravHead[0] = 0; - gravHead[1] = 0; - dGravHead_dP[0][0] = 0; - dGravHead_dP[0][1] = 0; - dGravHead_dP[1][0] = 0; - dGravHead_dP[1][1] = 0; - capGrad[0] = 0; - capGrad[1] = 0; - dCapGrad_dP[0][0] = 0; - dCapGrad_dP[1][0] = 0; - dCapGrad_dP[0][1] = 0; - dCapGrad_dP[1][1] = 0; - - for( integer ip = 0; ip < m_numPhases; ++ip ) - { - // calculate quantities on primary connected cells - // density - density[ip] = m_dens[seri[ix]][sesri[ix]][sei[ix]][0][ip]; // r = rho1 || rho2 - dDens_dP[ip][ix] = m_dDens_dPres[seri[ix]][sesri[ix]][sei[ix]][0][ip][Deriv::dP]; // dr/dP = dr1/dP1 || dr2/dP - - viscosity[ip] = m_visc[seri[ix]][sesri[ix]][sei[ix]][0][ip]; // r = rho1 || rho2 - dVisc_dP[ip][ix] = m_dVisc_dPres[seri[ix]][sesri[ix]][sei[ix]][0][ip][Deriv::dP]; // dr/dP = dr1/dP1 || dr2/dP - - densMean[ip] = density[ip]; // rho = (rho1 + rho2) - dDensMean_dP[ip][0] = dDens_dP[ip][ix]; // drho/dP = { (dr1/dP1) , (dr2/dP2) } - dDensMean_dP[ip][1] = dDens_dP[ip][ix]; - - //***** calculation of flux ***** - - // compute potential difference - real64 potScale = 0.0; - real64 dPresGrad_dTrans = 0.0; - real64 dGravHead_dTrans = 0.0; - real64 dCapGrad_dTrans = 0.0; - constexpr int signPotDiff[2] = {1, -1}; - - for( integer ke = 0; ke < 2; ++ke ) - { - localIndex const er = seri[ke]; - localIndex const esr = sesri[ke]; - localIndex const ei = sei[ke]; - - real64 const pressure = m_pres[er][esr][ei]; // P = P1 || P2 - presGrad[ip] += transHat[ix] * pressure; // DPv = T (P1 - P2) - dPresGrad_dTrans += signPotDiff[ke] * pressure; // dDPv/dT = (P1 - P2) - dPresGrad_dP[ip][ke] = transHat[ix]; // dDPv/dP = { T , -T } - - real64 const gravD = transHat[ix] * gravCoefHat[ix]; // D = T g z1 || -T g z2 - real64 pot = transHat[ix] * pressure - densMean[ip] * gravD; // Phi = T P1 - rho T g z1 || -T P2 + rho T g z2 - - gravHead[ip] += densMean[ip] * gravD; // DPg = rho (T g z1 - T g z2) = T rho g (z1 - z2) - dGravHead_dTrans += signPotDiff[ke] * densMean[ip] * gravCoefHat[ix]; // dDPg/dT = rho g z1 - rho g z2 = rho g (z1 - z2) - - for( integer i = 0; i < 2; ++i ) - { - dGravHead_dP[ip][i] += dDensMean_dP[ip][i] * gravD; // dDPg/dP = {drho/dP1 * T g (z1 - z2) , drho/dP2 * T g (z1 - z2)} - } - - if( m_hasCapPressure ) // check sign convention - { - real64 capPres = m_phaseCapPressure[seri[ix]][sesri[ix]][sei[ix]][0][ip]; // Pc = Pc1 || Pc2 - - if( ke == 1 && ix == 0 ) { - capPres = faceCapPres1[0][0][ip]; - } else if ( ke == 1 && ix == 1 ) { - capPres = faceCapPres2[0][0][ip]; - } - - dCapGrad_dTrans -= signPotDiff[ke] * capPres; // dDPc/dT = (-Pc1 + Pc2) - pot -= transHat[ix] * capPres; // Phi = T P1 - rho T g z1 - T Pc1 || -T P2 + rho T g z2 + T - // Pc2 - capGrad[ip] -= transHat[ix] * capPres; // DPc = T (-Pc1 + Pc2) - } + real64 Pc_int = ( Pc1 + Pc2 ) / 2.0; - potScale = fmax( potScale, fabs( pot ) ); // maxPhi = Phi1 > Phi2 ? Phi1 : Phi2 - } + real64 Pc_min_all = fmax( Pc1_min, Pc2_min ); + real64 Pc_max_all = fmin( Pc1_max, Pc2_max ); - for( integer ke = 0; ke < 2; ++ke ) - { - dPresGrad_dP[ip][ke] += dTransHat_dP[ix] * dPresGrad_dTrans; // dDPv/dP = { T + dT/dP1 * (P1 - P2) , -T + dT/dP2 * (P1 - P2)} - dGravHead_dP[ip][ke] += dTransHat_dP[ix] * dGravHead_dTrans; // dDPg/dP = { drho/dP1 * T g (z1 - z2) + dT/dP1 * rho g (z1 - z2) , - // drho/dP2 * T g (z1 - z2) + dT/dP2 * rho g (z1 - z2) } - if( m_hasCapPressure ) + if( Pc_int < Pc_min_all || Pc_int > Pc_max_all ) { - real64 constexpr eps = 1e-8; - real64 dCapPres_dS = m_dPhaseCapPressure_dPhaseVolFrac[seri[ix]][sesri[ix]][sei[ix]][0][ip][ip]; // dPc/dS = dPc1/dS1 || - - - if( ke == 1 && ix == 0 ) { - dCapPres_dS = dCapPres1_dfacePhaseVolFrac[0][0][ip][ip]; - } else if ( ke == 1 && ix == 1 ) { - dCapPres_dS = dCapPres2_dfacePhaseVolFrac[0][0][ip][ip]; - } - // dPc2/dS2 - dCapGrad_dP[ip][ke] += dTransHat_dP[ix] * dCapGrad_dTrans; // dDPc/dP = { dT/dP1 * - // (-Pc1 + Pc2) , - // dT/dP2 * - // (-Pc1 + Pc2) } - dCapGrad_dS[ip][ke] -= transHat[ix] * dCapPres_dS; // dDPc/dS = { -T * - // dPc1/dS1 , T * - // dPc2/dS2 } + Pc_int = ( Pc_min_all + Pc_max_all ) / 2.0; } - } - - // *** upwinding *** - - // compute potential gradient - real64 potGrad = presGrad[ip] - gravHead[ip]; // DPhi = T (P1 - P2) - T rho g (z1 - z2) - if( m_hasCapPressure ) - { - potGrad += capGrad[ip]; // DPhi = T (P1 - P2) - T rho g (z1 - z2) + T (-Pc1 + Pc2) - } - - // compute upwinding tolerance - real64 constexpr upwRelTol = 1e-8; - real64 const upwAbsTol = fmax( potScale * upwRelTol, LvArray::NumericLimits< real64 >::epsilon ); // abstol = maxPhi * tol > eps ? - // maxPhi * tol : eps - - // decide mobility coefficients - smooth variation in [-upwAbsTol; upwAbsTol] - real64 const alpha = ( potGrad + upwAbsTol ) / ( 2 * upwAbsTol ); // alpha = (DPhi + abstol) / abstol / 2 - - // choose upstream cell - // if( alpha <= 0.0 || alpha >= 1.0 ) // no smoothing needed - // { - constexpr int sign[2] = {1, -1}; - - localIndex const k_up = 1 - localIndex( fmax( fmin( alpha, 1.0 ), 0.0 ) ); // 1 upwind -> k_up = 0 || 2 upwind -> k_up = 1 - - - if( k_up == 1 && ix == 0 ) { - - mobility[ip] = faceRelPerm1[0][0][ip] * density[ip] / viscosity[ip]; // M = Mupstream - dMob_dP[ip][k_up] = mobility[ip] * (dDens_dP[ip][ix] / density[ip] - dVisc_dP[ip][ix] / viscosity[ip]); // dM/dP = {dM/dP1 , 0} OR {0 , dM/dP2} - dMob_dS[ip][k_up] = dfacePhaseRelPerm1_dPhaseVolFrac[0][0][ip][ip] * density[ip] / viscosity[ip]; // dM/dS = {dM/dS1 , 0} OR {0 , dM/dS2} - } else if ( k_up == 1 && ix == 1 ) { - mobility[ip] = faceRelPerm2[0][0][ip] * density[ip] / viscosity[ip]; // M = Mupstream - dMob_dP[ip][k_up] = mobility[ip] * (dDens_dP[ip][ix] / density[ip] - dVisc_dP[ip][ix] / viscosity[ip]); // dM/dP = {dM/dP1 , 0} OR {0 , dM/dP2} - dMob_dS[ip][k_up] = dfacePhaseRelPerm2_dPhaseVolFrac[0][0][ip][ip] * density[ip] / viscosity[ip]; // dM/dS = {dM/dS1 , 0} OR {0 , dM/dS2} - } else { - mobility[ip] = m_mob[seri[k_up]][sesri[k_up]][sei[k_up]][ip]; // M = Mupstream - dMob_dP[ip][k_up] = m_dMob[seri[k_up]][sesri[k_up]][sei[k_up]][ip][Deriv::dP]; // dM/dP = {dM/dP1 , 0} OR {0 , dM/dP2} - dMob_dS[ip][k_up] = m_dMob[seri[k_up]][sesri[k_up]][sei[k_up]][ip][Deriv::dS]; // dM/dS = {dM/dS1 , 0} OR {0 , dM/dS2} - } - - - // } - // else // perform smoothing - // { - // real64 const mobWeights[2] = { alpha, 1.0 - alpha }; - // for( integer ke = 0; ke < 2; ++ke ) - // { - - // mobility[ip] += mobWeights[ke] * m_mob[seri[ke]][sesri[ke]][sei[ke]][ip]; // M = alpha * M1 + (1 - alpha) * M2 - // density2[ip] += mobWeights[ke] * m_dens[seri[ke]][sesri[ke]][sei[ke]][0][ip]; // r = rho1 || rho2 - // dDens_dP2[ip][ke] = mobWeights[ke] * m_dDens_dPres[seri[ke]][sesri[ke]][sei[ke]][0][ip][Deriv::dP]; // dr/dP = dr1/dP1 || - // // dr2/dP - // dMob_dP[ip][ke] = mobWeights[ke] * m_dMob[seri[ke]][sesri[ke]][sei[ke]][ip][Deriv::dP]; // dM/dP = {alpha * dM1/dP1 , (1 - - // // alpha) * dM2/dP2} - // dMob_dS[ip][ke] = mobWeights[ke] * m_dMob[seri[ke]][sesri[ke]][sei[ke]][ip][Deriv::dS]; // dM/dP = {alpha * dM1/dS1 , (1 - - // // alpha) * dM2/dS2} - // } - // } - real64 constexpr eps = 0.5e-8; - total_mobility += mobility[ip] + eps; - potGrad_ip[ip] = potGrad; - alpha_ip[ip] = alpha; - - } // loop over phases - /// Three Forces Flux Contribution: 1- Viscous 2- Gravitational 3- Capillary - constexpr int sign[2] = {1, -1}; - // loop over phases - for( integer ip = 0; ip < m_numPhases; ++ip ) - { - // 1- Viscous: pressure gradient depends on all points in the stencil - for( integer ke = 0; ke < 2; ++ke ) - { - halfFluxVal[ip][ix] = sign[0] * mobility[ip] / total_mobility * uT; - dhalfFlux_dP[ip][ix + ke] = sign[0] * sign[ip] * (dMob_dP[0][ke] * mobility[0] - dMob_dP[1][ke] * mobility[1]) / (total_mobility * total_mobility) * uT; // dF/dP = { T + dT/dP1 * (P1 - P2) , - // -T + dT/dP2 * (P1 - P2) } - dhalfFlux_dS[ip][ix + ke] = sign[0] * sign[ip] * (dMob_dS[0][ke] * mobility[0] - dMob_dS[1][ke] * mobility[1]) / (total_mobility * total_mobility) * uT; + real64 same_Pc_int = Pc_int; + + // GEOS_UNUSED_VAR(gravCoef2[0]); + // GEOS_UNUSED_VAR(gravCoef2[1]); + + // Pc_int = fmin( Pc_max_all, fmax( Pc_int, Pc_min_all )); + // m_interfaceConstitutivePairs[0][0] = std::make_tuple( relPerm, capPressure, fluid ); +// m_interfaceConstitutivePairs[0][1] = std::make_tuple( relPerm, capPressure, fluid ); + + stdVector< real64 > JFMultipliers = {jFMultiplier[0][0], jFMultiplier[0][1]}; + stdVector< real64 > trappedSats1 = {0.0, 0.0}; + stdVector< real64 > trappedSats2 = {0.0, 0.0}; + stdVector< real64 > transHats = {transHat[0], transHat[1]}; + stdVector< real64 > dTransHats_dP = {dTransHat_dP[0], dTransHat_dP[1]}; + stdVector< real64 > gravCoefHats = {gravCoefHat[0], gravCoefHat[1]}; + stdVector< real64 > gravCoefs = {gravCoef2[0], gravCoef2[1]}; + stdVector< real64 > cellCenterDuTdS = {duT_dP[0], duT_dP[1], duT_dS[0], duT_dS[1]}; + stdVector< real64 > cellCenterDens = {density2[0], density2[1]}; + stdVector< real64 > cellCenterDens_dP = {dDens_dP2[0][0], dDens_dP2[0][1], dDens_dP2[1][0], dDens_dP2[1][1]}; + std::vector< RelativePermeabilityBase * > relPerms = {std::get< 0 >( m_interfaceConstitutivePairs_temp ), std::get< 0 >( m_interfaceConstitutivePairs_temp )}; + std::vector< CapillaryPressureBase * > capPressures = {std::get< 1 >( m_interfaceConstitutivePairs_temp ), std::get< 1 >( m_interfaceConstitutivePairs_temp )}; + std::vector< TwoPhaseImmiscibleFluid * > fluids = {std::get< 2 >( m_interfaceConstitutivePairs_temp ), std::get< 2 >( m_interfaceConstitutivePairs_temp )}; + + stdVector< real64 > phi = {halfFluxVal[0][0], halfFluxVal[0][1]}; + stdVector< real64 > grad_phi_P = {0.0, 0.0, 0.0, 0.0}; + stdVector< real64 > grad_phi_S = {0.0, 0.0, 0.0, 0.0}; + + local_solver( uT, saturations, pressures, JFMultipliers, trappedSats1, trappedSats2, transHats, dTransHats_dP, gravCoefHats, gravCoefs, + cellCenterDuTdS, cellCenterDens, cellCenterDens_dP, relPerms, capPressures, fluids, phi, grad_phi_P, grad_phi_S, converged ); - } - // 2- Gravitational: gravitational head depends only on the two cells connected (same as mean density) - for( integer ke = 0; ke < 2; ++ke ) - { - halfFluxVal[ip][ix] -= mobility[0] * mobility[1] / total_mobility * gravHead[ip]; - - dhalfFlux_dP[ip][ix + ke] -= (dMob_dP[0][ke] * mobility[0] * mobility[0]+ dMob_dP[1][ke] * mobility[1] * mobility[1]) / (total_mobility * total_mobility) * gravHead[ip] + mobility[0] * mobility[1] / total_mobility * dGravHead_dP[ip][ke]; // dF/dP = { T + dT/dP1 * (P1 - P2) , - // -T + dT/dP2 * (P1 - P2) } - dhalfFlux_dS[ip][ix + ke] -= (dMob_dS[0][ke] * mobility[0] * mobility[0]+ dMob_dS[1][ke] * mobility[1] * mobility[1]) / (total_mobility * total_mobility) * gravHead[ip]; - } - - // 3- Capillary: capillary pressure contribution - - if( m_hasCapPressure ) - { - for( integer ke = 0; ke < 2; ++ke ) + fluxVal[0] = phi[0]; + fluxVal[1] = phi[1]; + dFlux_dP[0][0] = grad_phi_P[0]; + dFlux_dP[0][1] = grad_phi_P[1]; + dFlux_dP[1][0] = grad_phi_P[2]; + dFlux_dP[1][1] = grad_phi_P[3]; + dFlux_dS[0][0] = grad_phi_S[0]; + dFlux_dS[0][1] = grad_phi_S[1]; + dFlux_dS[1][0] = grad_phi_S[2]; + dFlux_dS[1][1] = grad_phi_S[3]; + + // Global residual and jacobian update: + for( integer ip = 0; ip < m_numPhases; ++ip ) { - halfFluxVal[ip][ix] -= sign[ip] * mobility[0] * mobility[1] / total_mobility * capGrad[1]; + // populate local flux vector and derivatives + stack.localFlux[k[0]*numEqn + ip] += m_dt * fluxVal[ip]; + stack.localFlux[k[1]*numEqn + ip] -= m_dt * fluxVal[ip]; - dhalfFlux_dP[ip][ix + ke] -= sign[ip] * (dMob_dP[0][ke] * mobility[0] * mobility[0]+ dMob_dP[1][ke] * mobility[1] * mobility[1]) / (total_mobility * total_mobility) * capGrad[1] + mobility[0] * mobility[1] / total_mobility * dCapGrad_dP[ip][ke]; // dF/dP = { T + dT/dP1 * (P1 - P2) , - // -T + dT/dP2 * (P1 - P2) } - dhalfFlux_dS[ip][ix + ke] -= sign[ip] * (dMob_dP[0][ke] * mobility[0] * mobility[0]+ dMob_dP[1][ke] * mobility[1] * mobility[1]) / (total_mobility * total_mobility) * capGrad[1] + mobility[0] * mobility[1] / total_mobility * dCapGrad_dS[ip][ke]; - } - } - - // does - - } // loop over phases - - } // loop over half fluxes - - local_jacobian = dhalfFlux_dS[1][1]*dfacePhaseVolFrac_dCapPres1[0][0][1][1] + dhalfFlux_dS[1][3]*dfacePhaseVolFrac_dCapPres2[0][0][1][1]; - local_residual = halfFluxVal[1][0] + halfFluxVal[1][1]; - - // // Write data to the file - // outFile << local_jacobian; - // outFile << ","; - // outFile << local_residual; - // outFile << ","; - // outFile << halfFluxVal[1][0]; - // outFile << ","; - // outFile << halfFluxVal[1][1]; - // outFile << ","; - // outFile << Pc_int; - // outFile << ","; - // outFile << iter; - // outFile << std::endl; - - if (std::fabs(local_jacobian) < 1e-16) { - std::cout << "Derivative is too small" << std::endl; - break; - } - - //std::cout << GEOS_FMT( " phase_mass = ( {:4.2e} )", phase_mass ); - real64 deltaPc = local_residual/local_jacobian; - - std::cout << GEOS_FMT( " local_R = ( {:4.2e} )", local_residual ); - std::cout << GEOS_FMT( " deltaPc = ( {:4.2e} )", deltaPc ); - - Pc_int -= deltaPc; - - - // Check convergence - if (std::fabs(local_residual) < tol) { - break; // Converged - } - - iter++; - } // while loop + for( integer ke = 0; ke < 2; ++ke ) + { + // pressure + localIndex const localDofIndexPres = k[ke] * numDof; + stack.localFluxJacobian[k[0]*numEqn + ip][localDofIndexPres] += m_dt * dFlux_dP[ip][ke]; + stack.localFluxJacobian[k[1]*numEqn + ip][localDofIndexPres] -= m_dt * dFlux_dP[ip][ke]; + + // saturation + localIndex const localDofIndexSat = k[ke] * numDof + 1; + stack.localFluxJacobian[k[0]*numEqn + ip][localDofIndexSat] += m_dt * dFlux_dS[ip][ke]; + stack.localFluxJacobian[k[1]*numEqn + ip][localDofIndexSat] -= m_dt * dFlux_dS[ip][ke]; + } - // // Close the file after writing - // outFile.close(); - for( integer ip = 0; ip < m_numPhases; ++ip ) - { - // populate local flux vector and derivatives - stack.localFlux[k[0]*numEqn + ip] += m_dt * (halfFluxVal[ip][0] + halfFluxVal[ip][1]); - stack.localFlux[k[1]*numEqn + ip] -= m_dt * (halfFluxVal[ip][0] + halfFluxVal[ip][1]); + // Customize the kernel with this lambda + kernelOp( k, seri, sesri, sei, connectionIndex, alpha_ip[ip], mobility, potGrad_ip[ip], fluxVal, dFlux_dP, dFlux_dS ); - for( integer ke = 0; ke < 2; ++ke ) - { - // pressure - localIndex const localDofIndexPres = k[ke] * numDof; - stack.localFluxJacobian[k[0]*numEqn + ip][localDofIndexPres] += m_dt * dhalfFlux_dP[ip][ke]; - stack.localFluxJacobian[k[1]*numEqn + ip][localDofIndexPres] -= m_dt * dhalfFlux_dP[ip][ke]; - - // saturation (hard-coded for 2-phase currently) - localIndex const localDofIndexSat = k[ke] * numDof + 1; - stack.localFluxJacobian[k[0]*numEqn + ip][localDofIndexSat] += m_dt * dhalfFlux_dS[ip][ke]; - stack.localFluxJacobian[k[1]*numEqn + ip][localDofIndexSat] -= m_dt * dhalfFlux_dS[ip][ke]; - } + } // loop over phases + } // end of else for interface conditions - // Customize the kernel with this lambda - kernelOp( k, seri, sesri, sei, connectionIndex, alpha_ip[ip], mobility, potGrad_ip[ip], fluxVal, dFlux_dP, dFlux_dS ); // Not sure what this - - } // loop over phases - } // end of else for interface conditions connectionIndex++; } } // loop over connection elements } + protected: /// Reference to the capillary pressure wrapper CAPPRESWRAPPER const m_capPressureWrapper; RELPERMWRAPPER const m_relPermWrapper; + string_array const m_interfaceFaceSetNames; + stdVector< std::array< std::tuple< constitutive::RelativePermeabilityBase *, + constitutive::CapillaryPressureBase *, + constitutive::TwoPhaseImmiscibleFluid * >, 2 > > const m_interfaceConstitutivePairs; + unordered_map< localIndex, localIndex > const m_interfaceRegionByConnector; + std::tuple< constitutive::RelativePermeabilityBase *, + constitutive::CapillaryPressureBase *, + constitutive::TwoPhaseImmiscibleFluid * > const m_interfaceConstitutivePairs_temp; + }; + /****************************************** */ /** @@ -1752,7 +2758,7 @@ class FluxComputeKernelFactory * @param[inout] localMatrix the local CRS matrix * @param[inout] localRhs the local right-hand side vector */ - template< typename POLICY, typename STENCILWRAPPER, typename CAPPRESWRAPPER, typename RELPERMWRAPPER > + template< typename POLICY, typename STENCILWRAPPER, typename CAPPRESWRAPPER, typename RELPERMWRAPPER > static void createAndLaunch( integer const numPhases, globalIndex const rankOffset, @@ -1765,6 +2771,14 @@ class FluxComputeKernelFactory STENCILWRAPPER const & stencilWrapper, CAPPRESWRAPPER const & capPresWrapper, RELPERMWRAPPER const & relPermWrapper, + string_array const & interfaceFaceSetNames, + stdVector< std::array< std::tuple< constitutive::RelativePermeabilityBase *, + constitutive::CapillaryPressureBase *, + constitutive::TwoPhaseImmiscibleFluid * >, 2 > > const & interfaceConstitutivePairs, + unordered_map< localIndex, localIndex > const & interfaceRegionByConnector, + std::tuple< constitutive::RelativePermeabilityBase *, + constitutive::CapillaryPressureBase *, + constitutive::TwoPhaseImmiscibleFluid * > const & interfaceConstitutivePairs_temp, ElementSubRegionBase const & subRegion, real64 const & dt, CRSMatrixView< real64, globalIndex const > const & localMatrix, @@ -1773,12 +2787,11 @@ class FluxComputeKernelFactory integer constexpr NUM_EQN = 2; integer constexpr NUM_DOF = 2; localIndex const domainSize = subRegion.size(); - // GEOS_UNUSED_PARAM( domainSize ); ElementRegionManager::ElementViewAccessor< arrayView1d< globalIndex const > > dofNumberAccessor = elemManager.constructArrayViewAccessor< globalIndex, 1 >( dofKey ); dofNumberAccessor.setName( solverName + "/accessors/" + dofKey ); - using kernelType = FluxComputeInterfaceConditionKernel< NUM_EQN, NUM_DOF, STENCILWRAPPER, CAPPRESWRAPPER, RELPERMWRAPPER >; + using kernelType = FluxComputeInterfaceConditionKernel< NUM_EQN, NUM_DOF, STENCILWRAPPER, CAPPRESWRAPPER, RELPERMWRAPPER >; typename kernelType::ImmiscibleMultiphaseFlowAccessors flowAccessors( elemManager, solverName ); typename kernelType::MultiphaseFluidAccessors fluidAccessors( elemManager, solverName ); typename kernelType::CapPressureAccessors capPressureAccessors( elemManager, solverName ); @@ -1787,8 +2800,8 @@ class FluxComputeKernelFactory kernelType kernel( numPhases, rankOffset, stencilWrapper, capPresWrapper, relPermWrapper, dofNumberAccessor, flowAccessors, fluidAccessors, capPressureAccessors, permAccessors, dt, localMatrix, localRhs, hasCapPressure, useTotalMassEquation, - checkPhasePresenceInGravity, domainSize); - kernelType::template launch< POLICY >( stencilWrapper.size() , kernel ); + checkPhasePresenceInGravity, interfaceFaceSetNames, interfaceConstitutivePairs, interfaceRegionByConnector, interfaceConstitutivePairs_temp, domainSize ); + kernelType::template launch< POLICY >( stencilWrapper.size(), kernel ); } }; @@ -1797,7 +2810,7 @@ class FluxComputeKernelFactory enum class KernelFlags { - TotalMassEquation = 1 << 0, // 1 + TotalMassEquation = 1 << 0, // 1 /// Add more flags like that if needed: // Flag2 = 1 << 1, // 2 @@ -2423,7 +3436,7 @@ class ResidualNormKernelFactory { ResidualNormKernel::launchLinf< POLICY >( subRegion.size(), kernel, residualNorm ); } - else // L2 norm + else // L2 norm { ResidualNormKernel::launchL2< POLICY >( subRegion.size(), kernel, residualNorm, residualNormalizer ); } @@ -2433,9 +3446,9 @@ class ResidualNormKernelFactory -} // namespace immiscible multiphasekernels +} // namespace immiscible multiphasekernels -} // namespace geos +} // namespace geos -#endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_MULTIPHASEKERNELS_HPP + #endif //GEOS_PHYSICSSOLVERS_FLUIDFLOW_MULTIPHASEKERNELS_HPP From 7927b3780d2b6191ac6917a99bd0025144e1fe40 Mon Sep 17 00:00:00 2001 From: Ammara-14 Date: Wed, 12 Nov 2025 14:02:43 -0800 Subject: [PATCH 094/104] updated --- .../JFunctionCapillaryPressure.cpp | 2 +- .../wellsTests/CMakeLists.txt | 17 - .../fluidFlow/ImmiscibleMultiphaseFlow.cpp | 2966 +++++++++-------- .../ImmiscibleMultiphaseKernels.hpp | 237 +- 4 files changed, 1690 insertions(+), 1532 deletions(-) diff --git a/src/coreComponents/constitutive/capillaryPressure/JFunctionCapillaryPressure.cpp b/src/coreComponents/constitutive/capillaryPressure/JFunctionCapillaryPressure.cpp index 738efb7b77f..5e7b9511cfa 100644 --- a/src/coreComponents/constitutive/capillaryPressure/JFunctionCapillaryPressure.cpp +++ b/src/coreComponents/constitutive/capillaryPressure/JFunctionCapillaryPressure.cpp @@ -115,7 +115,7 @@ JFunctionCapillaryPressure::JFunctionCapillaryPressure( std::string const & name toString( PermeabilityDirection::Y ) + " - only use the permeability in the y direction,\n" + toString( PermeabilityDirection::Z ) + " - only use the permeability in the z direction." ); - registerField( fields::cappres::jFuncMultiplier{}, &m_jFuncMultiplier ); + registerField< fields::cappres::jFuncMultiplier >( &m_jFuncMultiplier ); registerWrapper( viewKeyStruct::jFunctionWrappersString(), &m_jFuncKernelWrappers ). setSizedFromParent( 0 ). diff --git a/src/coreComponents/integrationTests/wellsTests/CMakeLists.txt b/src/coreComponents/integrationTests/wellsTests/CMakeLists.txt index 2a6063f14c2..5a30f2fe376 100644 --- a/src/coreComponents/integrationTests/wellsTests/CMakeLists.txt +++ b/src/coreComponents/integrationTests/wellsTests/CMakeLists.txt @@ -1,23 +1,6 @@ # Specify list of tests set( gtest_geosx_tests -<<<<<<< HEAD:src/coreComponents/unitTests/fluidFlowTests/CMakeLists.txt - testSinglePhaseMobilityKernel.cpp - testThermalCompMultiphaseFlow.cpp - testThermalSinglePhaseFlow.cpp - testFlowStatistics.cpp - testTransmissibility.cpp - testImmiscibleMultiphaseFlow.cpp - testImmiscibleInterfaceConditions.cpp ) - -if( ENABLE_PVTPackage ) - list( APPEND gtest_geosx_tests - testCompMultiphaseFlow.cpp - testCompMultiphaseFlowHybrid.cpp - testReactiveCompositionalMultiphaseOBL.cpp ) -endif() -======= testReservoirSinglePhaseMSWells.cpp ) ->>>>>>> develop:src/coreComponents/integrationTests/wellsTests/CMakeLists.txt set( tplDependencyList ${parallelDeps} gtest ) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index 00162bb1129..d6b73163285 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -17,1394 +17,1632 @@ * @file ImmiscibleMultiphaseFlow.cpp */ -#include "ImmiscibleMultiphaseFlow.hpp" - -#include "FlowSolverBaseFields.hpp" -#include "physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp" -#include "physicsSolvers/PhysicsSolverBaseKernels.hpp" -#include "physicsSolvers/fluidFlow/CompositionalMultiphaseUtilities.hpp" -#include "physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp" -#include "physicsSolvers/fluidFlow/kernels/compositional/RelativePermeabilityUpdateKernel.hpp" -#include "physicsSolvers/fluidFlow/kernels/compositional/CapillaryPressureUpdateKernel.hpp" -#include "constitutive/capillaryPressure/CapillaryPressureSelector.hpp" -#include "constitutive/relativePermeability/RelativePermeabilitySelector.hpp" - -#include "fieldSpecification/EquilibriumInitialCondition.hpp" -#include "fieldSpecification/SourceFluxBoundaryCondition.hpp" -#include "physicsSolvers/fluidFlow/SourceFluxStatistics.hpp" -#include "physicsSolvers/LogLevelsInfo.hpp" - -#include "constitutive/ConstitutivePassThru.hpp" -#include "constitutive/fluid/twophaseimmisciblefluid/TwoPhaseImmiscibleFluid.hpp" - -#include - -#if defined( __INTEL_COMPILER ) -#pragma GCC optimize "O0" -#endif - -namespace geos -{ - -using namespace dataRepository; -using namespace constitutive; -using namespace fields::immiscibleMultiphaseFlow; -using namespace immiscibleMultiphaseKernels; - - -ImmiscibleMultiphaseFlow::ImmiscibleMultiphaseFlow( const string & name, - Group * const parent ) - : - FlowSolverBase( name, parent ), - m_numPhases( 2 ), - m_hasCapPressure( false ), - m_useTotalMassEquation ( 1 ) -{ - this->registerWrapper( viewKeyStruct::inputTemperatureString(), &m_inputTemperature ). - setInputFlag( InputFlags::REQUIRED ). - setDescription( "Temperature" ); - - this->registerWrapper( viewKeyStruct::useTotalMassEquationString(), &m_useTotalMassEquation ). - setSizedFromParent( 0 ). - setInputFlag( InputFlags::OPTIONAL ). - setApplyDefaultValue( 1 ). - setDescription( "Flag indicating whether total mass equation is used" ); - - this->registerWrapper( viewKeyStruct::gravityDensitySchemeString(), &m_gravityDensityScheme ). - setSizedFromParent( 0 ). - setInputFlag( InputFlags::OPTIONAL ). - setApplyDefaultValue( GravityDensityScheme::ArithmeticAverage ). - setDescription( "Scheme for density treatment in gravity" ); - - this->registerWrapper( viewKeyStruct::solutionChangeScalingFactorString(), &m_solutionChangeScalingFactor ). - setSizedFromParent( 0 ). - setInputFlag( InputFlags::OPTIONAL ). - setApplyDefaultValue( 0.5 ). - setDescription( "Damping factor for solution change targets" ); - this->registerWrapper( viewKeyStruct::targetRelativePresChangeString(), &m_targetRelativePresChange ). - setSizedFromParent( 0 ). - setInputFlag( InputFlags::OPTIONAL ). - setApplyDefaultValue( 0.2 ). - setDescription( "Target (relative) change in pressure in a time step (expected value between 0 and 1)" ); - this->registerWrapper( viewKeyStruct::targetPhaseVolFracChangeString(), &m_targetPhaseVolFracChange ). - setSizedFromParent( 0 ). - setInputFlag( InputFlags::OPTIONAL ). - setApplyDefaultValue( 0.2 ). - setDescription( "Target (absolute) change in phase volume fraction in a time step" ); -} - -void ImmiscibleMultiphaseFlow::postInputInitialization() -{ - FlowSolverBase::postInputInitialization(); -} - -void ImmiscibleMultiphaseFlow::registerDataOnMesh( Group & meshBodies ) + #include "ImmiscibleMultiphaseFlow.hpp" + + #include "FlowSolverBaseFields.hpp" + #include "physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlowFields.hpp" + #include "physicsSolvers/PhysicsSolverBaseKernels.hpp" + #include "physicsSolvers/fluidFlow/CompositionalMultiphaseUtilities.hpp" + #include "physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp" + #include "physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/CapillaryPressureUpdateKernel.hpp" + #include "physicsSolvers/fluidFlow/kernels/compositional/ThermalAccumulationKernel.hpp" + #include "physicsSolvers/fluidFlow/kernels/compositional/RelativePermeabilityUpdateKernel.hpp" + #include "constitutive/ConstitutiveManager.hpp" + #include "constitutive/capillaryPressure/CapillaryPressureFields.hpp" + #include "constitutive/capillaryPressure/CapillaryPressureSelector.hpp" + #include "constitutive/relativePermeability/RelativePermeabilitySelector.hpp" + + #include "fieldSpecification/EquilibriumInitialCondition.hpp" + #include "fieldSpecification/SourceFluxBoundaryCondition.hpp" + #include "physicsSolvers/fluidFlow/SourceFluxStatistics.hpp" + #include "physicsSolvers/LogLevelsInfo.hpp" + + #include "constitutive/ConstitutivePassThru.hpp" + #include "constitutive/fluid/twophaseimmisciblefluid/TwoPhaseImmiscibleFluid.hpp" + + #include + + #if defined( __INTEL_COMPILER ) + #pragma GCC optimize "O0" + #endif + + namespace geos + { + + using namespace dataRepository; + using namespace constitutive; + using namespace fields::immiscibleMultiphaseFlow; + using namespace immiscibleMultiphaseKernels; + + + ImmiscibleMultiphaseFlow::ImmiscibleMultiphaseFlow( const string & name, + Group * const parent ) + : + FlowSolverBase( name, parent ), + m_numPhases( 2 ), + m_hasCapPressure( false ), + m_useTotalMassEquation ( 1 ) + { + this->registerWrapper( viewKeyStruct::inputTemperatureString(), &m_inputTemperature ). + setInputFlag( InputFlags::REQUIRED ). + setDescription( "Temperature" ); + + this->registerWrapper( viewKeyStruct::useTotalMassEquationString(), &m_useTotalMassEquation ). + setSizedFromParent( 0 ). + setInputFlag( InputFlags::OPTIONAL ). + setApplyDefaultValue( 1 ). + setDescription( "Flag indicating whether total mass equation is used" ); + + this->registerWrapper( viewKeyStruct::gravityDensitySchemeString(), &m_gravityDensityScheme ). + setSizedFromParent( 0 ). + setInputFlag( InputFlags::OPTIONAL ). + setApplyDefaultValue( GravityDensityScheme::ArithmeticAverage ). + setDescription( "Scheme for density treatment in gravity" ); + + this->registerWrapper( viewKeyStruct::solutionChangeScalingFactorString(), &m_solutionChangeScalingFactor ). + setSizedFromParent( 0 ). + setInputFlag( InputFlags::OPTIONAL ). + setApplyDefaultValue( 0.5 ). + setDescription( "Damping factor for solution change targets" ); + this->registerWrapper( viewKeyStruct::targetRelativePresChangeString(), &m_targetRelativePresChange ). + setSizedFromParent( 0 ). + setInputFlag( InputFlags::OPTIONAL ). + setApplyDefaultValue( 0.2 ). + setDescription( "Target (relative) change in pressure in a time step (expected value between 0 and 1)" ); + this->registerWrapper( viewKeyStruct::targetPhaseVolFracChangeString(), &m_targetPhaseVolFracChange ). + setSizedFromParent( 0 ). + setInputFlag( InputFlags::OPTIONAL ). + setApplyDefaultValue( 0.2 ). + setDescription( "Target (absolute) change in phase volume fraction in a time step" ); + + this->registerWrapper( viewKeyStruct::interfaceFaceSetNamesString(), + &m_interfaceFaceSetNames ). + setInputFlag( InputFlags::OPTIONAL ). + setDescription( "Names of the interface face sets" ); + } + + void ImmiscibleMultiphaseFlow::postInputInitialization() + { + FlowSolverBase::postInputInitialization(); + } + + void ImmiscibleMultiphaseFlow::registerDataOnMesh( Group & meshBodies ) + { + FlowSolverBase::registerDataOnMesh( meshBodies ); + + // 0. Find a "reference" fluid model name (at this point, models are already attached to subregions) + forDiscretizationOnMeshTargets( meshBodies, [&]( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + mesh.getElemManager().forElementSubRegions( regionNames, + [&]( localIndex const, + ElementSubRegionBase & subRegion ) + { + // If at least one region has a capillary pressure model, consider it enabled for all + string const capPresName = getConstitutiveName< CapillaryPressureBase >( subRegion ); + if( !capPresName.empty() ) + { + m_hasCapPressure = true; + } + } ); + } ); + + m_numDofPerCell = m_numPhases; + + // 2. Register and resize all fields as necessary + forDiscretizationOnMeshTargets( meshBodies, [&]( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + mesh.getElemManager().forElementSubRegions( regionNames, + [&]( localIndex const, + ElementSubRegionBase & subRegion ) + { + if( m_hasCapPressure ) + { + subRegion.registerWrapper< string >( viewKeyStruct::capPressureNamesString() ). + setPlotLevel( PlotLevel::NOPLOT ). + setRestartFlags( RestartFlags::NO_WRITE ). + setSizedFromParent( 0 ). + setDescription( "Name of the capillary pressure constitutive model to use" ). + reference(); + + string & capPresName = subRegion.getReference< string >( viewKeyStruct::capPressureNamesString() ); + capPresName = getConstitutiveName< CapillaryPressureBase >( subRegion ); + GEOS_THROW_IF( capPresName.empty(), + GEOS_FMT( "{}: Capillary pressure model not found on subregion {}", + getDataContext(), subRegion.getDataContext() ), + InputError ); + } + + // The resizing of the arrays needs to happen here, before the call to initializePreSubGroups, + // to make sure that the dimensions are properly set before the timeHistoryOutput starts its initialization. + subRegion.registerField< phaseVolumeFraction >( getName() ). + reference().resizeDimension< 1 >( m_numPhases ); + + subRegion.registerField< phaseVolumeFraction_n >( getName() ). + reference().resizeDimension< 1 >( m_numPhases ); + + subRegion.registerField< bcPhaseVolumeFraction >( getName() ). + reference().resizeDimension< 1 >( m_numPhases ); + + subRegion.registerField< phaseMass >( getName() ). + reference().resizeDimension< 1 >( m_numPhases ); + + subRegion.registerField< phaseMass_n >( getName() ). + reference().resizeDimension< 1 >( m_numPhases ); + + subRegion.registerField< phaseMobility >( getName() ). + reference().resizeDimension< 1 >( m_numPhases ); + + subRegion.registerField< dPhaseMobility >( getName() ). + reference().resizeDimension< 1, 2 >( m_numPhases, m_numPhases ); // dP, dS + + } ); + + } ); + } + + void ImmiscibleMultiphaseFlow::setConstitutiveNames( ElementSubRegionBase & subRegion ) const + { + setConstitutiveName< TwoPhaseImmiscibleFluid >( subRegion, viewKeyStruct::fluidNamesString(), "two phase immiscible fluid" ); + + setConstitutiveName< RelativePermeabilityBase >( subRegion, viewKeyStruct::relPermNamesString(), "relative permeability" ); + } + + void ImmiscibleMultiphaseFlow::initializePreSubGroups() + { + m_linearSolverParameters.get().mgr.strategy = LinearSolverParameters::MGR::StrategyType::immiscibleMultiphaseFVM; + + FlowSolverBase::initializePreSubGroups(); + + DomainPartition & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" ); + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + mesh.getElemManager().forElementSubRegions( regionNames, + [&]( localIndex const, + ElementSubRegionBase & subRegion ) + { + arrayView1d< real64 > const temp = subRegion.getField< fields::flow::temperature >(); + temp.setValues< parallelHostPolicy >( m_inputTemperature ); + } ); + } ); + + // ***** Create FaceElements ***** + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & meshLevel, + string_array const & regionNames ) + { + + FaceManager const & faceManager = meshLevel.getFaceManager(); + Group const & faceSetGroup = faceManager.sets(); + ElementRegionManager & elemManager = meshLevel.getElemManager(); + m_interfaceConstitutivePairs.resize( m_interfaceFaceSetNames.size() ); + + // this is the FaceElement Level + for( size_t surfaceRegionIndex=0; surfaceRegionIndex < m_interfaceFaceSetNames.size(); ++surfaceRegionIndex ) + { + string const & faceSetName = m_interfaceFaceSetNames[surfaceRegionIndex]; + SortedArrayView< localIndex const > const & faceSet = faceSetGroup.getReference< SortedArray< localIndex > >( faceSetName ); + SurfaceElementRegion & faceRegion = elemManager.getRegion< SurfaceElementRegion >( faceSetName ); + + for( localIndex const faceIndex : faceSet ) + { + localIndex const faceIndices[2] = { faceIndex, faceIndex }; + faceRegion.addToSurfaceMesh( &faceManager, faceIndices ); + } + + FaceElementSubRegion const & faceSubRegion = faceRegion.getUniqueSubRegion< FaceElementSubRegion >(); + FixedToManyElementRelation const & faceElementsToCells = faceSubRegion.getToCellRelation(); + + std::function< std::tuple< CellElementSubRegion *, CellElementSubRegion * >(localIndex) > getSubregions = [&]( localIndex surfaceSubRegionIndex ) -> std::tuple< CellElementSubRegion *, + CellElementSubRegion * > + { + + int regionIdx0 = faceElementsToCells.m_toElementRegion[surfaceSubRegionIndex][0]; + int regionIdx1 = faceElementsToCells.m_toElementRegion[surfaceSubRegionIndex][1]; + int subRegionIdx0 = faceElementsToCells.m_toElementSubRegion[surfaceSubRegionIndex][0]; + int subRegionIdx1 = faceElementsToCells.m_toElementSubRegion[surfaceSubRegionIndex][1]; + + CellElementRegion & region0 = elemManager.getRegion< CellElementRegion >( regionIdx0 ); + CellElementRegion & region1 = elemManager.getRegion< CellElementRegion >( regionIdx1 ); + + CellElementSubRegion * subRegion0 = ®ion0.getSubRegion< CellElementSubRegion >( subRegionIdx0 ); + CellElementSubRegion * subRegion1 = ®ion1.getSubRegion< CellElementSubRegion >( subRegionIdx1 ); + return std::make_tuple( subRegion0, subRegion1 ); + }; + + // std::tuple< CellElementSubRegion *, CellElementSubRegion * > subRegionPair = getSubregions( surfaceRegionIndex ); + // CellElementSubRegion * subRegion0 = std::get< 0 >( subRegionPair ); + // CellElementSubRegion * subRegion1 = std::get< 1 >( subRegionPair ); + + // // get constitutives by type and name: relPerms, capPressures, Fluids (three pointers) + // std::string & relPermName0 = subRegion0->getReference< std::string >( viewKeyStruct::relPermNamesString()); + // std::string & relPermName1 = subRegion1->getReference< std::string >( viewKeyStruct::relPermNamesString()); + // RelativePermeabilityBase * relPerm0 = &getConstitutiveModel< RelativePermeabilityBase >( *subRegion0, relPermName0 ); + // RelativePermeabilityBase * relPerm1 = &getConstitutiveModel< RelativePermeabilityBase >( *subRegion1, relPermName1 ); + + // std::string & cappresName0 = subRegion0->getReference< std::string >( viewKeyStruct::capPressureNamesString()); + // std::string & cappresName1 = subRegion1->getReference< std::string >( viewKeyStruct::capPressureNamesString()); + // CapillaryPressureBase * capPressure0 = &getConstitutiveModel< CapillaryPressureBase >( *subRegion0, cappresName0 ); + // CapillaryPressureBase * capPressure1 = &getConstitutiveModel< CapillaryPressureBase >( *subRegion1, cappresName1 ); + + // std::string & fluidName0 = subRegion0->getReference< std::string >( viewKeyStruct::fluidNamesString() ); + // std::string & fluidName1 = subRegion1->getReference< std::string >( viewKeyStruct::fluidNamesString() ); + + // TwoPhaseImmiscibleFluid * fluid0 = &getConstitutiveModel< TwoPhaseImmiscibleFluid >( *subRegion0, fluidName0 ); + // TwoPhaseImmiscibleFluid * fluid1 = &getConstitutiveModel< TwoPhaseImmiscibleFluid >( *subRegion1, fluidName1 ); + + // m_interfaceConstitutivePairs[surfaceRegionIndex][0] = std::make_tuple( relPerm0, capPressure0, fluid0 ); + // m_interfaceConstitutivePairs[surfaceRegionIndex][1] = std::make_tuple( relPerm1, capPressure1, fluid1 ); + // Find a representative face element in this surface region with two adjacent cells +localIndex fei = -1; + +// Prefer face element 0 if valid; otherwise scan +if( faceElementsToCells.size() > 0 ) { - FlowSolverBase::registerDataOnMesh( meshBodies ); - - // 0. Find a "reference" fluid model name (at this point, models are already attached to subregions) - forDiscretizationOnMeshTargets( meshBodies, [&]( string const &, - MeshLevel & mesh, - string_array const & regionNames ) + // Check if face element 0 has two adjacent cells + if( faceElementsToCells.m_toElementRegion[0].size() >= 2 ) { - mesh.getElemManager().forElementSubRegions( regionNames, - [&]( localIndex const, - ElementSubRegionBase & subRegion ) - { - // If at least one region has a capillary pressure model, consider it enabled for all - string const capPresName = getConstitutiveName< CapillaryPressureBase >( subRegion ); - if( !capPresName.empty() ) - { - m_hasCapPressure = true; - } - } ); - } ); - - m_numDofPerCell = m_numPhases; - - // 2. Register and resize all fields as necessary - forDiscretizationOnMeshTargets( meshBodies, [&]( string const &, - MeshLevel & mesh, - string_array const & regionNames ) + fei = 0; + } + else { - mesh.getElemManager().forElementSubRegions( regionNames, - [&]( localIndex const, - ElementSubRegionBase & subRegion ) + // Scan to find the first interior face element with two neighbors + for( localIndex i = 1; i < faceElementsToCells.size(); ++i ) { - if( m_hasCapPressure ) + if( faceElementsToCells.m_toElementRegion[i].size() >= 2 ) { - subRegion.registerWrapper< string >( viewKeyStruct::capPressureNamesString() ). - setPlotLevel( PlotLevel::NOPLOT ). - setRestartFlags( RestartFlags::NO_WRITE ). - setSizedFromParent( 0 ). - setDescription( "Name of the capillary pressure constitutive model to use" ). - reference(); - - string & capPresName = subRegion.getReference< string >( viewKeyStruct::capPressureNamesString() ); - capPresName = getConstitutiveName< CapillaryPressureBase >( subRegion ); - GEOS_THROW_IF( capPresName.empty(), - GEOS_FMT( "{}: Capillary pressure model not found on subregion {}", - getDataContext(), subRegion.getDataContext() ), - InputError ); + fei = i; + break; } - - // The resizing of the arrays needs to happen here, before the call to initializePreSubGroups, - // to make sure that the dimensions are properly set before the timeHistoryOutput starts its initialization. - subRegion.registerField< phaseVolumeFraction >( getName() ). - reference().resizeDimension< 1 >( m_numPhases ); - - subRegion.registerField< phaseVolumeFraction_n >( getName() ). - reference().resizeDimension< 1 >( m_numPhases ); - - subRegion.registerField< bcPhaseVolumeFraction >( getName() ). - reference().resizeDimension< 1 >( m_numPhases ); - - subRegion.registerField< phaseMass >( getName() ). - reference().resizeDimension< 1 >( m_numPhases ); - - subRegion.registerField< phaseMass_n >( getName() ). - reference().resizeDimension< 1 >( m_numPhases ); - - subRegion.registerField< phaseMobility >( getName() ). - reference().resizeDimension< 1 >( m_numPhases ); - - subRegion.registerField< dPhaseMobility >( getName() ). - reference().resizeDimension< 1, 2 >( m_numPhases, m_numPhases ); // dP, dS - - } ); - - } ); -} - -void ImmiscibleMultiphaseFlow::setConstitutiveNames( ElementSubRegionBase & subRegion ) const -{ - setConstitutiveName< TwoPhaseImmiscibleFluid >( subRegion, viewKeyStruct::fluidNamesString(), "two phase immiscible fluid" ); - - setConstitutiveName< RelativePermeabilityBase >( subRegion, viewKeyStruct::relPermNamesString(), "relative permeability" ); -} - -void ImmiscibleMultiphaseFlow::initializePreSubGroups() -{ - m_linearSolverParameters.get().mgr.strategy = LinearSolverParameters::MGR::StrategyType::immiscibleMultiphaseFVM; - - FlowSolverBase::initializePreSubGroups(); - - DomainPartition & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" ); - - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel & mesh, - string_array const & regionNames ) - { - mesh.getElemManager().forElementSubRegions( regionNames, - [&]( localIndex const, - ElementSubRegionBase & subRegion ) - { - arrayView1d< real64 > const temp = subRegion.getField< fields::flow::temperature >(); - temp.setValues< parallelHostPolicy >( m_inputTemperature ); - } ); - } ); -} - - -void ImmiscibleMultiphaseFlow::updateFluidModel( ObjectManagerBase & dataGroup ) const -{ - GEOS_MARK_FUNCTION; - - arrayView1d< real64 const > const pres = dataGroup.getField< fields::flow::pressure >(); - - TwoPhaseImmiscibleFluid & fluid = getConstitutiveModel< TwoPhaseImmiscibleFluid >( dataGroup, dataGroup.getReference< string >( viewKeyStruct::fluidNamesString() ) ); - - constitutiveUpdatePassThru( fluid, [&] ( auto & castedFluid ) - { - using FluidType = TYPEOFREF( castedFluid ); - typename FluidType::KernelWrapper fluidWrapper = castedFluid.createKernelWrapper(); - - FluidUpdateKernel::launch< parallelDevicePolicy<> >( dataGroup.size(), fluidWrapper, pres ); - } ); -} - - -void ImmiscibleMultiphaseFlow::updateRelPermModel( ObjectManagerBase & dataGroup ) const -{ - GEOS_MARK_FUNCTION; - - - GEOS_UNUSED_VAR( dataGroup ); - - arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac = - dataGroup.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); - - string const & relPermName = dataGroup.getReference< string >( viewKeyStruct::relPermNamesString() ); - RelativePermeabilityBase & relPerm = getConstitutiveModel< RelativePermeabilityBase >( dataGroup, relPermName ); - - constitutive::constitutiveUpdatePassThru( relPerm, [&] ( auto & castedRelPerm ) - { - typename TYPEOFREF( castedRelPerm ) ::KernelWrapper relPermWrapper = castedRelPerm.createKernelWrapper(); - - isothermalCompositionalMultiphaseBaseKernels:: - RelativePermeabilityUpdateKernel:: - launch< parallelDevicePolicy<> >( dataGroup.size(), - relPermWrapper, - phaseVolFrac ); - } ); -} - -void ImmiscibleMultiphaseFlow::updateCapPressureModel( ObjectManagerBase & dataGroup ) const -{ - GEOS_MARK_FUNCTION; - - if( m_hasCapPressure ) - { - arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac = - dataGroup.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); - - string const & cappresName = dataGroup.getReference< string >( viewKeyStruct::capPressureNamesString() ); - CapillaryPressureBase & capPressure = getConstitutiveModel< CapillaryPressureBase >( dataGroup, cappresName ); - - constitutive::constitutiveUpdatePassThru( capPressure, [&] ( auto & castedCapPres ) - { - typename TYPEOFREF( castedCapPres ) ::KernelWrapper capPresWrapper = castedCapPres.createKernelWrapper(); - - isothermalCompositionalMultiphaseBaseKernels:: - CapillaryPressureUpdateKernel:: - launch< parallelDevicePolicy<> >( dataGroup.size(), - capPresWrapper, - phaseVolFrac ); - } ); - } -} - - -void ImmiscibleMultiphaseFlow::updateFluidState( ElementSubRegionBase & subRegion ) const -{ - GEOS_MARK_FUNCTION; - - updateFluidModel( subRegion ); - updateVolumeConstraint( subRegion ); - updatePhaseMass( subRegion ); - updateRelPermModel( subRegion ); - updatePhaseMobility( subRegion ); - updateCapPressureModel( subRegion ); -} - - -void ImmiscibleMultiphaseFlow::updatePhaseMass( ElementSubRegionBase & subRegion ) const -{ - GEOS_MARK_FUNCTION; - - string const & solidName = subRegion.getReference< string >( viewKeyStruct::solidNamesString() ); - string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); - - TwoPhaseImmiscibleFluid const & fluid = getConstitutiveModel< TwoPhaseImmiscibleFluid >( subRegion, fluidName ); - CoupledSolidBase const & solid = getConstitutiveModel< CoupledSolidBase >( subRegion, solidName ); - - arrayView1d< real64 const > const volume = subRegion.getElementVolume(); - arrayView2d< real64 const > const porosity = solid.getPorosity(); - - arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac= subRegion.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); - arrayView3d< real64 const, multifluid::USD_PHASE > phaseDens = fluid.phaseDensity(); - arrayView2d< real64, immiscibleFlow::USD_PHASE > const phaseMass = subRegion.getField< fields::immiscibleMultiphaseFlow::phaseMass >(); - - // Might be needed for geomechanics????? if so, need to change the accumulation as well? - //arrayView1d< real64 > const deltaVolume = subRegion.getField< fields::flow::deltaVolume >(); - - forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const ei ) - { - real64 const poreVolume = volume[ei] * porosity[ei][0]; - for( integer ip = 0; ip < 2; ++ip ) - { - phaseMass[ei][ip] = poreVolume * phaseVolFrac[ei][ip] * phaseDens[ei][0][ip]; - } - } ); -} - - -void ImmiscibleMultiphaseFlow::updatePhaseMobility( ObjectManagerBase & dataGroup ) const -{ - GEOS_MARK_FUNCTION; - - // note that the phase mobility computed here also includes phase density - string const & fluidName = dataGroup.getReference< string >( viewKeyStruct::fluidNamesString() ); - TwoPhaseImmiscibleFluid const & fluid = getConstitutiveModel< TwoPhaseImmiscibleFluid >( dataGroup, fluidName ); - - string const & relpermName = dataGroup.getReference< string >( viewKeyStruct::relPermNamesString() ); - RelativePermeabilityBase const & relperm = getConstitutiveModel< RelativePermeabilityBase >( dataGroup, relpermName ); - - immiscibleMultiphaseKernels:: - PhaseMobilityKernelFactory:: - createAndLaunch< parallelDevicePolicy<> >( m_numPhases, - dataGroup, - fluid, - relperm ); -} - -void ImmiscibleMultiphaseFlow::initializeFluidState( MeshLevel & mesh, - string_array const & regionNames ) -{ - GEOS_MARK_FUNCTION; - - mesh.getElemManager().forElementSubRegions( regionNames, - [&]( localIndex const, - ElementSubRegionBase & subRegion ) - { - // 2. Assume global component fractions have been prescribed. - // Initialize constitutive state to get fluid density. - updateFluidModel( subRegion ); - - } ); - - // for some reason CUDA does not want the host_device lambda to be defined inside the generic lambda - // I need the exact type of the subRegion for updateSolidflowProperties to work well. - mesh.getElemManager().forElementSubRegions< CellElementSubRegion, - SurfaceElementSubRegion >( regionNames, [&]( localIndex const, - auto & subRegion ) - { - // 4. Initialize/update dependent state quantities - - // 4.1 Update the constitutive models that only depend on - // - the primary variables - // - the fluid constitutive quantities (as they have already been updated) - // We postpone the other constitutive models for now - // In addition, to avoid multiplying permeability/porosity bay netToGross in the assembly kernel, we do it once and for all here - arrayView1d< real64 const > const netToGross = subRegion.template getField< fields::flow::netToGross >(); - CoupledSolidBase const & porousSolid = - getConstitutiveModel< CoupledSolidBase >( subRegion, subRegion.template getReference< string >( viewKeyStruct::solidNamesString() ) ); - PermeabilityBase const & permeabilityModel = - getConstitutiveModel< PermeabilityBase >( subRegion, subRegion.template getReference< string >( viewKeyStruct::permeabilityNamesString() ) ); - permeabilityModel.scaleHorizontalPermeability( netToGross ); - porousSolid.scaleReferencePorosity( netToGross ); - saveConvergedState( subRegion ); // necessary for a meaningful porosity update in sequential schemes - updatePorosityAndPermeability( subRegion ); - - // Now, we initialize and update each constitutive model one by one - - // 4.2 Save the computed porosity into the old porosity - // - // Note: - // - This must be called after updatePorosityAndPermeability - // - This step depends on porosity - string const & solidName = subRegion.template getReference< string >( viewKeyStruct::solidNamesString() ); - CoupledSolidBase const & porousMaterial = getConstitutiveModel< CoupledSolidBase >( subRegion, solidName ); - porousMaterial.initializeState(); - - // 4.3 Initialize/update the relative permeability model using the initial phase volume fraction - // This is needed to handle relative permeability hysteresis - // Also, initialize the fluid model - // - // Note: - // - This must be called after updateVolumeConstraint - // - This step depends on phaseVolFraction - - // initialized phase volume fraction - arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac = - subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); - - string const & relpermName = subRegion.template getReference< string >( viewKeyStruct::relPermNamesString() ); - RelativePermeabilityBase & relPermMaterial = - getConstitutiveModel< RelativePermeabilityBase >( subRegion, relpermName ); - relPermMaterial.saveConvergedPhaseVolFractionState( phaseVolFrac ); // this needs to happen before calling updateRelPermModel - updateRelPermModel( subRegion ); - relPermMaterial.saveConvergedState(); // this needs to happen after calling updateRelPermModel - - // 4.4 Then, we initialize/update the capillary pressure model - // - // Note: - // - This must be called after updatePorosityAndPermeability - // - This step depends on porosity and permeability - if( m_hasCapPressure ) - { - // initialized porosity - arrayView2d< real64 const > const porosity = porousMaterial.getPorosity(); - - string const & permName = subRegion.template getReference< string >( viewKeyStruct::permeabilityNamesString() ); - PermeabilityBase const & permeabilityMaterial = getConstitutiveModel< PermeabilityBase >( subRegion, permName ); - // initialized permeability - arrayView3d< real64 const > const permeability = permeabilityMaterial.permeability(); - - string const & capPressureName = subRegion.template getReference< string >( viewKeyStruct::capPressureNamesString() ); - CapillaryPressureBase const & capPressureMaterial = - getConstitutiveModel< CapillaryPressureBase >( subRegion, capPressureName ); - capPressureMaterial.initializeRockState( porosity, permeability ); // this needs to happen before calling updateCapPressureModel - updateCapPressureModel( subRegion ); } - - // 4.5 Update the phase mobility - // - // Note: - // - This must be called after updateRelPermModel - // - This step depends phaseRelPerm - updatePhaseMobility( subRegion ); - - } ); - - // 5. Save initial pressure - mesh.getElemManager().forElementSubRegions( regionNames, [&]( localIndex const, - ElementSubRegionBase & subRegion ) - { - arrayView1d< real64 const > const pres = subRegion.getField< fields::flow::pressure >(); - arrayView1d< real64 > const initPres = subRegion.getField< fields::flow::initialPressure >(); - arrayView1d< real64 const > const temp = subRegion.getField< fields::flow::temperature >(); - arrayView1d< real64 > const initTemp = subRegion.template getField< fields::flow::initialTemperature >(); - initPres.setValues< parallelDevicePolicy<> >( pres ); - initTemp.setValues< parallelDevicePolicy<> >( temp ); - - // TODO: Missing updatePhaseMass? - } ); -} - - -void ImmiscibleMultiphaseFlow::initializePostInitialConditionsPreSubGroups() -{ - GEOS_MARK_FUNCTION; - - FlowSolverBase::initializePostInitialConditionsPreSubGroups(); - - DomainPartition & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" ); - - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel & mesh, - string_array const & regionNames ) - { - FieldIdentifiers fieldsToBeSync; - fieldsToBeSync.addElementFields( { fields::flow::pressure::key(), - fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key() }, - regionNames ); - - CommunicationTools::getInstance().synchronizeFields( fieldsToBeSync, mesh, domain.getNeighbors(), false ); - } ); - - initializeState( domain ); -} - - -void -ImmiscibleMultiphaseFlow::implicitStepSetup( real64 const & GEOS_UNUSED_PARAM( time_n ), - real64 const & GEOS_UNUSED_PARAM( dt ), - DomainPartition & domain ) -{ - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel & mesh, - string_array const & regionNames ) - { - mesh.getElemManager().forElementSubRegions< CellElementSubRegion, - SurfaceElementSubRegion >( regionNames, - [&]( localIndex const, - auto & subRegion ) - { - saveConvergedState( subRegion ); - - // update porosity, permeability - updatePorosityAndPermeability( subRegion ); - // update all fluid properties - updateVolumeConstraint( subRegion ); - updateFluidState( subRegion ); - - // after the update, save the new saturation - arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac = - subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); - - arrayView2d< real64, immiscibleFlow::USD_PHASE > const phaseVolFrac_n = - subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction_n >(); - phaseVolFrac_n.setValues< parallelDevicePolicy<> >( phaseVolFrac ); - - arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const & phaseMass = - subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseMass >(); - - arrayView2d< real64, immiscibleFlow::USD_PHASE > const & phaseMass_n = - subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseMass_n >(); - phaseMass_n.setValues< parallelDevicePolicy<> >( phaseMass ); - - } ); - } ); + } } -void ImmiscibleMultiphaseFlow::assembleSystem( real64 const GEOS_UNUSED_PARAM( time_n ), - real64 const dt, - DomainPartition & domain, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) +// If no valid face element, skip this surface region +if( fei < 0 ) { - GEOS_MARK_FUNCTION; - - assembleAccumulationTerm( domain, - dofManager, - localMatrix, - localRhs ); - - - assembleFluxTerms( dt, - domain, - dofManager, - localMatrix, - localRhs ); + continue; } - - -void ImmiscibleMultiphaseFlow::assembleAccumulationTerm( DomainPartition & domain, +std::tuple< CellElementSubRegion *, CellElementSubRegion * > subRegionPair = getSubregions( fei ); +CellElementSubRegion * subRegion0 = std::get< 0 >( subRegionPair ); +CellElementSubRegion * subRegion1 = std::get< 1 >( subRegionPair ); + +// get constitutives by type and name: relPerms, capPressures, Fluids (three pointers) +std::string & relPermName0 = subRegion0->getReference< std::string >( viewKeyStruct::relPermNamesString()); +std::string & relPermName1 = subRegion1->getReference< std::string >( viewKeyStruct::relPermNamesString()); +RelativePermeabilityBase * relPerm0 = &getConstitutiveModel< RelativePermeabilityBase >( *subRegion0, relPermName0 ); +RelativePermeabilityBase * relPerm1 = &getConstitutiveModel< RelativePermeabilityBase >( *subRegion1, relPermName1 ); + +std::string & cappresName0 = subRegion0->getReference< std::string >( viewKeyStruct::capPressureNamesString()); +std::string & cappresName1 = subRegion1->getReference< std::string >( viewKeyStruct::capPressureNamesString()); +CapillaryPressureBase * capPressure0 = &getConstitutiveModel< CapillaryPressureBase >( *subRegion0, cappresName0 ); +CapillaryPressureBase * capPressure1 = &getConstitutiveModel< CapillaryPressureBase >( *subRegion1, cappresName1 ); + +std::string & fluidName0 = subRegion0->getReference< std::string >( viewKeyStruct::fluidNamesString() ); +std::string & fluidName1 = subRegion1->getReference< std::string >( viewKeyStruct::fluidNamesString() ); + +TwoPhaseImmiscibleFluid * fluid0 = &getConstitutiveModel< TwoPhaseImmiscibleFluid >( *subRegion0, fluidName0 ); +TwoPhaseImmiscibleFluid * fluid1 = &getConstitutiveModel< TwoPhaseImmiscibleFluid >( *subRegion1, fluidName1 ); + +m_interfaceConstitutivePairs[surfaceRegionIndex][0] = std::make_tuple( relPerm0, capPressure0, fluid0 ); +m_interfaceConstitutivePairs[surfaceRegionIndex][1] = std::make_tuple( relPerm1, capPressure1, fluid1 ); + + } + } ); + + } + + + void ImmiscibleMultiphaseFlow::updateFluidModel( ObjectManagerBase & dataGroup ) const + { + GEOS_MARK_FUNCTION; + + arrayView1d< real64 const > const pres = dataGroup.getField< fields::flow::pressure >(); + + TwoPhaseImmiscibleFluid & fluid = getConstitutiveModel< TwoPhaseImmiscibleFluid >( dataGroup, dataGroup.getReference< string >( viewKeyStruct::fluidNamesString() ) ); + + constitutiveUpdatePassThru( fluid, [&] ( auto & castedFluid ) + { + using FluidType = TYPEOFREF( castedFluid ); + typename FluidType::KernelWrapper fluidWrapper = castedFluid.createKernelWrapper(); + + FluidUpdateKernel::launch< parallelDevicePolicy<> >( dataGroup.size(), fluidWrapper, pres ); + } ); + } + + + void ImmiscibleMultiphaseFlow::updateRelPermModel( ObjectManagerBase & dataGroup ) const + { + GEOS_MARK_FUNCTION; + + + GEOS_UNUSED_VAR( dataGroup ); + + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac = + dataGroup.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); + + string const & relPermName = dataGroup.getReference< string >( viewKeyStruct::relPermNamesString() ); + RelativePermeabilityBase & relPerm = getConstitutiveModel< RelativePermeabilityBase >( dataGroup, relPermName ); + + constitutive::constitutiveUpdatePassThru( relPerm, [&] ( auto & castedRelPerm ) + { + typename TYPEOFREF( castedRelPerm ) ::KernelWrapper relPermWrapper = castedRelPerm.createKernelWrapper(); + + isothermalCompositionalMultiphaseBaseKernels:: + RelativePermeabilityUpdateKernel:: + launch< parallelDevicePolicy<> >( dataGroup.size(), + relPermWrapper, + phaseVolFrac ); + } ); + } + + void ImmiscibleMultiphaseFlow::updateCapPressureModel( ObjectManagerBase & dataGroup ) const + { + GEOS_MARK_FUNCTION; + + if( m_hasCapPressure ) + { + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac = + dataGroup.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); + + string const & cappresName = dataGroup.getReference< string >( viewKeyStruct::capPressureNamesString() ); + CapillaryPressureBase & capPressure = getConstitutiveModel< CapillaryPressureBase >( dataGroup, cappresName ); + + constitutive::constitutiveUpdatePassThru( capPressure, [&] ( auto & castedCapPres ) + { + typename TYPEOFREF( castedCapPres ) ::KernelWrapper capPresWrapper = castedCapPres.createKernelWrapper(); + + // isothermalCompositionalMultiphaseBaseKernels:: + immiscibleMultiphaseKernels:: + CapillaryPressureUpdateKernel:: + launch< parallelDevicePolicy<> >( dataGroup.size(), + capPresWrapper, + phaseVolFrac ); + } ); + } + } + + + void ImmiscibleMultiphaseFlow::updateFluidState( ElementSubRegionBase & subRegion ) const + { + GEOS_MARK_FUNCTION; + + updateFluidModel( subRegion ); + updateVolumeConstraint( subRegion ); + updatePhaseMass( subRegion ); + updateRelPermModel( subRegion ); + updatePhaseMobility( subRegion ); + updateCapPressureModel( subRegion ); + } + + + void ImmiscibleMultiphaseFlow::updatePhaseMass( ElementSubRegionBase & subRegion ) const + { + GEOS_MARK_FUNCTION; + + string const & solidName = subRegion.getReference< string >( viewKeyStruct::solidNamesString() ); + string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); + + TwoPhaseImmiscibleFluid const & fluid = getConstitutiveModel< TwoPhaseImmiscibleFluid >( subRegion, fluidName ); + CoupledSolidBase const & solid = getConstitutiveModel< CoupledSolidBase >( subRegion, solidName ); + + arrayView1d< real64 const > const volume = subRegion.getElementVolume(); + arrayView2d< real64 const > const porosity = solid.getPorosity(); + + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac= subRegion.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); + arrayView3d< real64 const, multifluid::USD_PHASE > phaseDens = fluid.phaseDensity(); + arrayView2d< real64, immiscibleFlow::USD_PHASE > const phaseMass = subRegion.getField< fields::immiscibleMultiphaseFlow::phaseMass >(); + + // Might be needed for geomechanics????? if so, need to change the accumulation as well? + //arrayView1d< real64 > const deltaVolume = subRegion.getField< fields::flow::deltaVolume >(); + + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const ei ) + { + real64 const poreVolume = volume[ei] * porosity[ei][0]; + for( integer ip = 0; ip < 2; ++ip ) + { + phaseMass[ei][ip] = poreVolume * phaseVolFrac[ei][ip] * phaseDens[ei][0][ip]; + } + } ); + } + + + void ImmiscibleMultiphaseFlow::updatePhaseMobility( ObjectManagerBase & dataGroup ) const + { + GEOS_MARK_FUNCTION; + + // note that the phase mobility computed here also includes phase density + string const & fluidName = dataGroup.getReference< string >( viewKeyStruct::fluidNamesString() ); + TwoPhaseImmiscibleFluid const & fluid = getConstitutiveModel< TwoPhaseImmiscibleFluid >( dataGroup, fluidName ); + + string const & relpermName = dataGroup.getReference< string >( viewKeyStruct::relPermNamesString() ); + RelativePermeabilityBase const & relperm = getConstitutiveModel< RelativePermeabilityBase >( dataGroup, relpermName ); + + immiscibleMultiphaseKernels:: + PhaseMobilityKernelFactory:: + createAndLaunch< parallelDevicePolicy<> >( m_numPhases, + dataGroup, + fluid, + relperm ); + } + + void ImmiscibleMultiphaseFlow::initializeFluidState( MeshLevel & mesh, + string_array const & regionNames ) + { + GEOS_MARK_FUNCTION; + + mesh.getElemManager().forElementSubRegions( regionNames, + [&]( localIndex const, + ElementSubRegionBase & subRegion ) + { + // 2. Assume global component fractions have been prescribed. + // Initialize constitutive state to get fluid density. + updateFluidModel( subRegion ); + + } ); + + // for some reason CUDA does not want the host_device lambda to be defined inside the generic lambda + // I need the exact type of the subRegion for updateSolidflowProperties to work well. + mesh.getElemManager().forElementSubRegions< CellElementSubRegion, + SurfaceElementSubRegion >( regionNames, [&]( localIndex const, + auto & subRegion ) + { + // 4. Initialize/update dependent state quantities + + // 4.1 Update the constitutive models that only depend on + // - the primary variables + // - the fluid constitutive quantities (as they have already been updated) + // We postpone the other constitutive models for now + // In addition, to avoid multiplying permeability/porosity bay netToGross in the assembly kernel, we do it once and for all here + arrayView1d< real64 const > const netToGross = subRegion.template getField< fields::flow::netToGross >(); + CoupledSolidBase const & porousSolid = + getConstitutiveModel< CoupledSolidBase >( subRegion, subRegion.template getReference< string >( viewKeyStruct::solidNamesString() ) ); + PermeabilityBase const & permeabilityModel = + getConstitutiveModel< PermeabilityBase >( subRegion, subRegion.template getReference< string >( viewKeyStruct::permeabilityNamesString() ) ); + permeabilityModel.scaleHorizontalPermeability( netToGross ); + porousSolid.scaleReferencePorosity( netToGross ); + saveConvergedState( subRegion ); // necessary for a meaningful porosity update in sequential schemes + updatePorosityAndPermeability( subRegion ); + + // Now, we initialize and update each constitutive model one by one + + // 4.2 Save the computed porosity into the old porosity + // + // Note: + // - This must be called after updatePorosityAndPermeability + // - This step depends on porosity + string const & solidName = subRegion.template getReference< string >( viewKeyStruct::solidNamesString() ); + CoupledSolidBase const & porousMaterial = getConstitutiveModel< CoupledSolidBase >( subRegion, solidName ); + porousMaterial.initializeState(); + + // 4.3 Initialize/update the relative permeability model using the initial phase volume fraction + // This is needed to handle relative permeability hysteresis + // Also, initialize the fluid model + // + // Note: + // - This must be called after updateVolumeConstraint + // - This step depends on phaseVolFraction + + // initialized phase volume fraction + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac = + subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); + + string const & relpermName = subRegion.template getReference< string >( viewKeyStruct::relPermNamesString() ); + RelativePermeabilityBase & relPermMaterial = + getConstitutiveModel< RelativePermeabilityBase >( subRegion, relpermName ); + relPermMaterial.saveConvergedPhaseVolFractionState( phaseVolFrac ); // this needs to happen before calling updateRelPermModel + updateRelPermModel( subRegion ); + relPermMaterial.saveConvergedState(); // this needs to happen after calling updateRelPermModel + + // 4.4 Then, we initialize/update the capillary pressure model + // + // Note: + // - This must be called after updatePorosityAndPermeability + // - This step depends on porosity and permeability + if( m_hasCapPressure ) + { + // initialized porosity + arrayView2d< real64 const > const porosity = porousMaterial.getPorosity(); + + string const & permName = subRegion.template getReference< string >( viewKeyStruct::permeabilityNamesString() ); + PermeabilityBase const & permeabilityMaterial = getConstitutiveModel< PermeabilityBase >( subRegion, permName ); + // initialized permeability + arrayView3d< real64 const > const permeability = permeabilityMaterial.permeability(); + + string const & capPressureName = subRegion.template getReference< string >( viewKeyStruct::capPressureNamesString() ); + CapillaryPressureBase const & capPressureMaterial = + getConstitutiveModel< CapillaryPressureBase >( subRegion, capPressureName ); + capPressureMaterial.initializeRockState( porosity, permeability ); // this needs to happen before calling updateCapPressureModel + updateCapPressureModel( subRegion ); + } + + // 4.5 Update the phase mobility + // + // Note: + // - This must be called after updateRelPermModel + // - This step depends phaseRelPerm + updatePhaseMobility( subRegion ); + + } ); + + // 5. Save initial pressure + mesh.getElemManager().forElementSubRegions( regionNames, [&]( localIndex const, + ElementSubRegionBase & subRegion ) + { + arrayView1d< real64 const > const pres = subRegion.getField< fields::flow::pressure >(); + arrayView1d< real64 > const initPres = subRegion.getField< fields::flow::initialPressure >(); + arrayView1d< real64 const > const temp = subRegion.getField< fields::flow::temperature >(); + arrayView1d< real64 > const initTemp = subRegion.template getField< fields::flow::initialTemperature >(); + initPres.setValues< parallelDevicePolicy<> >( pres ); + initTemp.setValues< parallelDevicePolicy<> >( temp ); + + // TODO: Missing updatePhaseMass? + } ); + } + + + void ImmiscibleMultiphaseFlow::initializePostInitialConditionsPreSubGroups() + { + GEOS_MARK_FUNCTION; + + FlowSolverBase::initializePostInitialConditionsPreSubGroups(); + + DomainPartition & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" ); + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + FieldIdentifiers fieldsToBeSync; + fieldsToBeSync.addElementFields( { fields::flow::pressure::key(), + fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key() }, + regionNames ); + + CommunicationTools::getInstance().synchronizeFields( fieldsToBeSync, mesh, domain.getNeighbors(), false ); + } ); + + // Retrieve the numerical methods and finite volume manager + FiniteVolumeManager const & fvManager = domain.getNumericalMethodManager().getFiniteVolumeManager(); + FluxApproximationBase const & fluxApprox = fvManager.getFluxApproximation( m_discretizationName ); + const geos::string flux_approximation_name = fluxApprox.getName(); + + // Clear the existing mapping between connector indices and interface region indices + m_interfaceRegionByConnector.clear(); + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( std::string const &, + MeshLevel & meshLevel, + string_array const & regionNames ) + { + // Access the face manager and retrieve the face set group for the current mesh level + FaceManager const & faceManager = meshLevel.getFaceManager(); + Group const & faceSetGroup = faceManager.sets(); + + // Access the connector indices map (face index → connector index) + Group & stencilGroup = + meshLevel.getGroup( FluxApproximationBase::groupKeyStruct::stencilMeshGroupString()) + .getGroup( flux_approximation_name ); + CellElementStencilTPFA & stencil = + stencilGroup.getReference< CellElementStencilTPFA >( + FluxApproximationBase::viewKeyStruct::cellStencilString()); + unordered_map< localIndex, localIndex > const & connectorIndices = stencil.getConnectorIndices(); + + // for all interface face sets to map connector indices to their corresponding interface region indices + for( size_t surfaceRegionIndex = 0; surfaceRegionIndex < m_interfaceFaceSetNames.size(); ++surfaceRegionIndex ) + { + // Iterate over each face and associate its connector index + std::string const & faceSetName = m_interfaceFaceSetNames[surfaceRegionIndex]; + for( localIndex kf : faceSetGroup.getReference< SortedArray< localIndex > >( faceSetName )) + { + auto it = connectorIndices.find( kf ); + if( it != connectorIndices.end()) + { + // Map the connector index to the corresponding surface region index + m_interfaceRegionByConnector[it->second] = surfaceRegionIndex; + } + } + } + } ); + + + initializeState( domain ); + } + + + void + ImmiscibleMultiphaseFlow::implicitStepSetup( real64 const & GEOS_UNUSED_PARAM( time_n ), + real64 const & GEOS_UNUSED_PARAM( dt ), + DomainPartition & domain ) + { + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + mesh.getElemManager().forElementSubRegions< CellElementSubRegion, + SurfaceElementSubRegion >( regionNames, + [&]( localIndex const, + auto & subRegion ) + { + saveConvergedState( subRegion ); + + // update porosity, permeability + updatePorosityAndPermeability( subRegion ); + // update all fluid properties + updateVolumeConstraint( subRegion ); + updateFluidState( subRegion ); + + // after the update, save the new saturation + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac = + subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); + + arrayView2d< real64, immiscibleFlow::USD_PHASE > const phaseVolFrac_n = + subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction_n >(); + phaseVolFrac_n.setValues< parallelDevicePolicy<> >( phaseVolFrac ); + + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const & phaseMass = + subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseMass >(); + + arrayView2d< real64, immiscibleFlow::USD_PHASE > const & phaseMass_n = + subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseMass_n >(); + phaseMass_n.setValues< parallelDevicePolicy<> >( phaseMass ); + + } ); + } ); + } + + void ImmiscibleMultiphaseFlow::assembleSystem( real64 const GEOS_UNUSED_PARAM( time_n ), + real64 const dt, + DomainPartition & domain, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) + { + GEOS_MARK_FUNCTION; + + assembleAccumulationTerm( domain, + dofManager, + localMatrix, + localRhs ); + + + assembleFluxTerms( dt, + domain, + dofManager, + localMatrix, + localRhs ); + } + + + + void ImmiscibleMultiphaseFlow::assembleAccumulationTerm( DomainPartition & domain, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) const + { + GEOS_MARK_FUNCTION; + + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel const & mesh, + string_array const & regionNames ) + { + mesh.getElemManager().forElementSubRegions( regionNames, + [&]( localIndex const, + ElementSubRegionBase const & subRegion ) + { + string const dofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); + string const & solidName = subRegion.getReference< string >( viewKeyStruct::solidNamesString() ); + string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); + + TwoPhaseImmiscibleFluid const & fluid = getConstitutiveModel< TwoPhaseImmiscibleFluid >( subRegion, fluidName ); + CoupledSolidBase const & solid = getConstitutiveModel< CoupledSolidBase >( subRegion, solidName ); + + immiscibleMultiphaseKernels:: + AccumulationKernelFactory:: + createAndLaunch< parallelDevicePolicy<> >( m_numPhases, + dofManager.rankOffset(), + m_useTotalMassEquation, + dofKey, + subRegion, + fluid, + solid, + localMatrix, + localRhs ); + + } ); + } ); + } + + void ImmiscibleMultiphaseFlow::assembleFluxTerms( real64 const dt, + DomainPartition & domain, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) const + { + GEOS_MARK_FUNCTION; + + NumericalMethodsManager const & numericalMethodManager = domain.getNumericalMethodManager(); + FiniteVolumeManager const & fvManager = numericalMethodManager.getFiniteVolumeManager(); + FluxApproximationBase const & fluxApprox = fvManager.getFluxApproximation( m_discretizationName ); + + string const & dofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); + + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + if( m_hasCapPressure ) + { + mesh.getElemManager().forElementSubRegions( regionNames, + [&]( localIndex const, + ElementSubRegionBase & subRegion ) // Check if you need this. + { + // // Capillary pressure wrapper + // string const & cappresName = subRegion.getReference< string >( viewKeyStruct::capPressureNamesString() ); + // BrooksCoreyCapillaryPressure & capPressure = getConstitutiveModel< BrooksCoreyCapillaryPressure >( subRegion, cappresName ); + // CapillaryPressureBase * capPressure1 = &getConstitutiveModel< CapillaryPressureBase >( subRegion, cappresName ); + // BrooksCoreyCapillaryPressure::KernelWrapper capPresWrapper = capPressure.createKernelWrapper(); + + // // Relative permeability wrapper + // string const & relPermName = subRegion.getReference< string >( viewKeyStruct::relPermNamesString() ); + // BrooksCoreyRelativePermeability & relPerm = getConstitutiveModel< BrooksCoreyRelativePermeability >( subRegion, relPermName ); + // RelativePermeabilityBase * relPerm1 = &getConstitutiveModel< RelativePermeabilityBase >( subRegion, relPermName ); + // BrooksCoreyRelativePermeability::KernelWrapper relPermWrapper = relPerm.createKernelWrapper(); + + // // fluid + // string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); + // TwoPhaseImmiscibleFluid * fluid = &getConstitutiveModel< TwoPhaseImmiscibleFluid >( subRegion, fluidName ); + + // // m_interfaceConstitutivePairs[0][0] = std::make_tuple( relPerm1, capPressure1, fluid ); + // // m_interfaceConstitutivePairs[0][1] = std::make_tuple( relPerm1, capPressure1, fluid ); + + // auto interfaceConstitutivePairs_temp = std::make_tuple( relPerm1, capPressure1, fluid ); + + fluxApprox.forAllStencils( mesh, [&]( auto & stencil ) + { + typename TYPEOFREF( stencil ) ::KernelWrapper stencilWrapper = stencil.createKernelWrapper(); + immiscibleMultiphaseKernels:: + FluxComputeKernelFactory::createAndLaunch< parallelDevicePolicy<> >( m_numPhases, + dofManager.rankOffset(), + dofKey, + m_hasCapPressure, + m_useTotalMassEquation, + m_gravityDensityScheme == GravityDensityScheme::PhasePresence, + getName(), + mesh.getElemManager(), + stencilWrapper, + // capPresWrapper, + // relPermWrapper, + m_interfaceFaceSetNames, + m_interfaceConstitutivePairs, + m_interfaceRegionByConnector, + // interfaceConstitutivePairs_temp, + subRegion, + dt, + localMatrix.toViewConstSizes(), + localRhs.toView() ); + } ); + } ); + } + else + { + fluxApprox.forAllStencils( mesh, [&]( auto & stencil ) + { + typename TYPEOFREF( stencil ) ::KernelWrapper stencilWrapper = stencil.createKernelWrapper(); + immiscibleMultiphaseKernels:: + FluxComputeKernelFactory::createAndLaunch< parallelDevicePolicy<> >( m_numPhases, + dofManager.rankOffset(), + dofKey, + m_hasCapPressure, + m_useTotalMassEquation, + m_gravityDensityScheme == GravityDensityScheme::PhasePresence, + getName(), + mesh.getElemManager(), + stencilWrapper, + dt, + localMatrix.toViewConstSizes(), + localRhs.toView() ); + } ); + } + + } ); + } + + // Ryan: Looks like this will need to be overwritten as well... + // I have left the CompositionalMultiphaseFVM implementation for reference + void ImmiscibleMultiphaseFlow::setupDofs( DomainPartition const & domain, + DofManager & dofManager ) const + { + GEOS_UNUSED_VAR( domain, dofManager ); + // add a field for the cell-centered degrees of freedom + dofManager.addField( viewKeyStruct::elemDofFieldString(), + FieldLocation::Elem, + m_numDofPerCell, + getMeshTargets() ); + + //// this call with instruct GEOS to reorder the dof numbers + //dofManager.setLocalReorderingType( viewKeyStruct::elemDofFieldString(), + // DofManager::LocalReorderingType::ReverseCutHillMcKee ); + + NumericalMethodsManager const & numericalMethodManager = domain.getNumericalMethodManager(); + FiniteVolumeManager const & fvManager = numericalMethodManager.getFiniteVolumeManager(); + FluxApproximationBase const & fluxApprox = fvManager.getFluxApproximation( m_discretizationName ); + dofManager.addCoupling( viewKeyStruct::elemDofFieldString(), fluxApprox ); + } + + void ImmiscibleMultiphaseFlow::applyBoundaryConditions( real64 const time_n, + real64 const dt, + DomainPartition & domain, DofManager const & dofManager, CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) const -{ - GEOS_MARK_FUNCTION; - - - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel const & mesh, - string_array const & regionNames ) - { - mesh.getElemManager().forElementSubRegions( regionNames, - [&]( localIndex const, - ElementSubRegionBase const & subRegion ) - { - string const dofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); - string const & solidName = subRegion.getReference< string >( viewKeyStruct::solidNamesString() ); - string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); - - TwoPhaseImmiscibleFluid const & fluid = getConstitutiveModel< TwoPhaseImmiscibleFluid >( subRegion, fluidName ); - CoupledSolidBase const & solid = getConstitutiveModel< CoupledSolidBase >( subRegion, solidName ); - - immiscibleMultiphaseKernels:: - AccumulationKernelFactory:: - createAndLaunch< parallelDevicePolicy<> >( m_numPhases, - dofManager.rankOffset(), - m_useTotalMassEquation, - dofKey, - subRegion, - fluid, - solid, - localMatrix, - localRhs ); - - } ); - } ); -} - -void ImmiscibleMultiphaseFlow::assembleFluxTerms( real64 const dt, - DomainPartition const & domain, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) const -{ - GEOS_MARK_FUNCTION; - - NumericalMethodsManager const & numericalMethodManager = domain.getNumericalMethodManager(); - FiniteVolumeManager const & fvManager = numericalMethodManager.getFiniteVolumeManager(); - FluxApproximationBase const & fluxApprox = fvManager.getFluxApproximation( m_discretizationName ); - - string const & dofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); - - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, - MeshLevel const & mesh, + arrayView1d< real64 > const & localRhs ) + { + GEOS_MARK_FUNCTION; + + // apply pressure boundary conditions. + applyDirichletBC( time_n, dt, dofManager, domain, localMatrix.toViewConstSizes(), localRhs.toView() ); + + // apply flux boundary conditions + applySourceFluxBC( time_n, dt, dofManager, domain, localMatrix.toViewConstSizes(), localRhs.toView() ); + } + + + namespace + { + char const bcLogMessage[] = + "ImmiscibleMultiphaseFlow {}: at time {}s, " + "the <{}> boundary condition '{}' is applied to the element set '{}' in subRegion '{}'. " + "\nThe scale of this boundary condition is {} and multiplies the value of the provided function (if any). " + "\nThe total number of target elements (including ghost elements) is {}. " + "\nNote that if this number is equal to zero for all subRegions, the boundary condition will not be applied on this element set."; + } + + bool ImmiscibleMultiphaseFlow::validateDirichletBC( DomainPartition & domain, + real64 const time ) const + { + constexpr integer MAX_NP = 2; + FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); + + bool bcConsistent = true; + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, string_array const & ) - { - fluxApprox.forAllStencils( mesh, [&]( auto & stencil ) - { - typename TYPEOFREF( stencil ) ::KernelWrapper stencilWrapper = stencil.createKernelWrapper(); - immiscibleMultiphaseKernels:: - FluxComputeKernelFactory::createAndLaunch< parallelDevicePolicy<> >( m_numPhases, - dofManager.rankOffset(), - dofKey, - m_hasCapPressure, - m_useTotalMassEquation, - m_gravityDensityScheme == GravityDensityScheme::PhasePresence, - getName(), - mesh.getElemManager(), - stencilWrapper, - dt, - localMatrix.toViewConstSizes(), - localRhs.toView() ); - } ); - } ); -} - -void ImmiscibleMultiphaseFlow::setupDofs( DomainPartition const & domain, - DofManager & dofManager ) const -{ - GEOS_UNUSED_VAR( domain, dofManager ); - // add a field for the cell-centered degrees of freedom - dofManager.addField( viewKeyStruct::elemDofFieldString(), - FieldLocation::Elem, - m_numDofPerCell, - getMeshTargets() ); - - //// this call with instruct GEOS to reorder the dof numbers - //dofManager.setLocalReorderingType( viewKeyStruct::elemDofFieldString(), - // DofManager::LocalReorderingType::ReverseCutHillMcKee ); - - NumericalMethodsManager const & numericalMethodManager = domain.getNumericalMethodManager(); - FiniteVolumeManager const & fvManager = numericalMethodManager.getFiniteVolumeManager(); - FluxApproximationBase const & fluxApprox = fvManager.getFluxApproximation( m_discretizationName ); - dofManager.addCoupling( viewKeyStruct::elemDofFieldString(), fluxApprox ); -} - -void ImmiscibleMultiphaseFlow::applyBoundaryConditions( real64 const time_n, - real64 const dt, - DomainPartition & domain, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) -{ - GEOS_MARK_FUNCTION; - - // apply pressure boundary conditions. - applyDirichletBC( time_n, dt, dofManager, domain, localMatrix.toViewConstSizes(), localRhs.toView() ); - - // apply flux boundary conditions - applySourceFluxBC( time_n, dt, dofManager, domain, localMatrix.toViewConstSizes(), localRhs.toView() ); -} - - -namespace -{ -char const bcLogMessage[] = - "ImmiscibleMultiphaseFlow {}: at time {}s, " - "the <{}> boundary condition '{}' is applied to the element set '{}' in subRegion '{}'. " - "\nThe scale of this boundary condition is {} and multiplies the value of the provided function (if any). " - "\nThe total number of target elements (including ghost elements) is {}. " - "\nNote that if this number is equal to zero for all subRegions, the boundary condition will not be applied on this element set."; -} - -bool ImmiscibleMultiphaseFlow::validateDirichletBC( DomainPartition & domain, - real64 const time ) const -{ - constexpr integer MAX_NP = 2; - FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); - - bool bcConsistent = true; - - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel & mesh, - string_array const & ) - { - // map: regionName -> subRegionName -> setName -> numPhases to check pressure/phase are present consistent - map< string, map< string, map< string, ComponentMask< MAX_NP > > > > bcPresCompStatusMap; - - // 1. Check pressure Dirichlet BCs - fsManager.apply< ElementSubRegionBase >( time, - mesh, - fields::flow::pressure::key(), - [&]( FieldSpecificationBase const &, - string const & setName, - SortedArrayView< localIndex const > const &, - ElementSubRegionBase & subRegion, - string const & ) - { - // Check whether pressure has already been applied to this set - string const & subRegionName = subRegion.getName(); - string const & regionName = subRegion.getParent().getParent().getName(); - - auto & subRegionSetMap = bcPresCompStatusMap[regionName][subRegionName]; - if( subRegionSetMap.count( setName ) > 0 ) - { - bcConsistent = false; - GEOS_WARNING( BCMessage::pressureConflict( regionName, subRegionName, setName, - fields::flow::pressure::key() ) ); - } - subRegionSetMap[setName].setNumComp( m_numPhases ); - } ); - // 2. Check saturation Dirichlet BCs - fsManager.apply< ElementSubRegionBase >( time, - mesh, - fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key(), - [&] ( FieldSpecificationBase const & fs, + { + // map: regionName -> subRegionName -> setName -> numPhases to check pressure/phase are present consistent + map< string, map< string, map< string, ComponentMask< MAX_NP > > > > bcPresCompStatusMap; + + // 1. Check pressure Dirichlet BCs + fsManager.apply< ElementSubRegionBase >( time, + mesh, + fields::flow::pressure::key(), + [&]( FieldSpecificationBase const &, string const & setName, SortedArrayView< localIndex const > const &, ElementSubRegionBase & subRegion, string const & ) - { - string const & subRegionName = subRegion.getName( ); - string const & regionName = subRegion.getParent().getParent().getName(); - integer const comp = fs.getComponent(); - - auto & subRegionSetMap = bcPresCompStatusMap[regionName][subRegionName]; - if( subRegionSetMap.count( setName ) == 0 ) - { - bcConsistent = false; - GEOS_WARNING( BCMessage::missingPressure( regionName, subRegionName, setName, - fields::flow::pressure::key() ) ); - } - if( comp < 0 || comp >= m_numPhases ) - { - bcConsistent = false; - GEOS_WARNING( BCMessage::invalidComponentIndex( comp, fs.getName(), - fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key() ) ); - return; // can't check next part with invalid component id - } - - ComponentMask< MAX_NP > & compMask = subRegionSetMap[setName]; - if( compMask[comp] ) - { - bcConsistent = false; - fsManager.forSubGroups< EquilibriumInitialCondition >( [&] ( EquilibriumInitialCondition const & bc ) - { - string_array const & componentNames = bc.getComponentNames(); - GEOS_WARNING( BCMessage::conflictingComposition( comp, componentNames[comp], - regionName, subRegionName, setName, - fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key() ) ); - } ); - } - compMask.set( comp ); - } ); - - // 3.2 Check consistency between composition BC applied to sets - // Note: for a temperature-only boundary condition, this loop does not do anything - for( auto const & regionEntry : bcPresCompStatusMap ) - { - for( auto const & subRegionEntry : regionEntry.second ) - { - for( auto const & setEntry : subRegionEntry.second ) - { - ComponentMask< MAX_NP > const & compMask = setEntry.second; - - fsManager.forSubGroups< EquilibriumInitialCondition >( [&] ( EquilibriumInitialCondition const & fs ) - { - string_array const & componentNames = fs.getComponentNames(); - for( size_t ic = 0; ic < componentNames.size(); ic++ ) - { - if( !compMask[ic] ) - { - bcConsistent = false; - GEOS_WARNING( BCMessage::notAppliedOnRegion( ic, componentNames[ic], - regionEntry.first, subRegionEntry.first, setEntry.first, - fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key() ) ); - } - } - } ); - } - } - } - } ); - - return bcConsistent; -} - -void ImmiscibleMultiphaseFlow::applyDirichletBC( real64 const time_n, - real64 const dt, - DofManager const & dofManager, - DomainPartition & domain, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) const -{ - GEOS_MARK_FUNCTION; - - // Only validate BC at the beginning of Newton loop - if( m_nonlinearSolverParameters.m_numNewtonIterations == 0 ) - { - bool const bcConsistent = validateDirichletBC( domain, time_n + dt ); - GEOS_ERROR_IF( !bcConsistent, GEOS_FMT( "ImmiscibleMultiphaseFlow {}: inconsistent boundary conditions", getDataContext() ) ); - } - - FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); - - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel & mesh, - string_array const & ) - { - - // 1. Apply pressure Dirichlet BCs, store in a separate field - applyFieldValue< ElementSubRegionBase >( time_n, dt, mesh, bcLogMessage, - fields::flow::pressure::key(), fields::flow::bcPressure::key() ); - // 2. Apply saturation BC (phase volume fraction) and store in a separate field - applyFieldValue< ElementSubRegionBase >( time_n, dt, mesh, bcLogMessage, - fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key(), - fields::immiscibleMultiphaseFlow::bcPhaseVolumeFraction::key() ); - - globalIndex const rankOffset = dofManager.rankOffset(); - string const dofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); - - // 3. Call constitutive update - fsManager.apply< ElementSubRegionBase >( time_n + dt, - mesh, - fields::flow::pressure::key(), - [&] ( FieldSpecificationBase const &, - string const &, - SortedArrayView< localIndex const > const & targetSet, - ElementSubRegionBase & subRegion, - string const & ) - { - - arrayView1d< real64 const > const bcPres = - subRegion.getReference< array1d< real64 > >( fields::flow::bcPressure::key() ); - arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const bcPhaseVolFraction = - subRegion.getReference< array2d< real64, immiscibleFlow::LAYOUT_PHASE > >( - fields::immiscibleMultiphaseFlow::bcPhaseVolumeFraction::key() ); - - arrayView1d< integer const > const ghostRank = - subRegion.getReference< array1d< integer > >( ObjectManagerBase::viewKeyStruct::ghostRankString() ); - arrayView1d< globalIndex const > const dofNumber = - subRegion.getReference< array1d< globalIndex > >( dofKey ); - arrayView1d< real64 const > const pres = - subRegion.getReference< array1d< real64 > >( fields::flow::pressure::key() ); - arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFraction = - subRegion.getReference< array2d< real64, immiscibleFlow::LAYOUT_PHASE > >( - fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key() ); - - integer const numPhase = m_numPhases; - - - forAll< parallelDevicePolicy<> >( targetSet.size(), [=] GEOS_HOST_DEVICE ( localIndex const a ) - { - localIndex const ei = targetSet[a]; - if( ghostRank[ei] >= 0 ) - { - return; - } - - globalIndex const dofIndex = dofNumber[ei]; - localIndex const localRow = dofIndex - rankOffset; - real64 rhsValue; - - // 3.1. Apply pressure value to the matrix/rhs - FieldSpecificationEqual::SpecifyFieldValue( dofIndex, - rankOffset, - localMatrix, - rhsValue, - bcPres[ei], - pres[ei] ); - localRhs[localRow] = rhsValue; - - // 3.2. For each phase, apply target saturation value - for( integer ip = 0; ip < numPhase-1; ++ip ) - { - FieldSpecificationEqual::SpecifyFieldValue( dofIndex + ip + 1, - rankOffset, - localMatrix, - rhsValue, - bcPhaseVolFraction[ei][ip], - phaseVolFraction[ei][ip] ); - localRhs[localRow + ip + 1] = rhsValue; - } - } ); - } ); - } ); -} - -void ImmiscibleMultiphaseFlow::applySourceFluxBC( real64 const time, + { + // Check whether pressure has already been applied to this set + string const & subRegionName = subRegion.getName(); + string const & regionName = subRegion.getParent().getParent().getName(); + + auto & subRegionSetMap = bcPresCompStatusMap[regionName][subRegionName]; + if( subRegionSetMap.count( setName ) > 0 ) + { + bcConsistent = false; + GEOS_WARNING( BCMessage::pressureConflict( regionName, subRegionName, setName, + fields::flow::pressure::key() ) ); + } + subRegionSetMap[setName].setNumComp( m_numPhases ); + } ); + // 2. Check saturation Dirichlet BCs + fsManager.apply< ElementSubRegionBase >( time, + mesh, + fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key(), + [&] ( FieldSpecificationBase const & fs, + string const & setName, + SortedArrayView< localIndex const > const &, + ElementSubRegionBase & subRegion, + string const & ) + { + string const & subRegionName = subRegion.getName( ); + string const & regionName = subRegion.getParent().getParent().getName(); + integer const comp = fs.getComponent(); + + auto & subRegionSetMap = bcPresCompStatusMap[regionName][subRegionName]; + if( subRegionSetMap.count( setName ) == 0 ) + { + bcConsistent = false; + GEOS_WARNING( BCMessage::missingPressure( regionName, subRegionName, setName, + fields::flow::pressure::key() ) ); + } + if( comp < 0 || comp >= m_numPhases ) + { + bcConsistent = false; + GEOS_WARNING( BCMessage::invalidComponentIndex( comp, fs.getName(), + fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key() ) ); + return; // can't check next part with invalid component id + } + + ComponentMask< MAX_NP > & compMask = subRegionSetMap[setName]; + if( compMask[comp] ) + { + bcConsistent = false; + fsManager.forSubGroups< EquilibriumInitialCondition >( [&] ( EquilibriumInitialCondition const & bc ) + { + string_array const & componentNames = bc.getComponentNames(); + GEOS_WARNING( BCMessage::conflictingComposition( comp, componentNames[comp], + regionName, subRegionName, setName, + fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key() ) ); + } ); + } + compMask.set( comp ); + } ); + + // 3.2 Check consistency between composition BC applied to sets + // Note: for a temperature-only boundary condition, this loop does not do anything + for( auto const & regionEntry : bcPresCompStatusMap ) + { + for( auto const & subRegionEntry : regionEntry.second ) + { + for( auto const & setEntry : subRegionEntry.second ) + { + ComponentMask< MAX_NP > const & compMask = setEntry.second; + + fsManager.forSubGroups< EquilibriumInitialCondition >( [&] ( EquilibriumInitialCondition const & fs ) + { + string_array const & componentNames = fs.getComponentNames(); + for( size_t ic = 0; ic < componentNames.size(); ic++ ) + { + if( !compMask[ic] ) + { + bcConsistent = false; + GEOS_WARNING( BCMessage::notAppliedOnRegion( ic, componentNames[ic], + regionEntry.first, subRegionEntry.first, setEntry.first, + fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key() ) ); + } + } + } ); + } + } + } + } ); + + return bcConsistent; + } + + void ImmiscibleMultiphaseFlow::applyDirichletBC( real64 const time_n, real64 const dt, DofManager const & dofManager, DomainPartition & domain, CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) const -{ - GEOS_MARK_FUNCTION; - - FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); - - string const dofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); - - // Step 1: count individual source flux boundary conditions - - std::map< string, localIndex > bcNameToBcId; - localIndex bcCounter = 0; - - fsManager.forSubGroups< SourceFluxBoundaryCondition >( [&] ( SourceFluxBoundaryCondition const & bc ) - { - // collect all the bc names to idx - bcNameToBcId[bc.getName()] = bcCounter; - bcCounter++; - } ); - - if( bcCounter == 0 ) - { - return; - } - - // Step 2: count the set size for each source flux (each source flux may have multiple target sets) - - array1d< globalIndex > bcAllSetsSize( bcNameToBcId.size() ); - - computeSourceFluxSizeScalingFactor( time, - dt, - domain, - bcNameToBcId, - bcAllSetsSize.toView() ); - - // Step 3: we are ready to impose the boundary condition, normalized by the set size - - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel & mesh, - string_array const & ) - { - - fsManager.apply< ElementSubRegionBase, - SourceFluxBoundaryCondition >( time + dt, - mesh, - SourceFluxBoundaryCondition::catalogName(), - [&]( SourceFluxBoundaryCondition const & fs, - string const & setName, - SortedArrayView< localIndex const > const & targetSet, - ElementSubRegionBase & subRegion, - string const & ) - { - if( fs.getLogLevel() >= 1 && m_nonlinearSolverParameters.m_numNewtonIterations == 0 ) - { - globalIndex const numTargetElems = MpiWrapper::sum< globalIndex >( targetSet.size() ); - GEOS_LOG_RANK_0( GEOS_FMT( bcLogMessage, - getName(), time+dt, fs.getCatalogName(), fs.getName(), - setName, subRegion.getName(), fs.getScale(), numTargetElems ) ); - } - - if( targetSet.size() == 0 ) - { - return; - } - if( !subRegion.hasWrapper( dofKey ) ) - { - if( fs.getLogLevel() >= 1 ) - { - GEOS_LOG_RANK( GEOS_FMT( "{}: trying to apply SourceFlux, but its targetSet named '{}' intersects with non-simulated region named '{}'.", - getDataContext(), setName, subRegion.getName() ) ); - } - return; - } - - arrayView1d< globalIndex const > const dofNumber = subRegion.getReference< array1d< globalIndex > >( dofKey ); - arrayView1d< integer const > const ghostRank = subRegion.ghostRank(); - - // Step 3.1: get the values of the source boundary condition that need to be added to the rhs - - array1d< globalIndex > dofArray( targetSet.size() ); - array1d< real64 > rhsContributionArray( targetSet.size() ); - arrayView1d< real64 > rhsContributionArrayView = rhsContributionArray.toView(); - localIndex const rankOffset = dofManager.rankOffset(); - - RAJA::ReduceSum< parallelDeviceReduce, real64 > massProd( 0.0 ); - - // note that the dofArray will not be used after this step (simpler to use dofNumber instead) - fs.computeRhsContribution< FieldSpecificationAdd, - parallelDevicePolicy<> >( targetSet.toViewConst(), - time + dt, - dt, - subRegion, - dofNumber, - rankOffset, - localMatrix, - dofArray.toView(), - rhsContributionArrayView, - [] GEOS_HOST_DEVICE ( localIndex const ) - { - return 0.0; - } ); - - // Step 3.2: we are ready to add the right-hand side contributions, taking into account our equation layout - - // get the normalizer - real64 const sizeScalingFactor = bcAllSetsSize[bcNameToBcId.at( fs.getName())]; - integer const fluidPhaseId = fs.getComponent(); - integer const numFluidPhases = m_numPhases; - integer useTotalMassEquation = m_useTotalMassEquation; - forAll< parallelDevicePolicy<> >( targetSet.size(), [sizeScalingFactor, - targetSet, - rankOffset, - ghostRank, - fluidPhaseId, - numFluidPhases, - useTotalMassEquation, - dofNumber, - rhsContributionArrayView, - localRhs, - massProd] GEOS_HOST_DEVICE ( localIndex const a ) - { - // we need to filter out ghosts here, because targetSet may contain them - localIndex const ei = targetSet[a]; - if( ghostRank[ei] >= 0 ) - { - return; - } - - real64 const rhsValue = rhsContributionArrayView[a] / sizeScalingFactor; // scale the contribution by the sizeScalingFactor here! - massProd += rhsValue; - if( useTotalMassEquation > 0 ) - { - // for all "fluid components", we add the value to the total mass balance equation - globalIndex const totalMassBalanceRow = dofNumber[ei] - rankOffset; - localRhs[totalMassBalanceRow] += rhsValue; - if( fluidPhaseId < numFluidPhases - 1 ) - { - globalIndex const compMassBalanceRow = totalMassBalanceRow + fluidPhaseId + 1; // component mass bal equations are shifted - localRhs[compMassBalanceRow] += rhsValue; - } - } - else - { - globalIndex const compMassBalanceRow = dofNumber[ei] - rankOffset + fluidPhaseId; - localRhs[compMassBalanceRow] += rhsValue; - } - } ); - - SourceFluxStatsAggregator::forAllFluxStatWrappers( subRegion, fs.getName(), - [&]( SourceFluxStatsAggregator::WrappedStats & wrapper ) - { - // set the new sub-region statistics for this timestep - array1d< real64 > massProdArr{ m_numPhases }; - massProdArr[fluidPhaseId] = massProd.get(); - wrapper.gatherTimeStepStats( time, dt, massProdArr.toViewConst(), targetSet.size() ); - } ); - } ); - } ); -} - -real64 ImmiscibleMultiphaseFlow::calculateResidualNorm( real64 const & GEOS_UNUSED_PARAM( time_n ), - real64 const & GEOS_UNUSED_PARAM( dt ), - DomainPartition const & domain, - DofManager const & dofManager, - arrayView1d< real64 const > const & localRhs ) -{ - GEOS_MARK_FUNCTION; - array1d< real64 > localResidualNorm; - array1d< real64 > localResidualNormalizer; - localResidualNorm.resize( numNorm ); - localResidualNormalizer.resize( numNorm ); - - physicsSolverBaseKernels::NormType const normType = getNonlinearSolverParameters().normType(); - - globalIndex const rankOffset = dofManager.rankOffset(); - string const dofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); - - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel const & mesh, - string_array const & regionNames ) - { - mesh.getElemManager().forElementSubRegions( regionNames, - [&]( localIndex const, - ElementSubRegionBase const & subRegion ) - { - real64 subRegionResidualNorm[numNorm]{}; - real64 subRegionResidualNormalizer[numNorm]{}; - - string const & solidName = subRegion.getReference< string >( viewKeyStruct::solidNamesString() ); - CoupledSolidBase const & solid = getConstitutiveModel< CoupledSolidBase >( subRegion, solidName ); - - // step 1: compute the norm in the subRegion - - real64 subRegionFlowResidualNorm[1]{}; - real64 subRegionFlowResidualNormalizer[1]{}; - - immiscibleMultiphaseKernels:: - ResidualNormKernelFactory::createAndLaunch< parallelDevicePolicy<> >( normType, - 2, - rankOffset, - dofKey, - localRhs, - subRegion, - solid, - m_nonlinearSolverParameters.m_minNormalizer, - subRegionFlowResidualNorm, - subRegionFlowResidualNormalizer ); - subRegionResidualNorm[0] = subRegionFlowResidualNorm[0]; - subRegionResidualNormalizer[0] = subRegionFlowResidualNormalizer[0]; - - // step 2: first reduction across meshBodies/regions/subRegions - if( normType == physicsSolverBaseKernels::NormType::Linf ) - { - physicsSolverBaseKernels::LinfResidualNormHelper:: - updateLocalNorm< numNorm >( subRegionResidualNorm, localResidualNorm ); - } - else - { - physicsSolverBaseKernels::L2ResidualNormHelper:: - updateLocalNorm< numNorm >( subRegionResidualNorm, subRegionResidualNormalizer, localResidualNorm, localResidualNormalizer ); - } - } ); - } ); - - real64 residualNorm = 0.0; - residualNorm = localResidualNorm[0]; - if( normType == physicsSolverBaseKernels::NormType::Linf ) - { - physicsSolverBaseKernels::LinfResidualNormHelper::computeGlobalNorm( localResidualNorm[0], residualNorm ); - } - else - { - physicsSolverBaseKernels::L2ResidualNormHelper::computeGlobalNorm( localResidualNorm[0], localResidualNormalizer[0], residualNorm ); - } - - GEOS_LOG_LEVEL_RANK_0_NLR( logInfo::ResidualNorm, GEOS_FMT( " ( R{} ) = ( {:4.2e} )", - coupledSolverAttributePrefix(), residualNorm )) - - getConvergenceStats().setResidualValue( GEOS_FMT( "R{}", coupledSolverAttributePrefix()), residualNorm ); - - return residualNorm; -} - -void ImmiscibleMultiphaseFlow::applySystemSolution( DofManager const & dofManager, - arrayView1d< real64 const > const & localSolution, - real64 const scalingFactor, - real64 const dt, - DomainPartition & domain ) -{ - GEOS_UNUSED_VAR( dt ); - - DofManager::CompMask pressureMask( m_numDofPerCell, 0, 1 ); - - // 1. apply the pressure update - dofManager.addVectorToField( localSolution, - viewKeyStruct::elemDofFieldString(), - fields::flow::pressure::key(), - scalingFactor, - pressureMask ); - - // 2. apply the phaseVolumeFraction update - dofManager.addVectorToField( localSolution, - viewKeyStruct::elemDofFieldString(), - fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key(), - scalingFactor, - ~pressureMask ); - - // 3. synchronize - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, + { + GEOS_MARK_FUNCTION; + + // Only validate BC at the beginning of Newton loop + if( m_nonlinearSolverParameters.m_numNewtonIterations == 0 ) + { + bool const bcConsistent = validateDirichletBC( domain, time_n + dt ); + GEOS_ERROR_IF( !bcConsistent, GEOS_FMT( "ImmiscibleMultiphaseFlow {}: inconsistent boundary conditions", getDataContext() ) ); + } + + FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + string_array const & ) + { + + // 1. Apply pressure Dirichlet BCs, store in a separate field + applyFieldValue< ElementSubRegionBase >( time_n, dt, mesh, bcLogMessage, + fields::flow::pressure::key(), fields::flow::bcPressure::key() ); + // 2. Apply saturation BC (phase volume fraction) and store in a separate field + applyFieldValue< ElementSubRegionBase >( time_n, dt, mesh, bcLogMessage, + fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key(), + fields::immiscibleMultiphaseFlow::bcPhaseVolumeFraction::key() ); + + globalIndex const rankOffset = dofManager.rankOffset(); + string const dofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); + + // 3. Call constitutive update + fsManager.apply< ElementSubRegionBase >( time_n + dt, + mesh, + fields::flow::pressure::key(), + [&] ( FieldSpecificationBase const &, + string const &, + SortedArrayView< localIndex const > const & targetSet, + ElementSubRegionBase & subRegion, + string const & ) + { + + arrayView1d< real64 const > const bcPres = + subRegion.getReference< array1d< real64 > >( fields::flow::bcPressure::key() ); + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const bcPhaseVolFraction = + subRegion.getReference< array2d< real64, immiscibleFlow::LAYOUT_PHASE > >( + fields::immiscibleMultiphaseFlow::bcPhaseVolumeFraction::key() ); + + arrayView1d< integer const > const ghostRank = + subRegion.getReference< array1d< integer > >( ObjectManagerBase::viewKeyStruct::ghostRankString() ); + arrayView1d< globalIndex const > const dofNumber = + subRegion.getReference< array1d< globalIndex > >( dofKey ); + arrayView1d< real64 const > const pres = + subRegion.getReference< array1d< real64 > >( fields::flow::pressure::key() ); + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFraction = + subRegion.getReference< array2d< real64, immiscibleFlow::LAYOUT_PHASE > >( + fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key() ); + + integer const numPhase = m_numPhases; + + + forAll< parallelDevicePolicy<> >( targetSet.size(), [=] GEOS_HOST_DEVICE ( localIndex const a ) + { + localIndex const ei = targetSet[a]; + if( ghostRank[ei] >= 0 ) + { + return; + } + + globalIndex const dofIndex = dofNumber[ei]; + localIndex const localRow = dofIndex - rankOffset; + real64 rhsValue; + + // 3.1. Apply pressure value to the matrix/rhs + FieldSpecificationEqual::SpecifyFieldValue( dofIndex, + rankOffset, + localMatrix, + rhsValue, + bcPres[ei], + pres[ei] ); + localRhs[localRow] = rhsValue; + + // 3.2. For each phase, apply target saturation value + for( integer ip = 0; ip < numPhase-1; ++ip ) + { + FieldSpecificationEqual::SpecifyFieldValue( dofIndex + ip + 1, + rankOffset, + localMatrix, + rhsValue, + bcPhaseVolFraction[ei][ip], + phaseVolFraction[ei][ip] ); + localRhs[localRow + ip + 1] = rhsValue; + } + } ); + } ); + } ); + } + + void ImmiscibleMultiphaseFlow::applySourceFluxBC( real64 const time, + real64 const dt, + DofManager const & dofManager, + DomainPartition & domain, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) const + { + GEOS_MARK_FUNCTION; + + FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); + + string const dofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); + + // Step 1: count individual source flux boundary conditions + + std::map< string, localIndex > bcNameToBcId; + localIndex bcCounter = 0; + + fsManager.forSubGroups< SourceFluxBoundaryCondition >( [&] ( SourceFluxBoundaryCondition const & bc ) + { + // collect all the bc names to idx + bcNameToBcId[bc.getName()] = bcCounter; + bcCounter++; + } ); + + if( bcCounter == 0 ) + { + return; + } + + // Step 2: count the set size for each source flux (each source flux may have multiple target sets) + + array1d< globalIndex > bcAllSetsSize( bcNameToBcId.size() ); + + computeSourceFluxSizeScalingFactor( time, + dt, + domain, + bcNameToBcId, + bcAllSetsSize.toView() ); + + // Step 3: we are ready to impose the boundary condition, normalized by the set size + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, MeshLevel & mesh, + string_array const & ) + { + + fsManager.apply< ElementSubRegionBase, + SourceFluxBoundaryCondition >( time + dt, + mesh, + SourceFluxBoundaryCondition::catalogName(), + [&]( SourceFluxBoundaryCondition const & fs, + string const & setName, + SortedArrayView< localIndex const > const & targetSet, + ElementSubRegionBase & subRegion, + string const & ) + { + if( fs.getLogLevel() >= 1 && m_nonlinearSolverParameters.m_numNewtonIterations == 0 ) + { + globalIndex const numTargetElems = MpiWrapper::sum< globalIndex >( targetSet.size() ); + GEOS_LOG_RANK_0( GEOS_FMT( bcLogMessage, + getName(), time+dt, fs.getCatalogName(), fs.getName(), + setName, subRegion.getName(), fs.getScale(), numTargetElems ) ); + } + + if( targetSet.size() == 0 ) + { + return; + } + if( !subRegion.hasWrapper( dofKey ) ) + { + if( fs.getLogLevel() >= 1 ) + { + GEOS_LOG_RANK( GEOS_FMT( "{}: trying to apply SourceFlux, but its targetSet named '{}' intersects with non-simulated region named '{}'.", + getDataContext(), setName, subRegion.getName() ) ); + } + return; + } + + arrayView1d< globalIndex const > const dofNumber = subRegion.getReference< array1d< globalIndex > >( dofKey ); + arrayView1d< integer const > const ghostRank = subRegion.ghostRank(); + + // Step 3.1: get the values of the source boundary condition that need to be added to the rhs + + array1d< globalIndex > dofArray( targetSet.size() ); + array1d< real64 > rhsContributionArray( targetSet.size() ); + arrayView1d< real64 > rhsContributionArrayView = rhsContributionArray.toView(); + localIndex const rankOffset = dofManager.rankOffset(); + + RAJA::ReduceSum< parallelDeviceReduce, real64 > massProd( 0.0 ); + + // note that the dofArray will not be used after this step (simpler to use dofNumber instead) + fs.computeRhsContribution< FieldSpecificationAdd, + parallelDevicePolicy<> >( targetSet.toViewConst(), + time + dt, + dt, + subRegion, + dofNumber, + rankOffset, + localMatrix, + dofArray.toView(), + rhsContributionArrayView, + [] GEOS_HOST_DEVICE ( localIndex const ) + { + return 0.0; + } ); + + // Step 3.2: we are ready to add the right-hand side contributions, taking into account our equation layout + + // get the normalizer + real64 const sizeScalingFactor = bcAllSetsSize[bcNameToBcId.at( fs.getName())]; + integer const fluidPhaseId = fs.getComponent(); + integer const numFluidPhases = m_numPhases; + integer useTotalMassEquation = m_useTotalMassEquation; + forAll< parallelDevicePolicy<> >( targetSet.size(), [sizeScalingFactor, + targetSet, + rankOffset, + ghostRank, + fluidPhaseId, + numFluidPhases, + useTotalMassEquation, + dofNumber, + rhsContributionArrayView, + localRhs, + massProd] GEOS_HOST_DEVICE ( localIndex const a ) + { + // we need to filter out ghosts here, because targetSet may contain them + localIndex const ei = targetSet[a]; + if( ghostRank[ei] >= 0 ) + { + return; + } + + real64 const rhsValue = rhsContributionArrayView[a] / sizeScalingFactor; // scale the contribution by the sizeScalingFactor here! + massProd += rhsValue; + if( useTotalMassEquation > 0 ) + { + // for all "fluid components", we add the value to the total mass balance equation + globalIndex const totalMassBalanceRow = dofNumber[ei] - rankOffset; + localRhs[totalMassBalanceRow] += rhsValue; + if( fluidPhaseId < numFluidPhases - 1 ) + { + globalIndex const compMassBalanceRow = totalMassBalanceRow + fluidPhaseId + 1; // component mass bal equations are shifted + localRhs[compMassBalanceRow] += rhsValue; + } + } + else + { + globalIndex const compMassBalanceRow = dofNumber[ei] - rankOffset + fluidPhaseId; + localRhs[compMassBalanceRow] += rhsValue; + } + } ); + + SourceFluxStatsAggregator::forAllFluxStatWrappers( subRegion, fs.getName(), + [&]( SourceFluxStatsAggregator::WrappedStats & wrapper ) + { + // set the new sub-region statistics for this timestep + array1d< real64 > massProdArr{ m_numPhases }; + massProdArr[fluidPhaseId] = massProd.get(); + wrapper.gatherTimeStepStats( time, dt, massProdArr.toViewConst(), targetSet.size() ); + } ); + } ); + } ); + } + + real64 ImmiscibleMultiphaseFlow::calculateResidualNorm( real64 const & GEOS_UNUSED_PARAM( time_n ), + real64 const & GEOS_UNUSED_PARAM( dt ), + DomainPartition const & domain, + DofManager const & dofManager, + arrayView1d< real64 const > const & localRhs ) + { + GEOS_MARK_FUNCTION; + array1d< real64 > localResidualNorm; + array1d< real64 > localResidualNormalizer; + localResidualNorm.resize( numNorm ); + localResidualNormalizer.resize( numNorm ); + + physicsSolverBaseKernels::NormType const normType = getNonlinearSolverParameters().normType(); + + globalIndex const rankOffset = dofManager.rankOffset(); + string const dofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel const & mesh, string_array const & regionNames ) - { - stdVector< string > fields{ fields::flow::pressure::key(), fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key() }; - - FieldIdentifiers fieldsToBeSync; - fieldsToBeSync.addElementFields( fields, regionNames ); - - CommunicationTools::getInstance().synchronizeFields( fieldsToBeSync, mesh, domain.getNeighbors(), true ); - } ); -} - - -void ImmiscibleMultiphaseFlow::updateVolumeConstraint( ElementSubRegionBase & subRegion ) const -{ - GEOS_MARK_FUNCTION; - - arrayView2d< real64, immiscibleFlow::USD_PHASE > const phaseVolumeFraction = subRegion.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); - - forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const ei ) - { - phaseVolumeFraction[ei][1] = 1.0 - phaseVolumeFraction[ei][0]; - } ); -} - - -void ImmiscibleMultiphaseFlow::resetStateToBeginningOfStep( DomainPartition & domain ) -{ - GEOS_MARK_FUNCTION; - - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel & mesh, - string_array const & regionNames ) - { - mesh.getElemManager().forElementSubRegions< CellElementSubRegion, - SurfaceElementSubRegion >( regionNames, - [&]( localIndex const, - auto & subRegion ) - { - arrayView1d< real64 > const & pres = - subRegion.template getField< fields::flow::pressure >(); - arrayView1d< real64 const > const & pres_n = - subRegion.template getField< fields::flow::pressure_n >(); - pres.setValues< parallelDevicePolicy<> >( pres_n ); - - // after the update, save the new saturation - arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac_n = - subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction_n >(); - - arrayView2d< real64, immiscibleFlow::USD_PHASE > const phaseVolFrac = - subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); - phaseVolFrac.setValues< parallelDevicePolicy<> >( phaseVolFrac_n ); - - arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const & phaseMass_n = - subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseMass_n >(); - - arrayView2d< real64, immiscibleFlow::USD_PHASE > const & phaseMass = - subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseMass >(); - phaseMass.setValues< parallelDevicePolicy<> >( phaseMass_n ); - - if( m_isThermal ) - { - arrayView1d< real64 > const & temp = - subRegion.template getField< fields::flow::temperature >(); - arrayView1d< real64 const > const & temp_n = - subRegion.template getField< fields::flow::temperature_n >(); - temp.setValues< parallelDevicePolicy<> >( temp_n ); - } - - // update porosity, permeability - updatePorosityAndPermeability( subRegion ); - // update all fluid properties - updateFluidState( subRegion ); - } ); - } ); -} - -void ImmiscibleMultiphaseFlow::implicitStepComplete( real64 const & time, - real64 const & dt, + { + mesh.getElemManager().forElementSubRegions( regionNames, + [&]( localIndex const, + ElementSubRegionBase const & subRegion ) + { + real64 subRegionResidualNorm[numNorm]{}; + real64 subRegionResidualNormalizer[numNorm]{}; + + string const & solidName = subRegion.getReference< string >( viewKeyStruct::solidNamesString() ); + CoupledSolidBase const & solid = getConstitutiveModel< CoupledSolidBase >( subRegion, solidName ); + + // step 1: compute the norm in the subRegion + + real64 subRegionFlowResidualNorm[1]{}; + real64 subRegionFlowResidualNormalizer[1]{}; + + immiscibleMultiphaseKernels:: + ResidualNormKernelFactory::createAndLaunch< parallelDevicePolicy<> >( normType, + 2, + rankOffset, + dofKey, + localRhs, + subRegion, + solid, + m_nonlinearSolverParameters.m_minNormalizer, + subRegionFlowResidualNorm, + subRegionFlowResidualNormalizer ); + subRegionResidualNorm[0] = subRegionFlowResidualNorm[0]; + subRegionResidualNormalizer[0] = subRegionFlowResidualNormalizer[0]; + + // step 2: first reduction across meshBodies/regions/subRegions + if( normType == physicsSolverBaseKernels::NormType::Linf ) + { + physicsSolverBaseKernels::LinfResidualNormHelper:: + updateLocalNorm< numNorm >( subRegionResidualNorm, localResidualNorm ); + } + else + { + physicsSolverBaseKernels::L2ResidualNormHelper:: + updateLocalNorm< numNorm >( subRegionResidualNorm, subRegionResidualNormalizer, localResidualNorm, localResidualNormalizer ); + } + } ); + } ); + + real64 residualNorm = 0.0; + residualNorm = localResidualNorm[0]; + if( normType == physicsSolverBaseKernels::NormType::Linf ) + { + physicsSolverBaseKernels::LinfResidualNormHelper::computeGlobalNorm( localResidualNorm[0], residualNorm ); + } + else + { + physicsSolverBaseKernels::L2ResidualNormHelper::computeGlobalNorm( localResidualNorm[0], localResidualNormalizer[0], residualNorm ); + } + + if( getLogLevel() >= 1 && logger::internal::rank == 0 ) + { + std::cout << GEOS_FMT( " ( R{} ) = ( {:4.2e} )", coupledSolverAttributePrefix(), residualNorm ); + } + + return residualNorm; + } + + void ImmiscibleMultiphaseFlow::applySystemSolution( DofManager const & dofManager, + arrayView1d< real64 const > const & localSolution, + real64 const scalingFactor, + real64 const dt, DomainPartition & domain ) -{ - // Step 1: save the converged aquifer state - // note: we have to save the aquifer state **before** updating the pressure, - // otherwise the aquifer flux is saved with the wrong pressure time level - saveAquiferConvergedState( time, dt, domain ); - - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel & mesh, - string_array const & regionNames ) - { - mesh.getElemManager().forElementSubRegions( regionNames, - [&]( localIndex const, - ElementSubRegionBase & subRegion ) - { - // Step 3: save the converged solid state - string const & solidName = subRegion.getReference< string >( viewKeyStruct::solidNamesString() ); - CoupledSolidBase const & porousMaterial = getConstitutiveModel< CoupledSolidBase >( subRegion, solidName ); - if( m_keepVariablesConstantDuringInitStep ) - { - porousMaterial.ignoreConvergedState(); // newPorosity <- porosity_n - } - else - { - porousMaterial.saveConvergedState(); // porosity_n <- porosity - } - - // Step 4: save converged state for the relperm model to handle hysteresis - arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac = - subRegion.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); - string const & relPermName = subRegion.getReference< string >( viewKeyStruct::relPermNamesString() ); - RelativePermeabilityBase const & relPermMaterial = - getConstitutiveModel< RelativePermeabilityBase >( subRegion, relPermName ); - relPermMaterial.saveConvergedPhaseVolFractionState( phaseVolFrac ); - - // Step 5: if capillary pressure is supported, send the converged porosity and permeability to the capillary pressure model - // note: this is needed when the capillary pressure depends on porosity and permeability (Leverett J-function for instance) - if( m_hasCapPressure ) - { - arrayView2d< real64 const > const porosity = porousMaterial.getPorosity(); - - string const & permName = subRegion.getReference< string >( viewKeyStruct::permeabilityNamesString() ); - PermeabilityBase const & permeabilityMaterial = - getConstitutiveModel< PermeabilityBase >( subRegion, permName ); - arrayView3d< real64 const > const permeability = permeabilityMaterial.permeability(); - - string const & capPressName = subRegion.getReference< string >( viewKeyStruct::capPressureNamesString() ); - CapillaryPressureBase const & capPressureMaterial = - getConstitutiveModel< CapillaryPressureBase >( subRegion, capPressName ); - capPressureMaterial.saveConvergedRockState( porosity, permeability ); - } - } ); - } ); - -} - -void ImmiscibleMultiphaseFlow::saveConvergedState( ElementSubRegionBase & subRegion ) const -{ - FlowSolverBase::saveConvergedState( subRegion ); - - arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac = - subRegion.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); - arrayView2d< real64, immiscibleFlow::USD_PHASE > const phaseVolFrac_n = - subRegion.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction_n >(); - phaseVolFrac_n.setValues< parallelDevicePolicy<> >( phaseVolFrac ); - - arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseMass = - subRegion.getField< fields::immiscibleMultiphaseFlow::phaseMass >(); - arrayView2d< real64, immiscibleFlow::USD_PHASE > const phaseMass_n = - subRegion.getField< fields::immiscibleMultiphaseFlow::phaseMass_n >(); - phaseMass_n.setValues< parallelDevicePolicy<> >( phaseMass ); - -} - -void ImmiscibleMultiphaseFlow::updateState( DomainPartition & domain ) -{ - GEOS_MARK_FUNCTION; - - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel & mesh, - string_array const & regionNames ) - { - mesh.getElemManager().forElementSubRegions< CellElementSubRegion, - SurfaceElementSubRegion >( regionNames, [&]( localIndex const, - auto & subRegion ) - { - // update porosity, permeability, and solid internal energy - updatePorosityAndPermeability( subRegion ); - // update all fluid properties - updateVolumeConstraint( subRegion ); - updateFluidState( subRegion ); - } ); - } ); -} - -real64 ImmiscibleMultiphaseFlow::setNextDtBasedOnStateChange( real64 const & currentDt, - DomainPartition & domain ) -{ - if( m_targetRelativePresChange >= 1.0 && - m_targetPhaseVolFracChange >= 1.0 ) - { - return LvArray::NumericLimits< real64 >::max; - } - - real64 maxRelativePresChange = 0.0; - real64 maxAbsolutePhaseVolFracChange = 0.0; - - integer const numPhase = m_numPhases; - - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel & mesh, - string_array const & regionNames ) - { - mesh.getElemManager().forElementSubRegions( regionNames, - [&]( localIndex const, - ElementSubRegionBase & subRegion ) - { - arrayView1d< integer const > const ghostRank = subRegion.ghostRank(); - - arrayView1d< real64 const > const pres = subRegion.getField< fields::flow::pressure >(); - arrayView1d< real64 const > const pres_n = subRegion.getField< fields::flow::pressure_n >(); - arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac = - subRegion.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); - arrayView2d< real64, immiscibleFlow::USD_PHASE > const phaseVolFrac_n = - subRegion.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction_n >(); - - RAJA::ReduceMax< parallelDeviceReduce, real64 > subRegionMaxPresChange( 0.0 ); - RAJA::ReduceMax< parallelDeviceReduce, real64 > subRegionMaxPhaseVolFracChange( 0.0 ); - - forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const ei ) - { - if( ghostRank[ei] < 0 ) - { - // switch from relative to absolute when values less than 1 - subRegionMaxPresChange.max( LvArray::math::abs( pres[ei] - pres_n[ei] ) / LvArray::math::max( LvArray::math::abs( pres_n[ei] ), 1.0 ) ); - for( integer ip = 0; ip < numPhase; ++ip ) - { - subRegionMaxPhaseVolFracChange.max( LvArray::math::abs( phaseVolFrac[ei][ip] - phaseVolFrac_n[ei][ip] ) ); - } - } - } ); - - maxRelativePresChange = LvArray::math::max( maxRelativePresChange, subRegionMaxPresChange.get() ); - maxAbsolutePhaseVolFracChange = LvArray::math::max( maxAbsolutePhaseVolFracChange, subRegionMaxPhaseVolFracChange.get() ); - - } ); - } ); - - maxRelativePresChange = MpiWrapper::max( maxRelativePresChange ); - maxAbsolutePhaseVolFracChange = MpiWrapper::max( maxAbsolutePhaseVolFracChange ); - - GEOS_LOG_LEVEL_RANK_0( logInfo::TimeStep, GEOS_FMT( "{}: max relative pressure change during time step = {} %", - getName(), GEOS_FMT( "{:.{}f}", 100*maxRelativePresChange, 3 ) ) ); - GEOS_LOG_LEVEL_RANK_0( logInfo::TimeStep, GEOS_FMT( "{}: max absolute phase volume fraction change during time step = {}", - getName(), GEOS_FMT( "{:.{}f}", maxAbsolutePhaseVolFracChange, 3 ) ) ); - - real64 const eps = LvArray::NumericLimits< real64 >::epsilon; - - real64 const nextDtPressure = currentDt * ( 1.0 + m_solutionChangeScalingFactor ) * m_targetRelativePresChange - / std::max( eps, maxRelativePresChange + m_solutionChangeScalingFactor * m_targetRelativePresChange ); - if( m_nonlinearSolverParameters.getLogLevel() > 0 ) - GEOS_LOG_RANK_0( GEOS_FMT( "{}: next time step based on pressure change = {}", getName(), nextDtPressure )); - real64 const nextDtPhaseVolFrac = currentDt * ( 1.0 + m_solutionChangeScalingFactor ) * m_targetPhaseVolFracChange - / std::max( eps, maxAbsolutePhaseVolFracChange + m_solutionChangeScalingFactor * m_targetPhaseVolFracChange ); - if( m_nonlinearSolverParameters.getLogLevel() > 0 ) - GEOS_LOG_RANK_0( GEOS_FMT( "{}: next time step based on phase volume fraction change = {}", getName(), nextDtPhaseVolFrac )); - - return std::min( nextDtPressure, nextDtPhaseVolFrac ); - -} - -REGISTER_CATALOG_ENTRY( PhysicsSolverBase, ImmiscibleMultiphaseFlow, string const &, Group * const ) - -} // namespace geos + { + GEOS_UNUSED_VAR( dt ); + + DofManager::CompMask pressureMask( m_numDofPerCell, 0, 1 ); + + // 1. apply the pressure update + dofManager.addVectorToField( localSolution, + viewKeyStruct::elemDofFieldString(), + fields::flow::pressure::key(), + scalingFactor, + pressureMask ); + + // 2. apply the phaseVolumeFraction update + dofManager.addVectorToField( localSolution, + viewKeyStruct::elemDofFieldString(), + fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key(), + scalingFactor, + ~pressureMask ); + + // 3. synchronize + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + std::vector< string > fields{ fields::flow::pressure::key(), fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key() }; + + FieldIdentifiers fieldsToBeSync; + fieldsToBeSync.addElementFields( fields, regionNames ); + + CommunicationTools::getInstance().synchronizeFields( fieldsToBeSync, mesh, domain.getNeighbors(), true ); + } ); + } + + + void ImmiscibleMultiphaseFlow::updateVolumeConstraint( ElementSubRegionBase & subRegion ) const + { + GEOS_MARK_FUNCTION; + + arrayView2d< real64, immiscibleFlow::USD_PHASE > const phaseVolumeFraction = subRegion.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); + + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const ei ) + { + phaseVolumeFraction[ei][0] = fmin( 1.0, fmax( phaseVolumeFraction[ei][0], 0.0 )); ; + phaseVolumeFraction[ei][1] = 1.0 - phaseVolumeFraction[ei][0]; + } ); + } + + + void ImmiscibleMultiphaseFlow::resetStateToBeginningOfStep( DomainPartition & domain ) + { + GEOS_MARK_FUNCTION; + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + mesh.getElemManager().forElementSubRegions< CellElementSubRegion, + SurfaceElementSubRegion >( regionNames, + [&]( localIndex const, + auto & subRegion ) + { + arrayView1d< real64 > const & pres = + subRegion.template getField< fields::flow::pressure >(); + arrayView1d< real64 const > const & pres_n = + subRegion.template getField< fields::flow::pressure_n >(); + pres.setValues< parallelDevicePolicy<> >( pres_n ); + + // after the update, save the new saturation + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac_n = + subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction_n >(); + + arrayView2d< real64, immiscibleFlow::USD_PHASE > const phaseVolFrac = + subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); + phaseVolFrac.setValues< parallelDevicePolicy<> >( phaseVolFrac_n ); + + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const & phaseMass_n = + subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseMass_n >(); + + arrayView2d< real64, immiscibleFlow::USD_PHASE > const & phaseMass = + subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseMass >(); + phaseMass.setValues< parallelDevicePolicy<> >( phaseMass_n ); + + if( m_isThermal ) + { + arrayView1d< real64 > const & temp = + subRegion.template getField< fields::flow::temperature >(); + arrayView1d< real64 const > const & temp_n = + subRegion.template getField< fields::flow::temperature_n >(); + temp.setValues< parallelDevicePolicy<> >( temp_n ); + } + + // update porosity, permeability + updatePorosityAndPermeability( subRegion ); + // update all fluid properties + updateFluidState( subRegion ); + } ); + } ); + } + + void ImmiscibleMultiphaseFlow::implicitStepComplete( real64 const & time, + real64 const & dt, + DomainPartition & domain ) + { + // Step 1: save the converged aquifer state + // note: we have to save the aquifer state **before** updating the pressure, + // otherwise the aquifer flux is saved with the wrong pressure time level + saveAquiferConvergedState( time, dt, domain ); + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + mesh.getElemManager().forElementSubRegions( regionNames, + [&]( localIndex const, + ElementSubRegionBase & subRegion ) + { + // Step 3: save the converged solid state + string const & solidName = subRegion.getReference< string >( viewKeyStruct::solidNamesString() ); + CoupledSolidBase const & porousMaterial = getConstitutiveModel< CoupledSolidBase >( subRegion, solidName ); + if( m_keepVariablesConstantDuringInitStep ) + { + porousMaterial.ignoreConvergedState(); // newPorosity <- porosity_n + } + else + { + porousMaterial.saveConvergedState(); // porosity_n <- porosity + } + + // Step 4: save converged state for the relperm model to handle hysteresis + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac = + subRegion.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); + string const & relPermName = subRegion.getReference< string >( viewKeyStruct::relPermNamesString() ); + RelativePermeabilityBase const & relPermMaterial = + getConstitutiveModel< RelativePermeabilityBase >( subRegion, relPermName ); + relPermMaterial.saveConvergedPhaseVolFractionState( phaseVolFrac ); + + // Step 5: if capillary pressure is supported, send the converged porosity and permeability to the capillary pressure model + // note: this is needed when the capillary pressure depends on porosity and permeability (Leverett J-function for instance) + if( m_hasCapPressure ) + { + arrayView2d< real64 const > const porosity = porousMaterial.getPorosity(); + + string const & permName = subRegion.getReference< string >( viewKeyStruct::permeabilityNamesString() ); + PermeabilityBase const & permeabilityMaterial = + getConstitutiveModel< PermeabilityBase >( subRegion, permName ); + arrayView3d< real64 const > const permeability = permeabilityMaterial.permeability(); + + string const & capPressName = subRegion.getReference< string >( viewKeyStruct::capPressureNamesString() ); + CapillaryPressureBase const & capPressureMaterial = + getConstitutiveModel< CapillaryPressureBase >( subRegion, capPressName ); + capPressureMaterial.saveConvergedRockState( porosity, permeability ); + } + } ); + } ); + } + + void ImmiscibleMultiphaseFlow::saveConvergedState( ElementSubRegionBase & subRegion ) const + { + FlowSolverBase::saveConvergedState( subRegion ); + + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac = + subRegion.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); + arrayView2d< real64, immiscibleFlow::USD_PHASE > const phaseVolFrac_n = + subRegion.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction_n >(); + phaseVolFrac_n.setValues< parallelDevicePolicy<> >( phaseVolFrac ); + + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseMass = + subRegion.getField< fields::immiscibleMultiphaseFlow::phaseMass >(); + arrayView2d< real64, immiscibleFlow::USD_PHASE > const phaseMass_n = + subRegion.getField< fields::immiscibleMultiphaseFlow::phaseMass_n >(); + phaseMass_n.setValues< parallelDevicePolicy<> >( phaseMass ); + + } + + void ImmiscibleMultiphaseFlow::updateState( DomainPartition & domain ) + { + GEOS_MARK_FUNCTION; + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + mesh.getElemManager().forElementSubRegions< CellElementSubRegion, + SurfaceElementSubRegion >( regionNames, [&]( localIndex const, + auto & subRegion ) + { + // update porosity, permeability, and solid internal energy + updatePorosityAndPermeability( subRegion ); + // update all fluid properties + updateVolumeConstraint( subRegion ); + updateFluidState( subRegion ); + } ); + } ); + } + + real64 ImmiscibleMultiphaseFlow::setNextDtBasedOnStateChange( real64 const & currentDt, + DomainPartition & domain ) + { + if( m_targetRelativePresChange >= 1.0 && + m_targetPhaseVolFracChange >= 1.0 ) + { + return LvArray::NumericLimits< real64 >::max; + } + + real64 maxRelativePresChange = 0.0; + real64 maxAbsolutePhaseVolFracChange = 0.0; + + integer const numPhase = m_numPhases; + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + mesh.getElemManager().forElementSubRegions( regionNames, + [&]( localIndex const, + ElementSubRegionBase & subRegion ) + { + arrayView1d< integer const > const ghostRank = subRegion.ghostRank(); + + arrayView1d< real64 const > const pres = subRegion.getField< fields::flow::pressure >(); + arrayView1d< real64 const > const pres_n = subRegion.getField< fields::flow::pressure_n >(); + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac = + subRegion.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); + arrayView2d< real64, immiscibleFlow::USD_PHASE > const phaseVolFrac_n = + subRegion.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction_n >(); + + RAJA::ReduceMax< parallelDeviceReduce, real64 > subRegionMaxPresChange( 0.0 ); + RAJA::ReduceMax< parallelDeviceReduce, real64 > subRegionMaxPhaseVolFracChange( 0.0 ); + + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const ei ) + { + if( ghostRank[ei] < 0 ) + { + // switch from relative to absolute when values less than 1 + subRegionMaxPresChange.max( LvArray::math::abs( pres[ei] - pres_n[ei] ) / LvArray::math::max( LvArray::math::abs( pres_n[ei] ), 1.0 ) ); + for( integer ip = 0; ip < numPhase; ++ip ) + { + subRegionMaxPhaseVolFracChange.max( LvArray::math::abs( phaseVolFrac[ei][ip] - phaseVolFrac_n[ei][ip] ) ); + } + } + } ); + + maxRelativePresChange = LvArray::math::max( maxRelativePresChange, subRegionMaxPresChange.get() ); + maxAbsolutePhaseVolFracChange = LvArray::math::max( maxAbsolutePhaseVolFracChange, subRegionMaxPhaseVolFracChange.get() ); + + } ); + } ); + + maxRelativePresChange = MpiWrapper::max( maxRelativePresChange ); + maxAbsolutePhaseVolFracChange = MpiWrapper::max( maxAbsolutePhaseVolFracChange ); + + GEOS_LOG_LEVEL_RANK_0( logInfo::TimeStep, GEOS_FMT( "{}: max relative pressure change during time step = {} %", + getName(), GEOS_FMT( "{:.{}f}", 100*maxRelativePresChange, 3 ) ) ); + GEOS_LOG_LEVEL_RANK_0( logInfo::TimeStep, GEOS_FMT( "{}: max absolute phase volume fraction change during time step = {}", + getName(), GEOS_FMT( "{:.{}f}", maxAbsolutePhaseVolFracChange, 3 ) ) ); + + real64 const eps = LvArray::NumericLimits< real64 >::epsilon; + + real64 const nextDtPressure = currentDt * ( 1.0 + m_solutionChangeScalingFactor ) * m_targetRelativePresChange + / std::max( eps, maxRelativePresChange + m_solutionChangeScalingFactor * m_targetRelativePresChange ); + if( m_nonlinearSolverParameters.getLogLevel() > 0 ) + GEOS_LOG_RANK_0( GEOS_FMT( "{}: next time step based on pressure change = {}", getName(), nextDtPressure )); + real64 const nextDtPhaseVolFrac = currentDt * ( 1.0 + m_solutionChangeScalingFactor ) * m_targetPhaseVolFracChange + / std::max( eps, maxAbsolutePhaseVolFracChange + m_solutionChangeScalingFactor * m_targetPhaseVolFracChange ); + if( m_nonlinearSolverParameters.getLogLevel() > 0 ) + GEOS_LOG_RANK_0( GEOS_FMT( "{}: next time step based on phase volume fraction change = {}", getName(), nextDtPhaseVolFrac )); + + return std::min( nextDtPressure, nextDtPhaseVolFrac ); + + } + + REGISTER_CATALOG_ENTRY( PhysicsSolverBase, ImmiscibleMultiphaseFlow, string const &, Group * const ) + + } // namespace geos + diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp index 25399a7ebc8..37b67a7852c 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp @@ -38,7 +38,7 @@ #include "constitutive/relativePermeability/RelativePermeabilityBase.hpp" #include "constitutive/relativePermeability/RelativePermeabilityFields.hpp" #include "constitutive/ConstitutiveManager.hpp" -#include "constitutive/capillaryPressure/capillaryPressureSelector.hpp" +#include "constitutive/capillaryPressure/CapillaryPressureSelector.hpp" #include "constitutive/relativePermeability/RelativePermeabilitySelector.hpp" #include "constitutive/ConstitutivePassThru.hpp" @@ -959,11 +959,11 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< dC1_dS[ip][ke] = dC_dS_term1 + dC_dS_term2 * dC_dS_term3; dhalfFlux1_dP[ip][ke] -= dC_dP; dhalfFlux1_dS[ip][ke] -= dC1_dS[ip][ke]; - // if (std::fabs(facePhaseVolFrac1[0][0] - 1.0) > 1e-8){ + if (std::fabs(facePhaseVolFrac1[0][0] - 1.0) > 1e-8){ dC1_dpc[ip][ke] = dC1_dS[ip][ke] * dfacePhaseVolFrac_dCapPres1[0][0][0][0]; - // } else { - // dC1_dpc[ip][ke] = dC_dS_term1 * dfacePhaseVolFrac_dCapPres1[0][0][0][0]; - // } + } else { + dC1_dpc[ip][ke] = dC_dS_term1 * dfacePhaseVolFrac_dCapPres1[0][0][0][0]; + } // GEOS_UNUSED_VAR( dC1_dpc[ip][ke] ); } @@ -972,11 +972,11 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< dC2_dS[ip][ke] = dC_dS_term1 + dC_dS_term2 * dC_dS_term3; dhalfFlux2_dP[ip][ke] -= dC_dP; dhalfFlux2_dS[ip][ke] -= dC2_dS[ip][ke]; - // if (std::fabs(facePhaseVolFrac2[0][0] - 1.0) > 1e-8){ + if (std::fabs(facePhaseVolFrac2[0][0] - 1.0) > 1e-8){ dC2_dpc[ip][ke] = dC2_dS[ip][ke] * dfacePhaseVolFrac_dCapPres2[0][0][0][0]; - // } else { - // dC2_dpc[ip][ke] = dC_dS_term1 * dfacePhaseVolFrac_dCapPres2[0][0][0][0]; - // } + } else { + dC2_dpc[ip][ke] = dC_dS_term1 * dfacePhaseVolFrac_dCapPres2[0][0][0][0]; + } // GEOS_UNUSED_VAR( dC2_dpc[ip][ke] ); } @@ -1040,7 +1040,7 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< } else { - if( std::fabs( halfFluxVal[ip][0] ) < 1e-20 ) + if( std::fabs( halfFluxVal[ip][0] ) < 1e-20 ) { k_up_0_check[ip] = k_up_0_b; } @@ -1106,6 +1106,9 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< // Check convergence if( std::fabs( local_residual ) < tol ) { + // if( std::fabs( dhalfFlux_dpc[0][0] - dhalfFlux_dpc[0][1] ) saturations, stdVector< real64 deltaPc = local_residual/local_jacobian; - // if (std::fabs(facePhaseVolFrac1[0][0] - 1.0) < 1e-5 && (std::fabs(deltaPc * dfacePhaseVolFrac_dCapPres2[0][0][0][0]) < 0.05)){ - // ext_iter0++; - // } - // if (std::fabs(facePhaseVolFrac2[0][0] - 1.0) < 1e-5 && (std::fabs(deltaPc * dfacePhaseVolFrac_dCapPres1[0][0][0][0]) < 0.05)){ - // ext_iter1++; - // } - - // if (ext_iter0 > 20){ - // halfFluxVal[0][1] = halfFluxVal[0][0]; - // halfFluxVal[1][1] = halfFluxVal[1][0]; - // local_residual = halfFluxVal[0][0] - halfFluxVal[0][1]; - // } - - // if (ext_iter1 > 20){ - // halfFluxVal[0][0] = halfFluxVal[0][1]; - // halfFluxVal[1][0] = halfFluxVal[1][1]; - // local_residual = halfFluxVal[0][0] - halfFluxVal[0][1]; - // } - if( std::fabs( local_residual ) < tol ) { + // if( std::fabs( dhalfFlux_dpc[0][0] - dhalfFlux_dpc[0][1] ) < eps2 ) { + // std::cout << "**********************ZeroJacobian*******************" << std::endl; + // } converged = 1; break; // Converged } @@ -1351,10 +1338,11 @@ class FluxComputeKernelBase fields::twophaseimmisciblefluid::dPhaseViscosity >; using CapPressureAccessors = - StencilMaterialAccessors< JFunctionCapillaryPressure, + StencilMaterialAccessors< BrooksCoreyCapillaryPressure, fields::cappres::phaseCapPressure, - fields::cappres::dPhaseCapPressure_dPhaseVolFraction, - fields::cappres::jFuncMultiplier >; + fields::cappres::dPhaseCapPressure_dPhaseVolFraction + >; + // ,fields::cappres::jFuncMultiplier >; using PermeabilityAccessors = @@ -1411,7 +1399,7 @@ class FluxComputeKernelBase m_dVisc_dPres( fluidAccessors.get( fields::twophaseimmisciblefluid::dPhaseViscosity {} ) ), m_phaseCapPressure( capPressureAccessors.get( fields::cappres::phaseCapPressure {} ) ), m_dPhaseCapPressure_dPhaseVolFrac( capPressureAccessors.get( fields::cappres::dPhaseCapPressure_dPhaseVolFraction {} ) ), - m_jFuncMultiplier( capPressureAccessors.get( fields::cappres::jFuncMultiplier {} ) ), + // m_jFuncMultiplier( capPressureAccessors.get( fields::cappres::jFuncMultiplier {} ) ), m_localMatrix( localMatrix ), m_localRhs( localRhs ), m_hasCapPressure ( hasCapPressure ), @@ -1460,7 +1448,7 @@ class FluxComputeKernelBase /// Views on capillary pressure ElementViewConst< arrayView3d< real64 const, cappres::USD_CAPPRES > > const m_phaseCapPressure; ElementViewConst< arrayView4d< real64 const, cappres::USD_CAPPRES_DS > > const m_dPhaseCapPressure_dPhaseVolFrac; - ElementViewConst< arrayView2d< real64 const > > const m_jFuncMultiplier; + // ElementViewConst< arrayView2d< real64 const > > const m_jFuncMultiplier; // Residual and jacobian @@ -2029,7 +2017,8 @@ class FluxComputeKernel : public FluxComputeKernelBase * @tparam RELPERMWRAPPER the type of the realtive permeability wrapper * @brief Define the interface for the assembly kernel in charge of flux terms */ -template< integer NUM_EQN, integer NUM_DOF, typename STENCILWRAPPER, typename CAPPRESWRAPPER, typename RELPERMWRAPPER > +// template< integer NUM_EQN, integer NUM_DOF, typename STENCILWRAPPER, typename CAPPRESWRAPPER, typename RELPERMWRAPPER > +template< integer NUM_EQN, integer NUM_DOF, typename STENCILWRAPPER > class FluxComputeInterfaceConditionKernel : public FluxComputeKernel< NUM_EQN, NUM_DOF, STENCILWRAPPER > { public: @@ -2057,7 +2046,7 @@ class FluxComputeInterfaceConditionKernel : public FluxComputeKernel< NUM_EQN, N using Base::m_phaseVolFrac; using Base::m_phaseMass_n; using Base::m_phaseCapPressure; - using Base::m_jFuncMultiplier; + // using Base::m_jFuncMultiplier; using Base::m_dPhaseCapPressure_dPhaseVolFrac; using Base::m_dens; using Base::m_dDens_dPres; @@ -2096,8 +2085,8 @@ class FluxComputeInterfaceConditionKernel : public FluxComputeKernel< NUM_EQN, N FluxComputeInterfaceConditionKernel( integer const numPhases, globalIndex const rankOffset, STENCILWRAPPER const & stencilWrapper, - CAPPRESWRAPPER const & capPressureWrapper, - RELPERMWRAPPER const & relPermWrapper, + // CAPPRESWRAPPER const & capPressureWrapper, + // RELPERMWRAPPER const & relPermWrapper, DofNumberAccessor const & dofNumberAccessor, ImmiscibleMultiphaseFlowAccessors const & multiPhaseFlowAccessors, MultiphaseFluidAccessors const & fluidAccessors, @@ -2114,9 +2103,9 @@ class FluxComputeInterfaceConditionKernel : public FluxComputeKernel< NUM_EQN, N constitutive::CapillaryPressureBase *, constitutive::TwoPhaseImmiscibleFluid * >, 2 > > const & interfaceConstitutivePairs, unordered_map< localIndex, localIndex > const & interfaceRegionByConnector, - std::tuple< constitutive::RelativePermeabilityBase *, - constitutive::CapillaryPressureBase *, - constitutive::TwoPhaseImmiscibleFluid * > const & interfaceConstitutivePairs_temp, + // std::tuple< constitutive::RelativePermeabilityBase *, + // constitutive::CapillaryPressureBase *, + // constitutive::TwoPhaseImmiscibleFluid * > const & interfaceConstitutivePairs_temp, localIndex const GEOS_UNUSED_PARAM( domainSize ) ) : Base( numPhases, rankOffset, @@ -2132,12 +2121,13 @@ class FluxComputeInterfaceConditionKernel : public FluxComputeKernel< NUM_EQN, N hasCapPressure, useTotalMassEquation, checkPhasePresenceInGravity ), - m_capPressureWrapper( capPressureWrapper ), - m_relPermWrapper( relPermWrapper ), + // m_capPressureWrapper( capPressureWrapper ), + // m_relPermWrapper( relPermWrapper ), m_interfaceFaceSetNames( interfaceFaceSetNames ), m_interfaceConstitutivePairs( interfaceConstitutivePairs ), - m_interfaceRegionByConnector( interfaceRegionByConnector ), - m_interfaceConstitutivePairs_temp( interfaceConstitutivePairs_temp ) + m_interfaceRegionByConnector( interfaceRegionByConnector ) + // , + // m_interfaceConstitutivePairs_temp( interfaceConstitutivePairs_temp ) {} /** @@ -2163,6 +2153,7 @@ class FluxComputeInterfaceConditionKernel : public FluxComputeKernel< NUM_EQN, N } + // if (connectorHasInterfaceConditionQ){ // // Improved transmission conditions // int ammar_code = 0; @@ -2204,7 +2195,7 @@ class FluxComputeInterfaceConditionKernel : public FluxComputeKernel< NUM_EQN, N real64 dGravHead_dP[numEqn][2]{}; real64 capGrad[numEqn]{}; - real64 capPresIC[numEqn][2]{}; + // real64 capPresIC[numEqn][2]{}; real64 jFMultiplier[numEqn][2]{}; real64 dCapGrad_dP[numEqn][2]{}; real64 dCapGrad_dS[numEqn][2]{}; @@ -2245,7 +2236,7 @@ class FluxComputeInterfaceConditionKernel : public FluxComputeKernel< NUM_EQN, N stdVector< real64 > saturations = {m_phaseVolFrac[seri[0]][sesri[0]][sei[0]][0], m_phaseVolFrac[seri[1]][sesri[1]][sei[1]][0] }; stdVector< real64 > pressures = {m_pres[seri[0]][sesri[0]][sei[0]], m_pres[seri[1]][sesri[1]][sei[1]] }; - bool isJfunction = 1; + bool isJfunction = 0; // loop over phases for( integer ip = 0; ip < m_numPhases; ++ip ) @@ -2318,9 +2309,9 @@ class FluxComputeInterfaceConditionKernel : public FluxComputeKernel< NUM_EQN, N if( m_hasCapPressure ) // check sign convention { real64 const capPres = m_phaseCapPressure[er][esr][ei][0][ip]; // Pc = Pc1 || Pc2 - jFMultiplier[ip][ke] = m_jFuncMultiplier[er][esr][ei][0]; + // jFMultiplier[ip][ke] = m_jFuncMultiplier[er][esr][ei][0]; - capPresIC[ip][ke] = capPres; + // capPresIC[ip][ke] = capPres; dCapGrad_dTrans -= signPotDiff[ke] * capPres; // dDPc/dT = (-Pc1 + Pc2) pot -= trans[ke] * capPres; // Phi = T P1 - rho T g z1 - T Pc1 || -T P2 + rho T g z2 + T // Pc2 @@ -2479,8 +2470,8 @@ class FluxComputeInterfaceConditionKernel : public FluxComputeKernel< NUM_EQN, N // this determines whether the local solver is needed becuase of heterogeneous capillary pressure regions - bool notOnInterface = std::fabs( jFMultiplier[0][0] - jFMultiplier[0][1] ) < 1 && std::fabs( jFMultiplier[1][0] - jFMultiplier[1][1] ) < 1; - notOnInterface = !connectorHasInterfaceConditionQ; + // bool notOnInterface = std::fabs( jFMultiplier[0][0] - jFMultiplier[0][1] ) < 1 && std::fabs( jFMultiplier[1][0] - jFMultiplier[1][1] ) < 1; + bool notOnInterface = !connectorHasInterfaceConditionQ; if( notOnInterface ) { for( integer ip = 0; ip < 2; ++ip ) @@ -2510,66 +2501,9 @@ class FluxComputeInterfaceConditionKernel : public FluxComputeKernel< NUM_EQN, N else { - // nonlinear solver's parameters - real64 tol = 1.0e-9; - int max_iter = 50; - bool converged = 0; - bool damping = true; - - // Local newton loop: - // Use of the capillary pressure kernel wrapper - StackArray< real64, 2, 2, immiscibleFlow::LAYOUT_PHASE > facePhaseVolFrac1( 1, 2 ); - StackArray< real64, 3, 2, constitutive::cappres::LAYOUT_CAPPRES > faceCapPres1( 1, 1, 2 ); - StackArray< real64, 4, 4, constitutive::cappres::LAYOUT_CAPPRES_DS > dfacePhaseVolFrac_dCapPres1( 1, 1, 2, 2 ); - StackArray< real64, 4, 4, constitutive::cappres::LAYOUT_CAPPRES_DS > dCapPres1_dfacePhaseVolFrac( 1, 1, 2, 2 ); - StackArray< real64, 2, 2, immiscibleFlow::LAYOUT_PHASE > facePhaseVolFrac2( 1, 2 ); - StackArray< real64, 3, 2, constitutive::cappres::LAYOUT_CAPPRES > faceCapPres2( 1, 1, 2 ); - StackArray< real64, 4, 4, constitutive::cappres::LAYOUT_CAPPRES_DS > dfacePhaseVolFrac_dCapPres2( 1, 1, 2, 2 ); - StackArray< real64, 4, 4, constitutive::cappres::LAYOUT_CAPPRES_DS > dCapPres2_dfacePhaseVolFrac( 1, 1, 2, 2 ); - StackArray< real64, 1, 2 > JFunc1( 2 ); - StackArray< real64, 1, 2 > JFunc2( 2 ); - JFunc1[0] = jFMultiplier[0][0]; - JFunc2[0] = jFMultiplier[0][1]; - - // finding endpoints: - facePhaseVolFrac1[0][1] = 0.0; - facePhaseVolFrac1[0][0] = 1.0; - m_capPressureWrapper.compute( facePhaseVolFrac1[0], - JFunc1.toSliceConst(), - faceCapPres1[0][0], - dCapPres1_dfacePhaseVolFrac[0][0] ); - real64 const Pc1_min = faceCapPres1[0][0][0]; - facePhaseVolFrac1[0][1] = 1.0; - facePhaseVolFrac1[0][0] = 0.0; - m_capPressureWrapper.compute( facePhaseVolFrac1[0], - JFunc1.toSliceConst(), - faceCapPres1[0][0], - dCapPres1_dfacePhaseVolFrac[0][0] ); - real64 const Pc1_max = faceCapPres1[0][0][0]; - - facePhaseVolFrac2[0][1] = 0.0; - facePhaseVolFrac2[0][0] = 1.0; - m_capPressureWrapper.compute( facePhaseVolFrac2[0], - JFunc2.toSliceConst(), - faceCapPres2[0][0], - dCapPres2_dfacePhaseVolFrac[0][0] ); - real64 const Pc2_min = faceCapPres2[0][0][0]; - facePhaseVolFrac2[0][1] = 1.0; - facePhaseVolFrac2[0][0] = 0.0; - m_capPressureWrapper.compute( facePhaseVolFrac2[0], - JFunc2.toSliceConst(), - faceCapPres2[0][0], - dCapPres2_dfacePhaseVolFrac[0][0] ); - real64 const Pc2_max = faceCapPres2[0][0][0]; + bool converged = 0; - // Use of the relative permeability kernel wrapper - StackArray< real64, 3, 2, constitutive::relperm::LAYOUT_RELPERM > faceTrappedVolFrac1( 1, 1, 2 ); - StackArray< real64, 3, 2, constitutive::relperm::LAYOUT_RELPERM > faceRelPerm1( 1, 1, 2 ); - StackArray< real64, 4, 4, constitutive::relperm::LAYOUT_RELPERM_DS > dfacePhaseRelPerm1_dPhaseVolFrac( 1, 1, 2, 2 ); - StackArray< real64, 3, 2, constitutive::relperm::LAYOUT_RELPERM > faceTrappedVolFrac2( 1, 1, 2 ); - StackArray< real64, 3, 2, constitutive::relperm::LAYOUT_RELPERM > faceRelPerm2( 1, 1, 2 ); - StackArray< real64, 4, 4, constitutive::relperm::LAYOUT_RELPERM_DS > dfacePhaseRelPerm2_dPhaseVolFrac( 1, 1, 2, 2 ); // clear working arrays real64 halfFluxVal[numEqn][2]{}; @@ -2580,31 +2514,9 @@ class FluxComputeInterfaceConditionKernel : public FluxComputeKernel< NUM_EQN, N real64 dhalfFlux_duT[numEqn][2]{}; real64 dhalfFlux_dpc[numEqn][2]{}; - // initial guess: - real64 S_int[numEqn]{}; - real64 const Pc1 = capPresIC[0][0]; - real64 const Pc2 = capPresIC[0][1]; - - real64 Pc_int = ( Pc1 + Pc2 ) / 2.0; - - real64 Pc_min_all = fmax( Pc1_min, Pc2_min ); - real64 Pc_max_all = fmin( Pc1_max, Pc2_max ); - - if( Pc_int < Pc_min_all || Pc_int > Pc_max_all ) - { - Pc_int = ( Pc_min_all + Pc_max_all ) / 2.0; - } - - real64 same_Pc_int = Pc_int; - // GEOS_UNUSED_VAR(gravCoef2[0]); - // GEOS_UNUSED_VAR(gravCoef2[1]); - - // Pc_int = fmin( Pc_max_all, fmax( Pc_int, Pc_min_all )); - // m_interfaceConstitutivePairs[0][0] = std::make_tuple( relPerm, capPressure, fluid ); -// m_interfaceConstitutivePairs[0][1] = std::make_tuple( relPerm, capPressure, fluid ); - - stdVector< real64 > JFMultipliers = {jFMultiplier[0][0], jFMultiplier[0][1]}; + // stdVector< real64 > JFMultipliers = {jFMultiplier[0][0], jFMultiplier[0][1]}; + stdVector< real64 > JFMultipliers = {0.0, 0.0}; stdVector< real64 > trappedSats1 = {0.0, 0.0}; stdVector< real64 > trappedSats2 = {0.0, 0.0}; stdVector< real64 > transHats = {transHat[0], transHat[1]}; @@ -2614,9 +2526,28 @@ class FluxComputeInterfaceConditionKernel : public FluxComputeKernel< NUM_EQN, N stdVector< real64 > cellCenterDuTdS = {duT_dP[0], duT_dP[1], duT_dS[0], duT_dS[1]}; stdVector< real64 > cellCenterDens = {density2[0], density2[1]}; stdVector< real64 > cellCenterDens_dP = {dDens_dP2[0][0], dDens_dP2[0][1], dDens_dP2[1][0], dDens_dP2[1][1]}; - std::vector< RelativePermeabilityBase * > relPerms = {std::get< 0 >( m_interfaceConstitutivePairs_temp ), std::get< 0 >( m_interfaceConstitutivePairs_temp )}; - std::vector< CapillaryPressureBase * > capPressures = {std::get< 1 >( m_interfaceConstitutivePairs_temp ), std::get< 1 >( m_interfaceConstitutivePairs_temp )}; - std::vector< TwoPhaseImmiscibleFluid * > fluids = {std::get< 2 >( m_interfaceConstitutivePairs_temp ), std::get< 2 >( m_interfaceConstitutivePairs_temp )}; + // std::vector< RelativePermeabilityBase * > relPerms = {std::get< 0 >( m_interfaceConstitutivePairs_temp ), std::get< 0 >( m_interfaceConstitutivePairs_temp )}; + // std::vector< CapillaryPressureBase * > capPressures = {std::get< 1 >( m_interfaceConstitutivePairs_temp ), std::get< 1 >( m_interfaceConstitutivePairs_temp )}; + // std::vector< TwoPhaseImmiscibleFluid * > fluids = {std::get< 2 >( m_interfaceConstitutivePairs_temp ), std::get< 2 >( m_interfaceConstitutivePairs_temp )}; + + // auto const & pairArray = m_interfaceConstitutivePairs[0]; + localIndex const surfaceRegionIndex = m_interfaceRegionByConnector.at(iconn); +auto const & pairArray = m_interfaceConstitutivePairs[surfaceRegionIndex]; + +std::vector< constitutive::RelativePermeabilityBase * > relPerms = { + std::get<0>( pairArray[0] ), + std::get<0>( pairArray[1] ) +}; + +std::vector< constitutive::CapillaryPressureBase * > capPressures = { + std::get<1>( pairArray[0] ), + std::get<1>( pairArray[1] ) +}; + +std::vector< constitutive::TwoPhaseImmiscibleFluid * > fluids = { + std::get<2>( pairArray[0] ), + std::get<2>( pairArray[1] ) +}; stdVector< real64 > phi = {halfFluxVal[0][0], halfFluxVal[0][1]}; stdVector< real64 > grad_phi_P = {0.0, 0.0, 0.0, 0.0}; @@ -2671,16 +2602,16 @@ class FluxComputeInterfaceConditionKernel : public FluxComputeKernel< NUM_EQN, N protected: /// Reference to the capillary pressure wrapper - CAPPRESWRAPPER const m_capPressureWrapper; - RELPERMWRAPPER const m_relPermWrapper; + // CAPPRESWRAPPER const m_capPressureWrapper; + // RELPERMWRAPPER const m_relPermWrapper; string_array const m_interfaceFaceSetNames; stdVector< std::array< std::tuple< constitutive::RelativePermeabilityBase *, constitutive::CapillaryPressureBase *, constitutive::TwoPhaseImmiscibleFluid * >, 2 > > const m_interfaceConstitutivePairs; unordered_map< localIndex, localIndex > const m_interfaceRegionByConnector; - std::tuple< constitutive::RelativePermeabilityBase *, - constitutive::CapillaryPressureBase *, - constitutive::TwoPhaseImmiscibleFluid * > const m_interfaceConstitutivePairs_temp; + // std::tuple< constitutive::RelativePermeabilityBase *, + // constitutive::CapillaryPressureBase *, + // constitutive::TwoPhaseImmiscibleFluid * > const m_interfaceConstitutivePairs_temp; }; @@ -2758,7 +2689,8 @@ class FluxComputeKernelFactory * @param[inout] localMatrix the local CRS matrix * @param[inout] localRhs the local right-hand side vector */ - template< typename POLICY, typename STENCILWRAPPER, typename CAPPRESWRAPPER, typename RELPERMWRAPPER > + // template< typename POLICY, typename STENCILWRAPPER, typename CAPPRESWRAPPER, typename RELPERMWRAPPER > + template< typename POLICY, typename STENCILWRAPPER > static void createAndLaunch( integer const numPhases, globalIndex const rankOffset, @@ -2769,16 +2701,16 @@ class FluxComputeKernelFactory string const & solverName, ElementRegionManager const & elemManager, STENCILWRAPPER const & stencilWrapper, - CAPPRESWRAPPER const & capPresWrapper, - RELPERMWRAPPER const & relPermWrapper, + // CAPPRESWRAPPER const & capPresWrapper, + // RELPERMWRAPPER const & relPermWrapper, string_array const & interfaceFaceSetNames, stdVector< std::array< std::tuple< constitutive::RelativePermeabilityBase *, constitutive::CapillaryPressureBase *, constitutive::TwoPhaseImmiscibleFluid * >, 2 > > const & interfaceConstitutivePairs, unordered_map< localIndex, localIndex > const & interfaceRegionByConnector, - std::tuple< constitutive::RelativePermeabilityBase *, - constitutive::CapillaryPressureBase *, - constitutive::TwoPhaseImmiscibleFluid * > const & interfaceConstitutivePairs_temp, + // std::tuple< constitutive::RelativePermeabilityBase *, + // constitutive::CapillaryPressureBase *, + // constitutive::TwoPhaseImmiscibleFluid * > const & interfaceConstitutivePairs_temp, ElementSubRegionBase const & subRegion, real64 const & dt, CRSMatrixView< real64, globalIndex const > const & localMatrix, @@ -2791,16 +2723,21 @@ class FluxComputeKernelFactory elemManager.constructArrayViewAccessor< globalIndex, 1 >( dofKey ); dofNumberAccessor.setName( solverName + "/accessors/" + dofKey ); - using kernelType = FluxComputeInterfaceConditionKernel< NUM_EQN, NUM_DOF, STENCILWRAPPER, CAPPRESWRAPPER, RELPERMWRAPPER >; + // using kernelType = FluxComputeInterfaceConditionKernel< NUM_EQN, NUM_DOF, STENCILWRAPPER, CAPPRESWRAPPER, RELPERMWRAPPER >; + using kernelType = FluxComputeInterfaceConditionKernel< NUM_EQN, NUM_DOF, STENCILWRAPPER >; typename kernelType::ImmiscibleMultiphaseFlowAccessors flowAccessors( elemManager, solverName ); typename kernelType::MultiphaseFluidAccessors fluidAccessors( elemManager, solverName ); typename kernelType::CapPressureAccessors capPressureAccessors( elemManager, solverName ); typename kernelType::PermeabilityAccessors permAccessors( elemManager, solverName ); - kernelType kernel( numPhases, rankOffset, stencilWrapper, capPresWrapper, relPermWrapper, dofNumberAccessor, + // kernelType kernel( numPhases, rankOffset, stencilWrapper, capPresWrapper, relPermWrapper, dofNumberAccessor, + // flowAccessors, fluidAccessors, capPressureAccessors, permAccessors, + // dt, localMatrix, localRhs, hasCapPressure, useTotalMassEquation, + // checkPhasePresenceInGravity, interfaceFaceSetNames, interfaceConstitutivePairs, interfaceRegionByConnector, interfaceConstitutivePairs_temp, domainSize ); + kernelType kernel( numPhases, rankOffset, stencilWrapper, dofNumberAccessor, flowAccessors, fluidAccessors, capPressureAccessors, permAccessors, dt, localMatrix, localRhs, hasCapPressure, useTotalMassEquation, - checkPhasePresenceInGravity, interfaceFaceSetNames, interfaceConstitutivePairs, interfaceRegionByConnector, interfaceConstitutivePairs_temp, domainSize ); + checkPhasePresenceInGravity, interfaceFaceSetNames, interfaceConstitutivePairs, interfaceRegionByConnector, domainSize ); kernelType::template launch< POLICY >( stencilWrapper.size(), kernel ); } }; From 98710589a15fb99617dca24f3b42e7865bfcd58b Mon Sep 17 00:00:00 2001 From: Ammara-14 Date: Wed, 4 Feb 2026 12:27:48 -0800 Subject: [PATCH 095/104] Adding input files and compiles on release --- .../initialPressure.txt | 0 .../1D_case/initialSaturation1.txt | 10 + .../1D_case/initialSaturation2.txt | 10 + .../jFunction_linear.txt | 0 .../1D_case/permx.geos | 10 + .../1D_case/permy.geos | 10 + .../1D_case/permz.geos | 10 + .../phaseVolumeFraction_water_linear.txt | 0 .../1D_case/tables/jFunction | 0 .../1D_case/tables/jFunction.txt | 76 ++ .../tables/jFunction_linear.txt | 0 .../tables/phaseVolumeFraction_water.txt | 2 +- .../phaseVolumeFraction_water_linear.txt | 0 .../uni_directional_flow_base.xml | 178 ++- ...i_directional_flow_interface_condition.xml | 30 +- .../1D_case/x.txt | 1 + .../1D_case/y.txt | 1 + .../1D_case/z.txt | 10 + .../3D_case/input/initialPressure.txt | 1200 +++++++++++++++++ .../3D_case/input/initialSaturation1.txt | 1200 +++++++++++++++++ .../3D_case/input/initialSaturation2.txt | 1200 +++++++++++++++++ .../3D_case/input/permx.geos | 1200 +++++++++++++++++ .../3D_case/input/permy.geos | 1200 +++++++++++++++++ .../3D_case/input/permz.geos | 1200 +++++++++++++++++ .../3D_case/input/x.txt | 10 + .../3D_case/input/y.txt | 6 + .../3D_case/input/z.txt | 20 + .../3D_case/uni_directional_flow_base.xml | 293 ++++ ...i_directional_flow_interface_condition.xml | 66 + ...oPhase_GravitySegregation_1d_pc_heter2.xml | 280 ---- .../initialSaturation1.txt | 10 - .../initialSaturation2.txt | 10 - .../permx.geos | 10 - .../permy.geos | 10 - .../permz.geos | 10 - .../tables/jFunction.txt | 13 - .../tables/phaseVolumeFraction_water.txt | 13 - .../x.txt | 1 - .../y.txt | 1 - .../z.txt | 10 - .../tables/jFunction_linear.txt | 2 - .../phaseVolumeFraction_water_linear.txt | 2 - .../BrooksCoreyCapillaryPressure.hpp | 2 + .../JFunctionCapillaryPressure.hpp | 1 + .../TableCapillaryPressure.hpp | 2 + .../fluidFlow/ImmiscibleMultiphaseFlow.cpp | 4 +- .../ImmiscibleMultiphaseKernels.hpp | 32 +- 47 files changed, 7895 insertions(+), 461 deletions(-) rename inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/{immiscible_GS_1d_pc_heter_famousCase_withIC => 1D_case}/initialPressure.txt (100%) create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/initialSaturation1.txt create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/initialSaturation2.txt rename inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/{immiscible_GS_1d_pc_heter_famousCase_withIC => 1D_case}/jFunction_linear.txt (100%) create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/permx.geos create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/permy.geos create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/permz.geos rename inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/{immiscible_GS_1d_pc_heter_famousCase_withIC => 1D_case}/phaseVolumeFraction_water_linear.txt (100%) create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/tables/jFunction create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/tables/jFunction.txt rename inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/{immiscible_GS_1d_pc_heter_famousCase_withIC => 1D_case}/tables/jFunction_linear.txt (100%) rename inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/{ => 1D_case}/tables/phaseVolumeFraction_water.txt (99%) mode change 100755 => 100644 rename inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/{immiscible_GS_1d_pc_heter_famousCase_withIC => 1D_case}/tables/phaseVolumeFraction_water_linear.txt (100%) rename inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/{ => 1D_case}/uni_directional_flow_base.xml (55%) rename inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/{ => 1D_case}/uni_directional_flow_interface_condition.xml (71%) create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/x.txt create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/y.txt create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/z.txt create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/input/initialPressure.txt create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/input/initialSaturation1.txt create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/input/initialSaturation2.txt create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/input/permx.geos create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/input/permy.geos create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/input/permz.geos create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/input/x.txt create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/input/y.txt create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/input/z.txt create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/uni_directional_flow_base.xml create mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/uni_directional_flow_interface_condition.xml delete mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/immiscibleTwoPhase_GravitySegregation_1d_pc_heter2.xml delete mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/initialSaturation1.txt delete mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/initialSaturation2.txt delete mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/permx.geos delete mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/permy.geos delete mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/permz.geos delete mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/tables/jFunction.txt delete mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/tables/phaseVolumeFraction_water.txt delete mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/x.txt delete mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/y.txt delete mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/z.txt delete mode 100644 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/tables/jFunction_linear.txt delete mode 100755 inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/tables/phaseVolumeFraction_water_linear.txt diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/initialPressure.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/initialPressure.txt similarity index 100% rename from inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/initialPressure.txt rename to inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/initialPressure.txt diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/initialSaturation1.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/initialSaturation1.txt new file mode 100644 index 00000000000..1859fabae78 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/initialSaturation1.txt @@ -0,0 +1,10 @@ +0.95 +0.95 +0.95 +0.95 +0.95 +0.95 +0.95 +0.05 +0.05 +0.05 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/initialSaturation2.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/initialSaturation2.txt new file mode 100644 index 00000000000..d113536f2fd --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/initialSaturation2.txt @@ -0,0 +1,10 @@ +0.05 +0.05 +0.05 +0.05 +0.05 +0.05 +0.05 +0.95 +0.95 +0.95 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/jFunction_linear.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/jFunction_linear.txt similarity index 100% rename from inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/jFunction_linear.txt rename to inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/jFunction_linear.txt diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/permx.geos b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/permx.geos new file mode 100644 index 00000000000..4d47d8fa568 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/permx.geos @@ -0,0 +1,10 @@ +50 +50 +50 +50 +50 +200 +200 +200 +200 +200 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/permy.geos b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/permy.geos new file mode 100644 index 00000000000..4d47d8fa568 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/permy.geos @@ -0,0 +1,10 @@ +50 +50 +50 +50 +50 +200 +200 +200 +200 +200 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/permz.geos b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/permz.geos new file mode 100644 index 00000000000..4d47d8fa568 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/permz.geos @@ -0,0 +1,10 @@ +50 +50 +50 +50 +50 +200 +200 +200 +200 +200 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/phaseVolumeFraction_water_linear.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/phaseVolumeFraction_water_linear.txt similarity index 100% rename from inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/phaseVolumeFraction_water_linear.txt rename to inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/phaseVolumeFraction_water_linear.txt diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/tables/jFunction b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/tables/jFunction new file mode 100644 index 00000000000..e69de29bb2d diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/tables/jFunction.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/tables/jFunction.txt new file mode 100644 index 00000000000..72a78a75b85 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/tables/jFunction.txt @@ -0,0 +1,76 @@ +99.9980934 +17.78445609 +11.20350909 +8.549878542 +7.057769576 +6.082201546 +5.386086427 +4.86006559 +4.446116454 +4.110353325 +3.831547061 +3.595663494 +3.393021946 +3.216710174 +3.061649542 +2.924017691 +2.800877928 +2.68993357 +2.589360389 +2.497689435 +2.413723433 +2.336475912 +2.265126101 +2.198985069 +2.137469915 +2.080083807 +2.02640045 +1.976051821 +1.928718377 +1.884121218 +1.842015737 +1.802186411 +1.764442543 +1.728614745 +1.694551981 +1.662119113 +1.631194842 +1.601669938 +1.573445757 +1.546432977 +1.520550493 +1.495724483 +1.471887601 +1.448978263 +1.426940034 +1.405721104 +1.385273798 +1.365554178 +1.346521677 +1.328138769 +1.310370692 +1.293185194 +1.276552299 +1.260444114 +1.244834648 +1.229699646 +1.215016445 +1.200763848 +1.186921998 +1.173472275 +1.160397205 +1.147680364 +1.135306301 +1.123260469 +1.111529155 +1.100099423 +1.088959056 +1.078096509 +1.067500858 +1.057161765 +1.047069433 +1.03721457 +1.027588362 +1.018182437 +1.008988837 +0.999999998 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/tables/jFunction_linear.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/tables/jFunction_linear.txt similarity index 100% rename from inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/tables/jFunction_linear.txt rename to inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/tables/jFunction_linear.txt diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/tables/phaseVolumeFraction_water.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/tables/phaseVolumeFraction_water.txt old mode 100755 new mode 100644 similarity index 99% rename from inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/tables/phaseVolumeFraction_water.txt rename to inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/tables/phaseVolumeFraction_water.txt index 30a57a9dee4..f38627d4e85 --- a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/tables/phaseVolumeFraction_water.txt +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/tables/phaseVolumeFraction_water.txt @@ -1,4 +1,4 @@ -0 +0.001 0.013333333 0.026666667 0.04 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/tables/phaseVolumeFraction_water_linear.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/tables/phaseVolumeFraction_water_linear.txt similarity index 100% rename from inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/tables/phaseVolumeFraction_water_linear.txt rename to inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/tables/phaseVolumeFraction_water_linear.txt diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/uni_directional_flow_base.xml b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/uni_directional_flow_base.xml similarity index 55% rename from inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/uni_directional_flow_base.xml rename to inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/uni_directional_flow_base.xml index 2640edbdc80..efbd5b34421 100644 --- a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/uni_directional_flow_base.xml +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/uni_directional_flow_base.xml @@ -2,19 +2,21 @@ - + + newtonTol="1.0e-5" + newtonMaxIter="20" + maxTimeStepCuts="20" + maxSubSteps="2000"/> + values="{ 900 }" /> + values="{ 400 }" /> + values="{ 0.001 }" /> + values="{ 0.001 }" /> + + + + coordinateFiles="{ tables/phaseVolumeFraction_water.txt }" + voxelFile="tables/jFunction.txt"/> + + + + @@ -88,51 +127,67 @@ + permeabilityComponents="{ 1.0e-14, 1.0e-14, 1.0e-14}"/> - - + wettingNonWettingSurfaceTension="6.12e-3" + permeabilityDirection="XY"/> --> + + + + + @@ -141,61 +196,73 @@ + + + scale="1.0" + functionName="pressureTable" /> + scale="1.0" + functionName="saturationTable1" /> + scale="1.0" + functionName="saturationTable2" /> - - - + fieldName="rockPerm_permeability" + functionName="permxFunc" + scale="1.0e-14"/> + fieldName="rockPerm_permeability" + functionName="permyFunc" + scale="1.0e-14"/> + fieldName="rockPerm_permeability" + functionName="permzFunc" + scale="1.0e-14"/> + @@ -203,23 +270,24 @@ - + - + diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/uni_directional_flow_interface_condition.xml b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/uni_directional_flow_interface_condition.xml similarity index 71% rename from inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/uni_directional_flow_interface_condition.xml rename to inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/uni_directional_flow_interface_condition.xml index c263012d27c..41ba4e3ed92 100644 --- a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/uni_directional_flow_interface_condition.xml +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/uni_directional_flow_interface_condition.xml @@ -10,42 +10,42 @@ - + xMax="{0.01, 1.00001, 1.00001}"/> --> + xMin="{ -0.00001, -0.00001, -0.00001}" + xMax="{ 1.00001, 1.00001, 1.00001}"/> + xMin="{ -0.01, -0.01, 4.99 }" + xMax="{ 1.01, 1.01, 5.01 }"/> + maxTime="86.4e+05"> - + diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/x.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/x.txt new file mode 100644 index 00000000000..2eb3c4fe4ee --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/x.txt @@ -0,0 +1 @@ +0.5 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/y.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/y.txt new file mode 100644 index 00000000000..2eb3c4fe4ee --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/y.txt @@ -0,0 +1 @@ +0.5 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/z.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/z.txt new file mode 100644 index 00000000000..f43a1f14d26 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/1D_case/z.txt @@ -0,0 +1,10 @@ +0.5 +1.5 +2.5 +3.5 +4.5 +5.5 +6.5 +7.5 +8.5 +9.5 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/input/initialPressure.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/input/initialPressure.txt new file mode 100644 index 00000000000..6963bb6148c --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/input/initialPressure.txt @@ -0,0 +1,1200 @@ +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00022072e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00066218e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00110362e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00154508e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00198652e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00242798e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00286942e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00331088e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00375232e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00419378e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00463522e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00507668e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00551812e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00595958e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00640102e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00684248e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00728392e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00772538e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00816682e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 +1.00860828e+07 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/input/initialSaturation1.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/input/initialSaturation1.txt new file mode 100644 index 00000000000..90ddc12151e --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/input/initialSaturation1.txt @@ -0,0 +1,1200 @@ +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e+00 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 +1.00000000e-02 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/input/initialSaturation2.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/input/initialSaturation2.txt new file mode 100644 index 00000000000..d5ef52f254b --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/input/initialSaturation2.txt @@ -0,0 +1,1200 @@ +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +0.00000000e+00 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 +9.90000000e-01 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/input/permx.geos b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/input/permx.geos new file mode 100644 index 00000000000..439bd535a86 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/input/permx.geos @@ -0,0 +1,1200 @@ +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/input/permy.geos b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/input/permy.geos new file mode 100644 index 00000000000..439bd535a86 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/input/permy.geos @@ -0,0 +1,1200 @@ +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/input/permz.geos b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/input/permz.geos new file mode 100644 index 00000000000..439bd535a86 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/input/permz.geos @@ -0,0 +1,1200 @@ +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +5.00000000e+01 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 +2.00000000e+02 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/input/x.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/input/x.txt new file mode 100644 index 00000000000..283fc50e7fb --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/input/x.txt @@ -0,0 +1,10 @@ +5.00000000e-01 +1.50000000e+00 +2.50000000e+00 +3.50000000e+00 +4.50000000e+00 +5.50000000e+00 +6.50000000e+00 +7.50000000e+00 +8.50000000e+00 +9.50000000e+00 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/input/y.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/input/y.txt new file mode 100644 index 00000000000..a01763bc5d1 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/input/y.txt @@ -0,0 +1,6 @@ +5.00000000e-01 +1.50000000e+00 +2.50000000e+00 +3.50000000e+00 +4.50000000e+00 +5.50000000e+00 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/input/z.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/input/z.txt new file mode 100644 index 00000000000..d122a370abe --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/input/z.txt @@ -0,0 +1,20 @@ +2.50000000e-01 +7.50000000e-01 +1.25000000e+00 +1.75000000e+00 +2.25000000e+00 +2.75000000e+00 +3.25000000e+00 +3.75000000e+00 +4.25000000e+00 +4.75000000e+00 +5.25000000e+00 +5.75000000e+00 +6.25000000e+00 +6.75000000e+00 +7.25000000e+00 +7.75000000e+00 +8.25000000e+00 +8.75000000e+00 +9.25000000e+00 +9.75000000e+00 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/uni_directional_flow_base.xml b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/uni_directional_flow_base.xml new file mode 100644 index 00000000000..eeeefa8277d --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/uni_directional_flow_base.xml @@ -0,0 +1,293 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/uni_directional_flow_interface_condition.xml b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/uni_directional_flow_interface_condition.xml new file mode 100644 index 00000000000..faea9a0d2e4 --- /dev/null +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/uni_directional_flow_interface_condition.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/immiscibleTwoPhase_GravitySegregation_1d_pc_heter2.xml b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/immiscibleTwoPhase_GravitySegregation_1d_pc_heter2.xml deleted file mode 100644 index 01f8c50219d..00000000000 --- a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/immiscibleTwoPhase_GravitySegregation_1d_pc_heter2.xml +++ /dev/null @@ -1,280 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/initialSaturation1.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/initialSaturation1.txt deleted file mode 100644 index 79cccb86897..00000000000 --- a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/initialSaturation1.txt +++ /dev/null @@ -1,10 +0,0 @@ -0.4 -0.4 -0.8 -0.8 -0.8 -0.8 -0.8 -0.8 -0.8 -0.8 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/initialSaturation2.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/initialSaturation2.txt deleted file mode 100644 index 72c544974fe..00000000000 --- a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/initialSaturation2.txt +++ /dev/null @@ -1,10 +0,0 @@ -0.6 -0.6 -0.2 -0.2 -0.2 -0.2 -0.2 -0.2 -0.2 -0.2 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/permx.geos b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/permx.geos deleted file mode 100644 index ec8beb6c503..00000000000 --- a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/permx.geos +++ /dev/null @@ -1,10 +0,0 @@ -112.5 -112.5 -112.5 -112.5 -112.5 -50 -50 -50 -50 -50 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/permy.geos b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/permy.geos deleted file mode 100644 index ec8beb6c503..00000000000 --- a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/permy.geos +++ /dev/null @@ -1,10 +0,0 @@ -112.5 -112.5 -112.5 -112.5 -112.5 -50 -50 -50 -50 -50 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/permz.geos b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/permz.geos deleted file mode 100644 index ec8beb6c503..00000000000 --- a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/permz.geos +++ /dev/null @@ -1,10 +0,0 @@ -112.5 -112.5 -112.5 -112.5 -112.5 -50 -50 -50 -50 -50 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/tables/jFunction.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/tables/jFunction.txt deleted file mode 100644 index dfd48c60a6b..00000000000 --- a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/tables/jFunction.txt +++ /dev/null @@ -1,13 +0,0 @@ -4.331729359 -3.523266264 -2.677103439 -2.356150157 -2.166062360 -2.034158727 -1.934627222 -1.855494313 -1.790286970 -1.735134860 -1.687551617 -1.666049754 - diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/tables/phaseVolumeFraction_water.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/tables/phaseVolumeFraction_water.txt deleted file mode 100644 index 4c7e1f01e40..00000000000 --- a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/tables/phaseVolumeFraction_water.txt +++ /dev/null @@ -1,13 +0,0 @@ -0 -0.05 -0.15 -0.25 -0.35 -0.45 -0.55 -0.65 -0.75 -0.85 -0.95 -1 - diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/x.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/x.txt deleted file mode 100644 index 7ed6ff82de6..00000000000 --- a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/x.txt +++ /dev/null @@ -1 +0,0 @@ -5 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/y.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/y.txt deleted file mode 100644 index 7ed6ff82de6..00000000000 --- a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/y.txt +++ /dev/null @@ -1 +0,0 @@ -5 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/z.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/z.txt deleted file mode 100644 index d71cc528224..00000000000 --- a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/immiscible_GS_1d_pc_heter_famousCase_withIC/z.txt +++ /dev/null @@ -1,10 +0,0 @@ -5 -15 -25 -35 -45 -55 -65 -75 -85 -95 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/tables/jFunction_linear.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/tables/jFunction_linear.txt deleted file mode 100644 index c2cba8f9783..00000000000 --- a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/tables/jFunction_linear.txt +++ /dev/null @@ -1,2 +0,0 @@ -10000 -3000 diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/tables/phaseVolumeFraction_water_linear.txt b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/tables/phaseVolumeFraction_water_linear.txt deleted file mode 100755 index 0d66ea1aee9..00000000000 --- a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/tables/phaseVolumeFraction_water_linear.txt +++ /dev/null @@ -1,2 +0,0 @@ -0 -1 diff --git a/src/coreComponents/constitutive/capillaryPressure/BrooksCoreyCapillaryPressure.hpp b/src/coreComponents/constitutive/capillaryPressure/BrooksCoreyCapillaryPressure.hpp index 4a7816683dd..0d71fcbc948 100644 --- a/src/coreComponents/constitutive/capillaryPressure/BrooksCoreyCapillaryPressure.hpp +++ b/src/coreComponents/constitutive/capillaryPressure/BrooksCoreyCapillaryPressure.hpp @@ -196,6 +196,8 @@ BrooksCoreyCapillaryPressureUpdate:: // compute first gas-oil capillary pressure as a function of gas-phase vol fraction integer const ip_gas = m_phaseOrder[CapillaryPressureBase::PhaseType::GAS]; integer const ip_oil = m_phaseOrder[CapillaryPressureBase::PhaseType::OIL]; + + GEOS_UNUSED_VAR( ip_gas ); if( ip_oil >= 0 ) { real64 const volFracScaled = (phaseVolFraction[ip_oil] - m_phaseMinVolumeFraction[ip_oil]) * volFracScaleInv; diff --git a/src/coreComponents/constitutive/capillaryPressure/JFunctionCapillaryPressure.hpp b/src/coreComponents/constitutive/capillaryPressure/JFunctionCapillaryPressure.hpp index 80815e98236..5e2f885cbf6 100644 --- a/src/coreComponents/constitutive/capillaryPressure/JFunctionCapillaryPressure.hpp +++ b/src/coreComponents/constitutive/capillaryPressure/JFunctionCapillaryPressure.hpp @@ -271,6 +271,7 @@ JFunctionCapillaryPressure::KernelWrapper:: integer const ipOil = m_phaseOrder[PT::OIL]; integer const ipGas = m_phaseOrder[PT::GAS]; + GEOS_UNUSED_VAR( ipOil ); // apply multiplier real64 capPresWater_J = phaseCapPres[ipWater] / jFuncMultiplier[0]; // std::cout << GEOS_FMT( " JM_2 = ( {:4.2e} )", jFuncMultiplier[0] ); diff --git a/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressure.hpp b/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressure.hpp index 949d431792a..7a018204287 100644 --- a/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressure.hpp +++ b/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressure.hpp @@ -199,6 +199,8 @@ TableCapillaryPressure::KernelWrapper:: integer const ipOil = m_phaseOrder[PT::OIL]; integer const ipGas = m_phaseOrder[PT::GAS]; + GEOS_UNUSED_VAR( ipOil ); + // put capillary pressure on the wetting phase real64 capPresWater = phaseCapPres[ipWater]; array1d input(1); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index 7bc576686dc..5b60a07045d 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -215,7 +215,7 @@ // ***** Create FaceElements ***** forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, MeshLevel & meshLevel, - string_array const & regionNames ) + string_array const & GEOS_UNUSED_PARAM( regionNames )) { FaceManager const & faceManager = meshLevel.getFaceManager(); @@ -617,7 +617,7 @@ m_interfaceConstitutivePairs[surfaceRegionIndex][1] = std::make_tuple( relPerm1, m_interfaceRegionByConnector.clear(); forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( std::string const &, MeshLevel & meshLevel, - string_array const & regionNames ) + string_array const & GEOS_UNUSED_PARAM( regionNames )) { // Access the face manager and retrieve the face set group for the current mesh level FaceManager const & faceManager = meshLevel.getFaceManager(); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp index 37b67a7852c..f9535bbadba 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp @@ -164,7 +164,7 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< converged = 0; bool damping = true; bool bisection = false; - bool lineSearch = false; + // bool lineSearch = false; bool newton_path = false; // Local newton loop: @@ -483,8 +483,8 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< // While loop (newton loop) int iter = 0; int div = 0; - int ext_iter0 = 0; - int ext_iter1 = 0; + // int ext_iter0 = 0; + // int ext_iter1 = 0; real64 next_Pc_int = 0.0; real64 old_Pc_int = 0.0; real64 old_residual = 0.0; @@ -701,8 +701,8 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< real64 dGravHead_dP[2][2]{}; real64 capGrad[2]{}; - real64 capPresIC[2][2]{}; - real64 jFMultiplier[2][2]{}; + // real64 capPresIC[2][2]{}; + // real64 jFMultiplier[2][2]{}; real64 dCapGrad_dP[2][2]{}; real64 dCapGrad_dS[2][2]{}; @@ -809,7 +809,7 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< dGravHead_dP[ip][ke] += signTix[ke] * dTransHat_dP[ix] * dGravHead_dTrans; - real64 constexpr eps = 1e-18; + // real64 constexpr eps = 1e-18; real64 dCapPres_dS = dCapPres1_dPhaseVolFrac[0][0][ip][ip]; if( ke == 1 && ix == 0 ) @@ -869,7 +869,7 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< /// Three Forces Flux Contribution: 1- Viscous 2- Gravitational 3- Capillary constexpr int sign[2] = {1, -1}; - real64 constexpr eps = 0.0; + // real64 constexpr eps = 0.0; // loop over phases for( integer ip = 0; ip < 2; ++ip ) @@ -2196,7 +2196,7 @@ class FluxComputeInterfaceConditionKernel : public FluxComputeKernel< NUM_EQN, N real64 capGrad[numEqn]{}; // real64 capPresIC[numEqn][2]{}; - real64 jFMultiplier[numEqn][2]{}; + // real64 jFMultiplier[numEqn][2]{}; real64 dCapGrad_dP[numEqn][2]{}; real64 dCapGrad_dS[numEqn][2]{}; @@ -2216,7 +2216,7 @@ class FluxComputeInterfaceConditionKernel : public FluxComputeKernel< NUM_EQN, N real64 gravCoefHat[numEqn]{}; real64 uT = 0; - real64 total_mobility = 0; + // real64 total_mobility = 0; real64 duT_dP[numEqn]{}; real64 duT_dS[numEqn]{}; @@ -2236,7 +2236,7 @@ class FluxComputeInterfaceConditionKernel : public FluxComputeKernel< NUM_EQN, N stdVector< real64 > saturations = {m_phaseVolFrac[seri[0]][sesri[0]][sei[0]][0], m_phaseVolFrac[seri[1]][sesri[1]][sei[1]][0] }; stdVector< real64 > pressures = {m_pres[seri[0]][sesri[0]][sei[0]], m_pres[seri[1]][sesri[1]][sei[1]] }; - bool isJfunction = 0; + // bool isJfunction = 0; // loop over phases for( integer ip = 0; ip < m_numPhases; ++ip ) @@ -2507,12 +2507,12 @@ class FluxComputeInterfaceConditionKernel : public FluxComputeKernel< NUM_EQN, N // clear working arrays real64 halfFluxVal[numEqn][2]{}; - real64 dhalfFlux1_dP[numEqn][2]{}; - real64 dhalfFlux1_dS[numEqn][2]{}; - real64 dhalfFlux2_dP[numEqn][2]{}; - real64 dhalfFlux2_dS[numEqn][2]{}; - real64 dhalfFlux_duT[numEqn][2]{}; - real64 dhalfFlux_dpc[numEqn][2]{}; + // real64 dhalfFlux1_dP[numEqn][2]{}; + // real64 dhalfFlux1_dS[numEqn][2]{}; + // real64 dhalfFlux2_dP[numEqn][2]{}; + // real64 dhalfFlux2_dS[numEqn][2]{}; + // real64 dhalfFlux_duT[numEqn][2]{}; + // real64 dhalfFlux_dpc[numEqn][2]{}; // stdVector< real64 > JFMultipliers = {jFMultiplier[0][0], jFMultiplier[0][1]}; From 5f7e6c0a132da89c881e3b9b8422463df3631de5 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Wed, 4 Feb 2026 22:47:42 -0800 Subject: [PATCH 096/104] wip: adding interface condition test to CmakeList --- .../BrooksCoreyCapillaryPressure.hpp | 49 +- .../TableCapillaryPressure.cpp | 2 +- .../TableCapillaryPressure.hpp | 10 +- .../VanGenuchtenCapillaryPressure.hpp | 10 +- .../testCO2SpycherPruessModels.cpp.uncrustify | 0 .../fluidFlowTests/CMakeLists.txt | 1 + .../testImmiscibleInterfaceConditions.cpp | 39 +- .../fluidFlow/ImmiscibleMultiphaseFlow.cpp | 3063 ++++++++--------- .../ImmiscibleMultiphaseKernels.hpp | 273 +- 9 files changed, 1741 insertions(+), 1706 deletions(-) create mode 100644 src/coreComponents/constitutive/unitTests/testCO2SpycherPruessModels.cpp.uncrustify diff --git a/src/coreComponents/constitutive/capillaryPressure/BrooksCoreyCapillaryPressure.hpp b/src/coreComponents/constitutive/capillaryPressure/BrooksCoreyCapillaryPressure.hpp index 0d71fcbc948..39b61e786f7 100644 --- a/src/coreComponents/constitutive/capillaryPressure/BrooksCoreyCapillaryPressure.hpp +++ b/src/coreComponents/constitutive/capillaryPressure/BrooksCoreyCapillaryPressure.hpp @@ -59,8 +59,8 @@ class BrooksCoreyCapillaryPressureUpdate final : public CapillaryPressureBaseUpd GEOS_HOST_DEVICE void computeInv( arraySlice1d< real64, compflow::USD_PHASE - 1 > const & phaseVolFraction, - arraySlice1d< real64 const, cappres::USD_CAPPRES - 2 > const & phaseCapPres, - arraySlice2d< real64, cappres::USD_CAPPRES_DS - 2 > const & dPhaseCapPres_dPhaseVolFrac ) const; + arraySlice1d< real64 const, cappres::USD_CAPPRES - 2 > const & phaseCapPres, + arraySlice2d< real64, cappres::USD_CAPPRES_DS - 2 > const & dPhaseCapPres_dPhaseVolFrac ) const; GEOS_HOST_DEVICE virtual void update( localIndex const k, @@ -85,20 +85,20 @@ class BrooksCoreyCapillaryPressureUpdate final : public CapillaryPressureBaseUpd real64 & phaseCapPressure, real64 & dPhaseCapPressure_dVolFrac ); - -GEOS_HOST_DEVICE -GEOS_FORCE_INLINE -static void -evaluateBrooksCoreyFunctionInv( real64 const phaseCapPressure, - int const ip, - real64 const volFracScaleInv, - real64 const exponentInv, - real64 const entryPressure, - real64 const maxCapPres_eps, - real64 const phaseMinVolumeFraction, - arrayView1d< integer const > const phaseOrder, - real64 & phaseVolFraction, - real64 & dPhaseCapPressure_dVolFrac ); + + GEOS_HOST_DEVICE + GEOS_FORCE_INLINE + static void + evaluateBrooksCoreyFunctionInv( real64 const phaseCapPressure, + int const ip, + real64 const volFracScaleInv, + real64 const exponentInv, + real64 const entryPressure, + real64 const maxCapPres_eps, + real64 const phaseMinVolumeFraction, + arrayView1d< integer const > const phaseOrder, + real64 & phaseVolFraction, + real64 & dPhaseCapPressure_dVolFrac ); arrayView1d< real64 const > m_phaseMinVolumeFraction; arrayView1d< real64 const > m_phaseCapPressureExponentInv; @@ -111,9 +111,6 @@ evaluateBrooksCoreyFunctionInv( real64 const phaseCapPressure, - - - class BrooksCoreyCapillaryPressure : public CapillaryPressureBase { public: @@ -222,8 +219,8 @@ GEOS_HOST_DEVICE inline void BrooksCoreyCapillaryPressureUpdate:: computeInv( arraySlice1d< real64, compflow::USD_PHASE - 1 > const & phaseVolFraction, - arraySlice1d< real64 const, cappres::USD_CAPPRES - 2 > const & phaseCapPres, - arraySlice2d< real64, cappres::USD_CAPPRES_DS - 2 > const & dPhaseCapPres_dPhaseVolFrac ) const + arraySlice1d< real64 const, cappres::USD_CAPPRES - 2 > const & phaseCapPres, + arraySlice2d< real64, cappres::USD_CAPPRES_DS - 2 > const & dPhaseCapPres_dPhaseVolFrac ) const { LvArray::forValuesInSlice( dPhaseCapPres_dPhaseVolFrac, []( real64 & val ){ val = 0.0; } ); @@ -268,7 +265,7 @@ BrooksCoreyCapillaryPressureUpdate:: m_phaseOrder, phaseVolFraction[ip_water], dPhaseCapPres_dPhaseVolFrac[ip_water][ip_water] ); - phaseVolFraction[ip_gas] = 1.0 - phaseVolFraction[ip_water]; + phaseVolFraction[ip_gas] = 1.0 - phaseVolFraction[ip_water]; } @@ -306,7 +303,7 @@ BrooksCoreyCapillaryPressureUpdate:: // m_phaseOrder, // phaseVolFraction[ip_gas], // dPhaseCapPres_dPhaseVolFrac[ip_gas][ip_gas] ); - // phaseVolFraction[ip_water] = 1.0 - phaseVolFraction[ip_gas]; + // phaseVolFraction[ip_water] = 1.0 - phaseVolFraction[ip_gas]; // } } @@ -357,7 +354,7 @@ BrooksCoreyCapillaryPressureUpdate:: real64 & phaseVolFraction, real64 & dPhaseCapPressure_dVolFrac ) { - + phaseVolFraction = 0.0; real64 value = 0.0; @@ -370,7 +367,7 @@ BrooksCoreyCapillaryPressureUpdate:: if( phaseCapPressure <= maxCapPres_eps && phaseCapPressure >= entryPressure ) { // intermediate value - real64 const val = pow( entryPressure, exponentInv) / pow( phaseCapPressure , exponentInv + 1 ); + real64 const val = pow( entryPressure, exponentInv ) / pow( phaseCapPressure, exponentInv + 1 ); value = (phaseCapPressure * val) * volFracScaleInv + phaseMinVolumeFraction; // entryPressure * (S_w)^( - 1 / exponentInv ) dPhaseCapPressure_dVolFrac = -dScaledWettingPhaseVolFrac_dVolFrac * val * exponentInv; @@ -379,7 +376,7 @@ BrooksCoreyCapillaryPressureUpdate:: else // enforce a constant and bounded capillary pressure { real64 const val = (phaseCapPressure > maxCapPres_eps) - ? pow( entryPressure, exponentInv) / pow( maxCapPres_eps , exponentInv) : 1.0; + ? pow( entryPressure, exponentInv ) / pow( maxCapPres_eps, exponentInv ) : 1.0; value = val * volFracScaleInv + phaseMinVolumeFraction; phaseVolFraction = (ip == ip_oil) ? 1.0 - value : value; } diff --git a/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressure.cpp b/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressure.cpp index 1fbc230a03e..b925627ff4b 100644 --- a/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressure.cpp +++ b/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressure.cpp @@ -72,7 +72,7 @@ TableCapillaryPressure::TableCapillaryPressure( std::string const & name, registerWrapper( viewKeyStruct::inverseCapPresWrappersString(), &m_inverseCapPresWrappers ). setSizedFromParent( 0 ). - setRestartFlags( RestartFlags::NO_WRITE ); + setRestartFlags( RestartFlags::NO_WRITE ); } void TableCapillaryPressure::postInputInitialization() diff --git a/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressure.hpp b/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressure.hpp index 7a018204287..5d132d3636a 100644 --- a/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressure.hpp +++ b/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressure.hpp @@ -127,7 +127,7 @@ class TableCapillaryPressure : public CapillaryPressureBase array1d< TableFunction::KernelWrapper > m_capPresKernelWrappers; array1d< TableFunction::KernelWrapper > m_inverseCapPresWrappers; - std::vector< std::shared_ptr > m_inverseTables; + std::vector< std::shared_ptr< TableFunction > > m_inverseTables; }; @@ -203,7 +203,7 @@ TableCapillaryPressure::KernelWrapper:: // put capillary pressure on the wetting phase real64 capPresWater = phaseCapPres[ipWater]; - array1d input(1); + array1d< real64 > input( 1 ); input[0] = capPresWater; auto inputSlice = input.toSliceConst(); @@ -211,9 +211,9 @@ TableCapillaryPressure::KernelWrapper:: m_capPresKernelWrappers[0].compute( &(phaseCapPres)[ipWater], &(dPhaseCapPres_dPhaseVolFrac)[ipWater][ipWater] ); phaseVolFraction[ipWater] = - m_inverseCapPresWrappers[0].compute( inputSlice, - &(dPhaseCapPres_dPhaseVolFrac)[ipWater][ipWater] ); - phaseVolFraction[ipGas] = 1.0 - phaseVolFraction[ipWater]; + m_inverseCapPresWrappers[0].compute( inputSlice, + &(dPhaseCapPres_dPhaseVolFrac)[ipWater][ipWater] ); + phaseVolFraction[ipGas] = 1.0 - phaseVolFraction[ipWater]; } diff --git a/src/coreComponents/constitutive/capillaryPressure/VanGenuchtenCapillaryPressure.hpp b/src/coreComponents/constitutive/capillaryPressure/VanGenuchtenCapillaryPressure.hpp index 798815cd877..6ac95221027 100644 --- a/src/coreComponents/constitutive/capillaryPressure/VanGenuchtenCapillaryPressure.hpp +++ b/src/coreComponents/constitutive/capillaryPressure/VanGenuchtenCapillaryPressure.hpp @@ -56,11 +56,11 @@ class VanGenuchtenCapillaryPressureUpdate final : public CapillaryPressureBaseUp void compute( arraySlice1d< real64 const, compflow::USD_PHASE - 1 > const & phaseVolFraction, arraySlice1d< real64, cappres::USD_CAPPRES - 2 > const & phaseCapPres, arraySlice2d< real64, cappres::USD_CAPPRES_DS - 2 > const & dPhaseCapPres_dPhaseVolFrac ) const; - + GEOS_HOST_DEVICE void computeInv( arraySlice1d< real64 const, compflow::USD_PHASE - 1 > const & phaseVolFraction, - arraySlice1d< real64, cappres::USD_CAPPRES - 2 > const & phaseCapPres, - arraySlice2d< real64, cappres::USD_CAPPRES_DS - 2 > const & dPhaseCapPres_dPhaseVolFrac ) const; + arraySlice1d< real64, cappres::USD_CAPPRES - 2 > const & phaseCapPres, + arraySlice2d< real64, cappres::USD_CAPPRES_DS - 2 > const & dPhaseCapPres_dPhaseVolFrac ) const; GEOS_HOST_DEVICE virtual void update( localIndex const k, @@ -198,8 +198,8 @@ GEOS_HOST_DEVICE inline void VanGenuchtenCapillaryPressureUpdate:: computeInv( arraySlice1d< real64 const, compflow::USD_PHASE - 1 > const & phaseVolFraction, - arraySlice1d< real64, cappres::USD_CAPPRES - 2 > const & phaseCapPres, - arraySlice2d< real64, cappres::USD_CAPPRES_DS - 2 > const & dPhaseCapPres_dPhaseVolFrac ) const + arraySlice1d< real64, cappres::USD_CAPPRES - 2 > const & phaseCapPres, + arraySlice2d< real64, cappres::USD_CAPPRES_DS - 2 > const & dPhaseCapPres_dPhaseVolFrac ) const { LvArray::forValuesInSlice( dPhaseCapPres_dPhaseVolFrac, []( real64 & val ){ val = 0.0; } ); diff --git a/src/coreComponents/constitutive/unitTests/testCO2SpycherPruessModels.cpp.uncrustify b/src/coreComponents/constitutive/unitTests/testCO2SpycherPruessModels.cpp.uncrustify new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/coreComponents/integrationTests/fluidFlowTests/CMakeLists.txt b/src/coreComponents/integrationTests/fluidFlowTests/CMakeLists.txt index 951cac7c502..9a89d938e2e 100644 --- a/src/coreComponents/integrationTests/fluidFlowTests/CMakeLists.txt +++ b/src/coreComponents/integrationTests/fluidFlowTests/CMakeLists.txt @@ -4,6 +4,7 @@ set( gtest_geosx_tests testThermalSinglePhaseFlow.cpp testTransmissibility.cpp testImmiscibleMultiphaseFlow.cpp + testImmiscibleInterfaceConditions.cpp testSinglePhaseMFDPolyhedral.cpp testSinglePhaseReactiveTransport.cpp ) diff --git a/src/coreComponents/integrationTests/fluidFlowTests/testImmiscibleInterfaceConditions.cpp b/src/coreComponents/integrationTests/fluidFlowTests/testImmiscibleInterfaceConditions.cpp index 95431c366a4..be96c05aa4d 100644 --- a/src/coreComponents/integrationTests/fluidFlowTests/testImmiscibleInterfaceConditions.cpp +++ b/src/coreComponents/integrationTests/fluidFlowTests/testImmiscibleInterfaceConditions.cpp @@ -26,11 +26,11 @@ #include "constitutive/fluid/twophaseimmisciblefluid/TwoPhaseImmiscibleFluid.hpp" #include "physicsSolvers/PhysicsSolverManager.hpp" #include "physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp" -#include "unitTests/fluidFlowTests/testCompFlowUtils.hpp" +#include "integrationTests/fluidFlowTests/testCompFlowUtils.hpp" #include "constitutive/unitTests/FluidModelTest.hpp" #include "constitutive/unitTests/FluidModelTest_impl.hpp" #include "common/initializeEnvironment.hpp" -#include "unitTests/constitutiveTests/constitutiveTestHelpers.hpp" +#include "constitutive/relativePermeability/unitTests/constitutiveTestHelpers.hpp" #include "functions/FunctionManager.hpp" #include "constitutive/capillaryPressure/CapillaryPressureFields.hpp" @@ -481,7 +481,7 @@ RelativePermeabilityBase & makeBrooksCoreyRelPerm( string const & name, Group & class ImmiscibleInterfaceConditionsTest : public FluidModelTest< TwoPhaseImmiscibleFluid, 2 > { public: - ImmiscibleInterfaceConditionsTest(): state( std::make_unique< CommandLineOptions >( g_commandLineOptions )), + ImmiscibleInterfaceConditionsTest(): state( std::make_unique< CommandLineOptions >( g_commandLineOptions )), m_parent( "TestParentGroup", m_node ) {} @@ -547,8 +547,8 @@ TEST_F( ImmiscibleInterfaceConditionsTest, LocalNonlinearSolverConvergence ) stdVector< real64 > gravCoefs = {465.97500000000002, 515.02499999999998}; - stdVector< real64 > phi = {0.0, 0.0}; - stdVector< real64 > grad_phi = {0.0, 0.0, 0.0, 0.0}; + std::vector< real64 > phi = {0.0, 0.0}; + std::vector< real64 > grad_phi = {0.0, 0.0, 0.0, 0.0}; std::ofstream outFile( "local_solver_results.csv" ); @@ -586,9 +586,18 @@ TEST_F( ImmiscibleInterfaceConditionsTest, LocalNonlinearSolverConvergence ) auto t0 = std::chrono::high_resolution_clock::now(); + // Define missing arguments for the updated signature + stdVector< real64 > cellCenterDuT = { 0.0, 0.0 }; + stdVector< real64 > cellCenterDens = { 0.0, 0.0 }; + stdVector< real64 > cellCenterDens_dP = { 0.0, 0.0 }; + std::vector< real64 > grad_phi_P = { 0.0, 0.0 }; + std::vector< real64 > grad_phi_S = { 0.0, 0.0 }; + bool converged; + // Call the GEOS local solver geos::immiscibleMultiphaseKernels::local_solver( uT, saturations, pressures, JFMultipliers, trappedSats1, trappedSats2, transHats, dTransHats_dP, gravCoefHats, gravCoefs, - relPerms, capPressures, fluids, phi, grad_phi ); + cellCenterDuT, cellCenterDens, cellCenterDens_dP, + relPerms, capPressures, fluids, phi, grad_phi_P, grad_phi_S, converged ); auto t1 = std::chrono::high_resolution_clock::now(); std::chrono::duration elapsed = t1 - t0; @@ -600,17 +609,17 @@ std::cout << "Local solver time: " << elapsed.count() << " s" << std::endl; outFile << GEOS_FMT( ",{:10.10e}", saturations[1] ); outFile << GEOS_FMT( ",{:10.10e}", phi[0] ); outFile << GEOS_FMT( ",{:10.10e}", phi[1] ); - outFile << GEOS_FMT( ",{:10.10e}", grad_phi[0] ); - outFile << GEOS_FMT( ",{:10.10e}", grad_phi[1] ); - outFile << GEOS_FMT( ",{:10.10e}", grad_phi[2] ); - outFile << GEOS_FMT( ",{:10.10e}", grad_phi[3] ); + outFile << GEOS_FMT( ",{:10.10e}", grad_phi_P[0] ); + outFile << GEOS_FMT( ",{:10.10e}", grad_phi_P[1] ); + outFile << GEOS_FMT( ",{:10.10e}", grad_phi_S[0] ); + outFile << GEOS_FMT( ",{:10.10e}", grad_phi_S[1] ); outFile << std::endl; phi[0] = 0; phi[1] = 0; - grad_phi[0] = 0; - grad_phi[1] = 0; - grad_phi[2] = 0; - grad_phi[3] = 0; + grad_phi_P[0] = 0; + grad_phi_P[1] = 0; + grad_phi_S[0] = 0; + grad_phi_S[1] = 0; // } // } @@ -674,4 +683,4 @@ int main( int argc, char * *argv ) // sat[1] = 1 - sat[0]; // } -// } \ No newline at end of file +// } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index 5b60a07045d..ec169a7e330 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -31,1616 +31,1615 @@ #include "constitutive/capillaryPressure/CapillaryPressureFields.hpp" #include "constitutive/capillaryPressure/CapillaryPressureSelector.hpp" #include "constitutive/relativePermeability/RelativePermeabilitySelector.hpp" - + #include "fieldSpecification/EquilibriumInitialCondition.hpp" #include "fieldSpecification/SourceFluxBoundaryCondition.hpp" #include "physicsSolvers/fluidFlow/SourceFluxStatistics.hpp" #include "physicsSolvers/LogLevelsInfo.hpp" - + #include "constitutive/ConstitutivePassThru.hpp" #include "constitutive/fluid/twophaseimmisciblefluid/TwoPhaseImmiscibleFluid.hpp" - + #include - + #if defined( __INTEL_COMPILER ) #pragma GCC optimize "O0" #endif - - namespace geos - { - - using namespace dataRepository; - using namespace constitutive; - using namespace fields::immiscibleMultiphaseFlow; - using namespace immiscibleMultiphaseKernels; - - - ImmiscibleMultiphaseFlow::ImmiscibleMultiphaseFlow( const string & name, - Group * const parent ) - : - FlowSolverBase( name, parent ), - m_numPhases( 2 ), - m_hasCapPressure( false ), - m_useTotalMassEquation ( 1 ) - { - this->registerWrapper( viewKeyStruct::inputTemperatureString(), &m_inputTemperature ). - setInputFlag( InputFlags::REQUIRED ). - setDescription( "Temperature" ); - - this->registerWrapper( viewKeyStruct::useTotalMassEquationString(), &m_useTotalMassEquation ). - setSizedFromParent( 0 ). - setInputFlag( InputFlags::OPTIONAL ). - setApplyDefaultValue( 1 ). - setDescription( "Flag indicating whether total mass equation is used" ); - - this->registerWrapper( viewKeyStruct::gravityDensitySchemeString(), &m_gravityDensityScheme ). - setSizedFromParent( 0 ). - setInputFlag( InputFlags::OPTIONAL ). - setApplyDefaultValue( GravityDensityScheme::ArithmeticAverage ). - setDescription( "Scheme for density treatment in gravity" ); - - this->registerWrapper( viewKeyStruct::solutionChangeScalingFactorString(), &m_solutionChangeScalingFactor ). - setSizedFromParent( 0 ). - setInputFlag( InputFlags::OPTIONAL ). - setApplyDefaultValue( 0.5 ). - setDescription( "Damping factor for solution change targets" ); - this->registerWrapper( viewKeyStruct::targetRelativePresChangeString(), &m_targetRelativePresChange ). - setSizedFromParent( 0 ). - setInputFlag( InputFlags::OPTIONAL ). - setApplyDefaultValue( 0.2 ). - setDescription( "Target (relative) change in pressure in a time step (expected value between 0 and 1)" ); - this->registerWrapper( viewKeyStruct::targetPhaseVolFracChangeString(), &m_targetPhaseVolFracChange ). - setSizedFromParent( 0 ). - setInputFlag( InputFlags::OPTIONAL ). - setApplyDefaultValue( 0.2 ). - setDescription( "Target (absolute) change in phase volume fraction in a time step" ); - - this->registerWrapper( viewKeyStruct::interfaceFaceSetNamesString(), - &m_interfaceFaceSetNames ). - setInputFlag( InputFlags::OPTIONAL ). - setDescription( "Names of the interface face sets" ); - } - - void ImmiscibleMultiphaseFlow::postInputInitialization() - { - FlowSolverBase::postInputInitialization(); - } - - void ImmiscibleMultiphaseFlow::registerDataOnMesh( Group & meshBodies ) - { - FlowSolverBase::registerDataOnMesh( meshBodies ); - - // 0. Find a "reference" fluid model name (at this point, models are already attached to subregions) - forDiscretizationOnMeshTargets( meshBodies, [&]( string const &, - MeshLevel & mesh, - string_array const & regionNames ) - { - mesh.getElemManager().forElementSubRegions( regionNames, - [&]( localIndex const, - ElementSubRegionBase & subRegion ) - { - // If at least one region has a capillary pressure model, consider it enabled for all - string const capPresName = getConstitutiveName< CapillaryPressureBase >( subRegion ); - if( !capPresName.empty() ) - { - m_hasCapPressure = true; - } - } ); - } ); - - m_numDofPerCell = m_numPhases; - - // 2. Register and resize all fields as necessary - forDiscretizationOnMeshTargets( meshBodies, [&]( string const &, - MeshLevel & mesh, - string_array const & regionNames ) - { - mesh.getElemManager().forElementSubRegions( regionNames, - [&]( localIndex const, - ElementSubRegionBase & subRegion ) - { - if( m_hasCapPressure ) - { - subRegion.registerWrapper< string >( viewKeyStruct::capPressureNamesString() ). - setPlotLevel( PlotLevel::NOPLOT ). - setRestartFlags( RestartFlags::NO_WRITE ). - setSizedFromParent( 0 ). - setDescription( "Name of the capillary pressure constitutive model to use" ). - reference(); - - string & capPresName = subRegion.getReference< string >( viewKeyStruct::capPressureNamesString() ); - capPresName = getConstitutiveName< CapillaryPressureBase >( subRegion ); - GEOS_THROW_IF( capPresName.empty(), - GEOS_FMT( "{}: Capillary pressure model not found on subregion {}", - getDataContext(), subRegion.getDataContext() ), - InputError ); - } - - // The resizing of the arrays needs to happen here, before the call to initializePreSubGroups, - // to make sure that the dimensions are properly set before the timeHistoryOutput starts its initialization. - subRegion.registerField< phaseVolumeFraction >( getName() ). - reference().resizeDimension< 1 >( m_numPhases ); - - subRegion.registerField< phaseVolumeFraction_n >( getName() ). - reference().resizeDimension< 1 >( m_numPhases ); - - subRegion.registerField< bcPhaseVolumeFraction >( getName() ). - reference().resizeDimension< 1 >( m_numPhases ); - - subRegion.registerField< phaseMass >( getName() ). - reference().resizeDimension< 1 >( m_numPhases ); - - subRegion.registerField< phaseMass_n >( getName() ). - reference().resizeDimension< 1 >( m_numPhases ); - - subRegion.registerField< phaseMobility >( getName() ). - reference().resizeDimension< 1 >( m_numPhases ); - - subRegion.registerField< dPhaseMobility >( getName() ). - reference().resizeDimension< 1, 2 >( m_numPhases, m_numPhases ); // dP, dS - - } ); - - } ); - } - - void ImmiscibleMultiphaseFlow::setConstitutiveNames( ElementSubRegionBase & subRegion ) const - { - setConstitutiveName< TwoPhaseImmiscibleFluid >( subRegion, viewKeyStruct::fluidNamesString(), "two phase immiscible fluid" ); - - setConstitutiveName< RelativePermeabilityBase >( subRegion, viewKeyStruct::relPermNamesString(), "relative permeability" ); - } - - void ImmiscibleMultiphaseFlow::initializePreSubGroups() - { - m_linearSolverParameters.get().mgr.strategy = LinearSolverParameters::MGR::StrategyType::immiscibleMultiphaseFVM; - - FlowSolverBase::initializePreSubGroups(); - - DomainPartition & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" ); - - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel & mesh, - string_array const & regionNames ) - { - mesh.getElemManager().forElementSubRegions( regionNames, - [&]( localIndex const, - ElementSubRegionBase & subRegion ) - { - arrayView1d< real64 > const temp = subRegion.getField< fields::flow::temperature >(); - temp.setValues< parallelHostPolicy >( m_inputTemperature ); - } ); - } ); - - // ***** Create FaceElements ***** - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel & meshLevel, - string_array const & GEOS_UNUSED_PARAM( regionNames )) - { - - FaceManager const & faceManager = meshLevel.getFaceManager(); - Group const & faceSetGroup = faceManager.sets(); - ElementRegionManager & elemManager = meshLevel.getElemManager(); - m_interfaceConstitutivePairs.resize( m_interfaceFaceSetNames.size() ); - - // this is the FaceElement Level - for( size_t surfaceRegionIndex=0; surfaceRegionIndex < m_interfaceFaceSetNames.size(); ++surfaceRegionIndex ) - { - string const & faceSetName = m_interfaceFaceSetNames[surfaceRegionIndex]; - SortedArrayView< localIndex const > const & faceSet = faceSetGroup.getReference< SortedArray< localIndex > >( faceSetName ); - SurfaceElementRegion & faceRegion = elemManager.getRegion< SurfaceElementRegion >( faceSetName ); - - for( localIndex const faceIndex : faceSet ) - { - localIndex const faceIndices[2] = { faceIndex, faceIndex }; - faceRegion.addToSurfaceMesh( &faceManager, faceIndices ); - } - - FaceElementSubRegion const & faceSubRegion = faceRegion.getUniqueSubRegion< FaceElementSubRegion >(); - FixedToManyElementRelation const & faceElementsToCells = faceSubRegion.getToCellRelation(); - - std::function< std::tuple< CellElementSubRegion *, CellElementSubRegion * >(localIndex) > getSubregions = [&]( localIndex surfaceSubRegionIndex ) -> std::tuple< CellElementSubRegion *, - CellElementSubRegion * > - { - - int regionIdx0 = faceElementsToCells.m_toElementRegion[surfaceSubRegionIndex][0]; - int regionIdx1 = faceElementsToCells.m_toElementRegion[surfaceSubRegionIndex][1]; - int subRegionIdx0 = faceElementsToCells.m_toElementSubRegion[surfaceSubRegionIndex][0]; - int subRegionIdx1 = faceElementsToCells.m_toElementSubRegion[surfaceSubRegionIndex][1]; - - CellElementRegion & region0 = elemManager.getRegion< CellElementRegion >( regionIdx0 ); - CellElementRegion & region1 = elemManager.getRegion< CellElementRegion >( regionIdx1 ); - - CellElementSubRegion * subRegion0 = ®ion0.getSubRegion< CellElementSubRegion >( subRegionIdx0 ); - CellElementSubRegion * subRegion1 = ®ion1.getSubRegion< CellElementSubRegion >( subRegionIdx1 ); - return std::make_tuple( subRegion0, subRegion1 ); - }; - + +namespace geos +{ + +using namespace dataRepository; +using namespace constitutive; +using namespace fields::immiscibleMultiphaseFlow; +using namespace immiscibleMultiphaseKernels; + + +ImmiscibleMultiphaseFlow::ImmiscibleMultiphaseFlow( const string & name, + Group * const parent ) + : + FlowSolverBase( name, parent ), + m_numPhases( 2 ), + m_hasCapPressure( false ), + m_useTotalMassEquation ( 1 ) +{ + this->registerWrapper( viewKeyStruct::inputTemperatureString(), &m_inputTemperature ). + setInputFlag( InputFlags::REQUIRED ). + setDescription( "Temperature" ); + + this->registerWrapper( viewKeyStruct::useTotalMassEquationString(), &m_useTotalMassEquation ). + setSizedFromParent( 0 ). + setInputFlag( InputFlags::OPTIONAL ). + setApplyDefaultValue( 1 ). + setDescription( "Flag indicating whether total mass equation is used" ); + + this->registerWrapper( viewKeyStruct::gravityDensitySchemeString(), &m_gravityDensityScheme ). + setSizedFromParent( 0 ). + setInputFlag( InputFlags::OPTIONAL ). + setApplyDefaultValue( GravityDensityScheme::ArithmeticAverage ). + setDescription( "Scheme for density treatment in gravity" ); + + this->registerWrapper( viewKeyStruct::solutionChangeScalingFactorString(), &m_solutionChangeScalingFactor ). + setSizedFromParent( 0 ). + setInputFlag( InputFlags::OPTIONAL ). + setApplyDefaultValue( 0.5 ). + setDescription( "Damping factor for solution change targets" ); + this->registerWrapper( viewKeyStruct::targetRelativePresChangeString(), &m_targetRelativePresChange ). + setSizedFromParent( 0 ). + setInputFlag( InputFlags::OPTIONAL ). + setApplyDefaultValue( 0.2 ). + setDescription( "Target (relative) change in pressure in a time step (expected value between 0 and 1)" ); + this->registerWrapper( viewKeyStruct::targetPhaseVolFracChangeString(), &m_targetPhaseVolFracChange ). + setSizedFromParent( 0 ). + setInputFlag( InputFlags::OPTIONAL ). + setApplyDefaultValue( 0.2 ). + setDescription( "Target (absolute) change in phase volume fraction in a time step" ); + + this->registerWrapper( viewKeyStruct::interfaceFaceSetNamesString(), + &m_interfaceFaceSetNames ). + setInputFlag( InputFlags::OPTIONAL ). + setDescription( "Names of the interface face sets" ); +} + +void ImmiscibleMultiphaseFlow::postInputInitialization() +{ + FlowSolverBase::postInputInitialization(); +} + +void ImmiscibleMultiphaseFlow::registerDataOnMesh( Group & meshBodies ) +{ + FlowSolverBase::registerDataOnMesh( meshBodies ); + + // 0. Find a "reference" fluid model name (at this point, models are already attached to subregions) + forDiscretizationOnMeshTargets( meshBodies, [&]( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + mesh.getElemManager().forElementSubRegions( regionNames, + [&]( localIndex const, + ElementSubRegionBase & subRegion ) + { + // If at least one region has a capillary pressure model, consider it enabled for all + string const capPresName = getConstitutiveName< CapillaryPressureBase >( subRegion ); + if( !capPresName.empty() ) + { + m_hasCapPressure = true; + } + } ); + } ); + + m_numDofPerCell = m_numPhases; + + // 2. Register and resize all fields as necessary + forDiscretizationOnMeshTargets( meshBodies, [&]( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + mesh.getElemManager().forElementSubRegions( regionNames, + [&]( localIndex const, + ElementSubRegionBase & subRegion ) + { + if( m_hasCapPressure ) + { + subRegion.registerWrapper< string >( viewKeyStruct::capPressureNamesString() ). + setPlotLevel( PlotLevel::NOPLOT ). + setRestartFlags( RestartFlags::NO_WRITE ). + setSizedFromParent( 0 ). + setDescription( "Name of the capillary pressure constitutive model to use" ). + reference(); + + string & capPresName = subRegion.getReference< string >( viewKeyStruct::capPressureNamesString() ); + capPresName = getConstitutiveName< CapillaryPressureBase >( subRegion ); + GEOS_THROW_IF( capPresName.empty(), + GEOS_FMT( "{}: Capillary pressure model not found on subregion {}", + getDataContext(), subRegion.getDataContext() ), + InputError ); + } + + // The resizing of the arrays needs to happen here, before the call to initializePreSubGroups, + // to make sure that the dimensions are properly set before the timeHistoryOutput starts its initialization. + subRegion.registerField< phaseVolumeFraction >( getName() ). + reference().resizeDimension< 1 >( m_numPhases ); + + subRegion.registerField< phaseVolumeFraction_n >( getName() ). + reference().resizeDimension< 1 >( m_numPhases ); + + subRegion.registerField< bcPhaseVolumeFraction >( getName() ). + reference().resizeDimension< 1 >( m_numPhases ); + + subRegion.registerField< phaseMass >( getName() ). + reference().resizeDimension< 1 >( m_numPhases ); + + subRegion.registerField< phaseMass_n >( getName() ). + reference().resizeDimension< 1 >( m_numPhases ); + + subRegion.registerField< phaseMobility >( getName() ). + reference().resizeDimension< 1 >( m_numPhases ); + + subRegion.registerField< dPhaseMobility >( getName() ). + reference().resizeDimension< 1, 2 >( m_numPhases, m_numPhases ); // dP, dS + + } ); + + } ); +} + +void ImmiscibleMultiphaseFlow::setConstitutiveNames( ElementSubRegionBase & subRegion ) const +{ + setConstitutiveName< TwoPhaseImmiscibleFluid >( subRegion, viewKeyStruct::fluidNamesString(), "two phase immiscible fluid" ); + + setConstitutiveName< RelativePermeabilityBase >( subRegion, viewKeyStruct::relPermNamesString(), "relative permeability" ); +} + +void ImmiscibleMultiphaseFlow::initializePreSubGroups() +{ + m_linearSolverParameters.get().mgr.strategy = LinearSolverParameters::MGR::StrategyType::immiscibleMultiphaseFVM; + + FlowSolverBase::initializePreSubGroups(); + + DomainPartition & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" ); + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + mesh.getElemManager().forElementSubRegions( regionNames, + [&]( localIndex const, + ElementSubRegionBase & subRegion ) + { + arrayView1d< real64 > const temp = subRegion.getField< fields::flow::temperature >(); + temp.setValues< parallelHostPolicy >( m_inputTemperature ); + } ); + } ); + + // ***** Create FaceElements ***** + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & meshLevel, + string_array const & GEOS_UNUSED_PARAM( regionNames )) + { + + FaceManager const & faceManager = meshLevel.getFaceManager(); + Group const & faceSetGroup = faceManager.sets(); + ElementRegionManager & elemManager = meshLevel.getElemManager(); + m_interfaceConstitutivePairs.resize( m_interfaceFaceSetNames.size() ); + + // this is the FaceElement Level + for( size_t surfaceRegionIndex=0; surfaceRegionIndex < m_interfaceFaceSetNames.size(); ++surfaceRegionIndex ) + { + string const & faceSetName = m_interfaceFaceSetNames[surfaceRegionIndex]; + SortedArrayView< localIndex const > const & faceSet = faceSetGroup.getReference< SortedArray< localIndex > >( faceSetName ); + SurfaceElementRegion & faceRegion = elemManager.getRegion< SurfaceElementRegion >( faceSetName ); + + for( localIndex const faceIndex : faceSet ) + { + localIndex const faceIndices[2] = { faceIndex, faceIndex }; + faceRegion.addToSurfaceMesh( &faceManager, faceIndices ); + } + + FaceElementSubRegion const & faceSubRegion = faceRegion.getUniqueSubRegion< FaceElementSubRegion >(); + FixedToManyElementRelation const & faceElementsToCells = faceSubRegion.getToCellRelation(); + + std::function< std::tuple< CellElementSubRegion *, CellElementSubRegion * >(localIndex) > getSubregions = [&]( localIndex surfaceSubRegionIndex ) -> std::tuple< CellElementSubRegion *, + CellElementSubRegion * > + { + + int regionIdx0 = faceElementsToCells.m_toElementRegion[surfaceSubRegionIndex][0]; + int regionIdx1 = faceElementsToCells.m_toElementRegion[surfaceSubRegionIndex][1]; + int subRegionIdx0 = faceElementsToCells.m_toElementSubRegion[surfaceSubRegionIndex][0]; + int subRegionIdx1 = faceElementsToCells.m_toElementSubRegion[surfaceSubRegionIndex][1]; + + CellElementRegion & region0 = elemManager.getRegion< CellElementRegion >( regionIdx0 ); + CellElementRegion & region1 = elemManager.getRegion< CellElementRegion >( regionIdx1 ); + + CellElementSubRegion * subRegion0 = ®ion0.getSubRegion< CellElementSubRegion >( subRegionIdx0 ); + CellElementSubRegion * subRegion1 = ®ion1.getSubRegion< CellElementSubRegion >( subRegionIdx1 ); + return std::make_tuple( subRegion0, subRegion1 ); + }; + // std::tuple< CellElementSubRegion *, CellElementSubRegion * > subRegionPair = getSubregions( surfaceRegionIndex ); // CellElementSubRegion * subRegion0 = std::get< 0 >( subRegionPair ); // CellElementSubRegion * subRegion1 = std::get< 1 >( subRegionPair ); - + // // get constitutives by type and name: relPerms, capPressures, Fluids (three pointers) // std::string & relPermName0 = subRegion0->getReference< std::string >( viewKeyStruct::relPermNamesString()); // std::string & relPermName1 = subRegion1->getReference< std::string >( viewKeyStruct::relPermNamesString()); // RelativePermeabilityBase * relPerm0 = &getConstitutiveModel< RelativePermeabilityBase >( *subRegion0, relPermName0 ); // RelativePermeabilityBase * relPerm1 = &getConstitutiveModel< RelativePermeabilityBase >( *subRegion1, relPermName1 ); - + // std::string & cappresName0 = subRegion0->getReference< std::string >( viewKeyStruct::capPressureNamesString()); // std::string & cappresName1 = subRegion1->getReference< std::string >( viewKeyStruct::capPressureNamesString()); // CapillaryPressureBase * capPressure0 = &getConstitutiveModel< CapillaryPressureBase >( *subRegion0, cappresName0 ); // CapillaryPressureBase * capPressure1 = &getConstitutiveModel< CapillaryPressureBase >( *subRegion1, cappresName1 ); - + // std::string & fluidName0 = subRegion0->getReference< std::string >( viewKeyStruct::fluidNamesString() ); // std::string & fluidName1 = subRegion1->getReference< std::string >( viewKeyStruct::fluidNamesString() ); - + // TwoPhaseImmiscibleFluid * fluid0 = &getConstitutiveModel< TwoPhaseImmiscibleFluid >( *subRegion0, fluidName0 ); // TwoPhaseImmiscibleFluid * fluid1 = &getConstitutiveModel< TwoPhaseImmiscibleFluid >( *subRegion1, fluidName1 ); - + // m_interfaceConstitutivePairs[surfaceRegionIndex][0] = std::make_tuple( relPerm0, capPressure0, fluid0 ); // m_interfaceConstitutivePairs[surfaceRegionIndex][1] = std::make_tuple( relPerm1, capPressure1, fluid1 ); - // Find a representative face element in this surface region with two adjacent cells -localIndex fei = -1; + // Find a representative face element in this surface region with two adjacent cells + localIndex fei = -1; // Prefer face element 0 if valid; otherwise scan -if( faceElementsToCells.size() > 0 ) + if( faceElementsToCells.size() > 0 ) + { + // Check if face element 0 has two adjacent cells + if( faceElementsToCells.m_toElementRegion[0].size() >= 2 ) + { + fei = 0; + } + else + { + // Scan to find the first interior face element with two neighbors + for( localIndex i = 1; i < faceElementsToCells.size(); ++i ) + { + if( faceElementsToCells.m_toElementRegion[i].size() >= 2 ) + { + fei = i; + break; + } + } + } + } + +// If no valid face element, skip this surface region + if( fei < 0 ) + { + continue; + } + + std::tuple< CellElementSubRegion *, CellElementSubRegion * > subRegionPair = getSubregions( fei ); + CellElementSubRegion * subRegion0 = std::get< 0 >( subRegionPair ); + CellElementSubRegion * subRegion1 = std::get< 1 >( subRegionPair ); + +// get constitutives by type and name: relPerms, capPressures, Fluids (three pointers) + std::string & relPermName0 = subRegion0->getReference< std::string >( viewKeyStruct::relPermNamesString()); + std::string & relPermName1 = subRegion1->getReference< std::string >( viewKeyStruct::relPermNamesString()); + RelativePermeabilityBase * relPerm0 = &getConstitutiveModel< RelativePermeabilityBase >( *subRegion0, relPermName0 ); + RelativePermeabilityBase * relPerm1 = &getConstitutiveModel< RelativePermeabilityBase >( *subRegion1, relPermName1 ); + + std::string & cappresName0 = subRegion0->getReference< std::string >( viewKeyStruct::capPressureNamesString()); + std::string & cappresName1 = subRegion1->getReference< std::string >( viewKeyStruct::capPressureNamesString()); + CapillaryPressureBase * capPressure0 = &getConstitutiveModel< CapillaryPressureBase >( *subRegion0, cappresName0 ); + CapillaryPressureBase * capPressure1 = &getConstitutiveModel< CapillaryPressureBase >( *subRegion1, cappresName1 ); + + std::string & fluidName0 = subRegion0->getReference< std::string >( viewKeyStruct::fluidNamesString() ); + std::string & fluidName1 = subRegion1->getReference< std::string >( viewKeyStruct::fluidNamesString() ); + + TwoPhaseImmiscibleFluid * fluid0 = &getConstitutiveModel< TwoPhaseImmiscibleFluid >( *subRegion0, fluidName0 ); + TwoPhaseImmiscibleFluid * fluid1 = &getConstitutiveModel< TwoPhaseImmiscibleFluid >( *subRegion1, fluidName1 ); + + m_interfaceConstitutivePairs[surfaceRegionIndex][0] = std::make_tuple( relPerm0, capPressure0, fluid0 ); + m_interfaceConstitutivePairs[surfaceRegionIndex][1] = std::make_tuple( relPerm1, capPressure1, fluid1 ); + + } + } ); + +} + + +void ImmiscibleMultiphaseFlow::updateFluidModel( ObjectManagerBase & dataGroup ) const { - // Check if face element 0 has two adjacent cells - if( faceElementsToCells.m_toElementRegion[0].size() >= 2 ) + GEOS_MARK_FUNCTION; + + arrayView1d< real64 const > const pres = dataGroup.getField< fields::flow::pressure >(); + + TwoPhaseImmiscibleFluid & fluid = getConstitutiveModel< TwoPhaseImmiscibleFluid >( dataGroup, dataGroup.getReference< string >( viewKeyStruct::fluidNamesString() ) ); + + constitutiveUpdatePassThru( fluid, [&] ( auto & castedFluid ) { - fei = 0; + using FluidType = TYPEOFREF( castedFluid ); + typename FluidType::KernelWrapper fluidWrapper = castedFluid.createKernelWrapper(); + + FluidUpdateKernel::launch< parallelDevicePolicy<> >( dataGroup.size(), fluidWrapper, pres ); + } ); +} + + +void ImmiscibleMultiphaseFlow::updateRelPermModel( ObjectManagerBase & dataGroup ) const +{ + GEOS_MARK_FUNCTION; + + + GEOS_UNUSED_VAR( dataGroup ); + + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac = + dataGroup.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); + + string const & relPermName = dataGroup.getReference< string >( viewKeyStruct::relPermNamesString() ); + RelativePermeabilityBase & relPerm = getConstitutiveModel< RelativePermeabilityBase >( dataGroup, relPermName ); + + constitutive::constitutiveUpdatePassThru( relPerm, [&] ( auto & castedRelPerm ) + { + typename TYPEOFREF( castedRelPerm ) ::KernelWrapper relPermWrapper = castedRelPerm.createKernelWrapper(); + + isothermalCompositionalMultiphaseBaseKernels:: + RelativePermeabilityUpdateKernel:: + launch< parallelDevicePolicy<> >( dataGroup.size(), + relPermWrapper, + phaseVolFrac ); + } ); +} + +void ImmiscibleMultiphaseFlow::updateCapPressureModel( ObjectManagerBase & dataGroup ) const +{ + GEOS_MARK_FUNCTION; + + if( m_hasCapPressure ) + { + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac = + dataGroup.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); + + string const & cappresName = dataGroup.getReference< string >( viewKeyStruct::capPressureNamesString() ); + CapillaryPressureBase & capPressure = getConstitutiveModel< CapillaryPressureBase >( dataGroup, cappresName ); + + constitutive::constitutiveUpdatePassThru( capPressure, [&] ( auto & castedCapPres ) + { + typename TYPEOFREF( castedCapPres ) ::KernelWrapper capPresWrapper = castedCapPres.createKernelWrapper(); + + // isothermalCompositionalMultiphaseBaseKernels:: + immiscibleMultiphaseKernels:: + CapillaryPressureUpdateKernel:: + launch< parallelDevicePolicy<> >( dataGroup.size(), + capPresWrapper, + phaseVolFrac ); + } ); } - else +} + + +void ImmiscibleMultiphaseFlow::updateFluidState( ElementSubRegionBase & subRegion ) const +{ + GEOS_MARK_FUNCTION; + + updateFluidModel( subRegion ); + updateVolumeConstraint( subRegion ); + updatePhaseMass( subRegion ); + updateRelPermModel( subRegion ); + updatePhaseMobility( subRegion ); + updateCapPressureModel( subRegion ); +} + + +void ImmiscibleMultiphaseFlow::updatePhaseMass( ElementSubRegionBase & subRegion ) const +{ + GEOS_MARK_FUNCTION; + + string const & solidName = subRegion.getReference< string >( viewKeyStruct::solidNamesString() ); + string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); + + TwoPhaseImmiscibleFluid const & fluid = getConstitutiveModel< TwoPhaseImmiscibleFluid >( subRegion, fluidName ); + CoupledSolidBase const & solid = getConstitutiveModel< CoupledSolidBase >( subRegion, solidName ); + + arrayView1d< real64 const > const volume = subRegion.getElementVolume(); + arrayView2d< real64 const > const porosity = solid.getPorosity(); + + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac= subRegion.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); + arrayView3d< real64 const, multifluid::USD_PHASE > phaseDens = fluid.phaseDensity(); + arrayView2d< real64, immiscibleFlow::USD_PHASE > const phaseMass = subRegion.getField< fields::immiscibleMultiphaseFlow::phaseMass >(); + + // Might be needed for geomechanics????? if so, need to change the accumulation as well? + //arrayView1d< real64 > const deltaVolume = subRegion.getField< fields::flow::deltaVolume >(); + + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const ei ) + { + real64 const poreVolume = volume[ei] * porosity[ei][0]; + for( integer ip = 0; ip < 2; ++ip ) + { + phaseMass[ei][ip] = poreVolume * phaseVolFrac[ei][ip] * phaseDens[ei][0][ip]; + } + } ); +} + + +void ImmiscibleMultiphaseFlow::updatePhaseMobility( ObjectManagerBase & dataGroup ) const +{ + GEOS_MARK_FUNCTION; + + // note that the phase mobility computed here also includes phase density + string const & fluidName = dataGroup.getReference< string >( viewKeyStruct::fluidNamesString() ); + TwoPhaseImmiscibleFluid const & fluid = getConstitutiveModel< TwoPhaseImmiscibleFluid >( dataGroup, fluidName ); + + string const & relpermName = dataGroup.getReference< string >( viewKeyStruct::relPermNamesString() ); + RelativePermeabilityBase const & relperm = getConstitutiveModel< RelativePermeabilityBase >( dataGroup, relpermName ); + + immiscibleMultiphaseKernels:: + PhaseMobilityKernelFactory:: + createAndLaunch< parallelDevicePolicy<> >( m_numPhases, + dataGroup, + fluid, + relperm ); +} + +void ImmiscibleMultiphaseFlow::initializeFluidState( MeshLevel & mesh, + string_array const & regionNames ) +{ + GEOS_MARK_FUNCTION; + + mesh.getElemManager().forElementSubRegions( regionNames, + [&]( localIndex const, + ElementSubRegionBase & subRegion ) + { + // 2. Assume global component fractions have been prescribed. + // Initialize constitutive state to get fluid density. + updateFluidModel( subRegion ); + + } ); + + // for some reason CUDA does not want the host_device lambda to be defined inside the generic lambda + // I need the exact type of the subRegion for updateSolidflowProperties to work well. + mesh.getElemManager().forElementSubRegions< CellElementSubRegion, + SurfaceElementSubRegion >( regionNames, [&]( localIndex const, + auto & subRegion ) + { + // 4. Initialize/update dependent state quantities + + // 4.1 Update the constitutive models that only depend on + // - the primary variables + // - the fluid constitutive quantities (as they have already been updated) + // We postpone the other constitutive models for now + // In addition, to avoid multiplying permeability/porosity bay netToGross in the assembly kernel, we do it once and for all here + arrayView1d< real64 const > const netToGross = subRegion.template getField< fields::flow::netToGross >(); + CoupledSolidBase const & porousSolid = + getConstitutiveModel< CoupledSolidBase >( subRegion, subRegion.template getReference< string >( viewKeyStruct::solidNamesString() ) ); + PermeabilityBase const & permeabilityModel = + getConstitutiveModel< PermeabilityBase >( subRegion, subRegion.template getReference< string >( viewKeyStruct::permeabilityNamesString() ) ); + permeabilityModel.scaleHorizontalPermeability( netToGross ); + porousSolid.scaleReferencePorosity( netToGross ); + saveConvergedState( subRegion ); // necessary for a meaningful porosity update in sequential schemes + updatePorosityAndPermeability( subRegion ); + + // Now, we initialize and update each constitutive model one by one + + // 4.2 Save the computed porosity into the old porosity + // + // Note: + // - This must be called after updatePorosityAndPermeability + // - This step depends on porosity + string const & solidName = subRegion.template getReference< string >( viewKeyStruct::solidNamesString() ); + CoupledSolidBase const & porousMaterial = getConstitutiveModel< CoupledSolidBase >( subRegion, solidName ); + porousMaterial.initializeState(); + + // 4.3 Initialize/update the relative permeability model using the initial phase volume fraction + // This is needed to handle relative permeability hysteresis + // Also, initialize the fluid model + // + // Note: + // - This must be called after updateVolumeConstraint + // - This step depends on phaseVolFraction + + // initialized phase volume fraction + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac = + subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); + + string const & relpermName = subRegion.template getReference< string >( viewKeyStruct::relPermNamesString() ); + RelativePermeabilityBase & relPermMaterial = + getConstitutiveModel< RelativePermeabilityBase >( subRegion, relpermName ); + relPermMaterial.saveConvergedPhaseVolFractionState( phaseVolFrac ); // this needs to happen before calling updateRelPermModel + updateRelPermModel( subRegion ); + relPermMaterial.saveConvergedState(); // this needs to happen after calling updateRelPermModel + + // 4.4 Then, we initialize/update the capillary pressure model + // + // Note: + // - This must be called after updatePorosityAndPermeability + // - This step depends on porosity and permeability + if( m_hasCapPressure ) + { + // initialized porosity + arrayView2d< real64 const > const porosity = porousMaterial.getPorosity(); + + string const & permName = subRegion.template getReference< string >( viewKeyStruct::permeabilityNamesString() ); + PermeabilityBase const & permeabilityMaterial = getConstitutiveModel< PermeabilityBase >( subRegion, permName ); + // initialized permeability + arrayView3d< real64 const > const permeability = permeabilityMaterial.permeability(); + + string const & capPressureName = subRegion.template getReference< string >( viewKeyStruct::capPressureNamesString() ); + CapillaryPressureBase const & capPressureMaterial = + getConstitutiveModel< CapillaryPressureBase >( subRegion, capPressureName ); + capPressureMaterial.initializeRockState( porosity, permeability ); // this needs to happen before calling updateCapPressureModel + updateCapPressureModel( subRegion ); + } + + // 4.5 Update the phase mobility + // + // Note: + // - This must be called after updateRelPermModel + // - This step depends phaseRelPerm + updatePhaseMobility( subRegion ); + + } ); + + // 5. Save initial pressure + mesh.getElemManager().forElementSubRegions( regionNames, [&]( localIndex const, + ElementSubRegionBase & subRegion ) + { + arrayView1d< real64 const > const pres = subRegion.getField< fields::flow::pressure >(); + arrayView1d< real64 > const initPres = subRegion.getField< fields::flow::initialPressure >(); + arrayView1d< real64 const > const temp = subRegion.getField< fields::flow::temperature >(); + arrayView1d< real64 > const initTemp = subRegion.template getField< fields::flow::initialTemperature >(); + initPres.setValues< parallelDevicePolicy<> >( pres ); + initTemp.setValues< parallelDevicePolicy<> >( temp ); + + // TODO: Missing updatePhaseMass? + } ); +} + + +void ImmiscibleMultiphaseFlow::initializePostInitialConditionsPreSubGroups() +{ + GEOS_MARK_FUNCTION; + + FlowSolverBase::initializePostInitialConditionsPreSubGroups(); + + DomainPartition & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" ); + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + FieldIdentifiers fieldsToBeSync; + fieldsToBeSync.addElementFields( { fields::flow::pressure::key(), + fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key() }, + regionNames ); + + CommunicationTools::getInstance().synchronizeFields( fieldsToBeSync, mesh, domain.getNeighbors(), false ); + } ); + + // Retrieve the numerical methods and finite volume manager + FiniteVolumeManager const & fvManager = domain.getNumericalMethodManager().getFiniteVolumeManager(); + FluxApproximationBase const & fluxApprox = fvManager.getFluxApproximation( m_discretizationName ); + const geos::string flux_approximation_name = fluxApprox.getName(); + + // Clear the existing mapping between connector indices and interface region indices + m_interfaceRegionByConnector.clear(); + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( std::string const &, + MeshLevel & meshLevel, + string_array const & GEOS_UNUSED_PARAM( regionNames )) { - // Scan to find the first interior face element with two neighbors - for( localIndex i = 1; i < faceElementsToCells.size(); ++i ) + // Access the face manager and retrieve the face set group for the current mesh level + FaceManager const & faceManager = meshLevel.getFaceManager(); + Group const & faceSetGroup = faceManager.sets(); + + // Access the connector indices map (face index → connector index) + Group & stencilGroup = + meshLevel.getGroup( FluxApproximationBase::groupKeyStruct::stencilMeshGroupString()) + .getGroup( flux_approximation_name ); + CellElementStencilTPFA & stencil = + stencilGroup.getReference< CellElementStencilTPFA >( + FluxApproximationBase::viewKeyStruct::cellStencilString()); + unordered_map< localIndex, localIndex > const & connectorIndices = stencil.getConnectorIndices(); + + // for all interface face sets to map connector indices to their corresponding interface region indices + for( size_t surfaceRegionIndex = 0; surfaceRegionIndex < m_interfaceFaceSetNames.size(); ++surfaceRegionIndex ) { - if( faceElementsToCells.m_toElementRegion[i].size() >= 2 ) + // Iterate over each face and associate its connector index + std::string const & faceSetName = m_interfaceFaceSetNames[surfaceRegionIndex]; + for( localIndex kf : faceSetGroup.getReference< SortedArray< localIndex > >( faceSetName )) { - fei = i; - break; + auto it = connectorIndices.find( kf ); + if( it != connectorIndices.end()) + { + // Map the connector index to the corresponding surface region index + m_interfaceRegionByConnector[it->second] = surfaceRegionIndex; + } } } - } + } ); + + + initializeState( domain ); } -// If no valid face element, skip this surface region -if( fei < 0 ) + +void +ImmiscibleMultiphaseFlow::implicitStepSetup( real64 const & GEOS_UNUSED_PARAM( time_n ), + real64 const & GEOS_UNUSED_PARAM( dt ), + DomainPartition & domain ) { - continue; + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + mesh.getElemManager().forElementSubRegions< CellElementSubRegion, + SurfaceElementSubRegion >( regionNames, + [&]( localIndex const, + auto & subRegion ) + { + saveConvergedState( subRegion ); + + // update porosity, permeability + updatePorosityAndPermeability( subRegion ); + // update all fluid properties + updateVolumeConstraint( subRegion ); + updateFluidState( subRegion ); + + // after the update, save the new saturation + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac = + subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); + + arrayView2d< real64, immiscibleFlow::USD_PHASE > const phaseVolFrac_n = + subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction_n >(); + phaseVolFrac_n.setValues< parallelDevicePolicy<> >( phaseVolFrac ); + + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const & phaseMass = + subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseMass >(); + + arrayView2d< real64, immiscibleFlow::USD_PHASE > const & phaseMass_n = + subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseMass_n >(); + phaseMass_n.setValues< parallelDevicePolicy<> >( phaseMass ); + + } ); + } ); } -std::tuple< CellElementSubRegion *, CellElementSubRegion * > subRegionPair = getSubregions( fei ); -CellElementSubRegion * subRegion0 = std::get< 0 >( subRegionPair ); -CellElementSubRegion * subRegion1 = std::get< 1 >( subRegionPair ); +void ImmiscibleMultiphaseFlow::assembleSystem( real64 const GEOS_UNUSED_PARAM( time_n ), + real64 const dt, + DomainPartition & domain, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) +{ + GEOS_MARK_FUNCTION; -// get constitutives by type and name: relPerms, capPressures, Fluids (three pointers) -std::string & relPermName0 = subRegion0->getReference< std::string >( viewKeyStruct::relPermNamesString()); -std::string & relPermName1 = subRegion1->getReference< std::string >( viewKeyStruct::relPermNamesString()); -RelativePermeabilityBase * relPerm0 = &getConstitutiveModel< RelativePermeabilityBase >( *subRegion0, relPermName0 ); -RelativePermeabilityBase * relPerm1 = &getConstitutiveModel< RelativePermeabilityBase >( *subRegion1, relPermName1 ); - -std::string & cappresName0 = subRegion0->getReference< std::string >( viewKeyStruct::capPressureNamesString()); -std::string & cappresName1 = subRegion1->getReference< std::string >( viewKeyStruct::capPressureNamesString()); -CapillaryPressureBase * capPressure0 = &getConstitutiveModel< CapillaryPressureBase >( *subRegion0, cappresName0 ); -CapillaryPressureBase * capPressure1 = &getConstitutiveModel< CapillaryPressureBase >( *subRegion1, cappresName1 ); - -std::string & fluidName0 = subRegion0->getReference< std::string >( viewKeyStruct::fluidNamesString() ); -std::string & fluidName1 = subRegion1->getReference< std::string >( viewKeyStruct::fluidNamesString() ); - -TwoPhaseImmiscibleFluid * fluid0 = &getConstitutiveModel< TwoPhaseImmiscibleFluid >( *subRegion0, fluidName0 ); -TwoPhaseImmiscibleFluid * fluid1 = &getConstitutiveModel< TwoPhaseImmiscibleFluid >( *subRegion1, fluidName1 ); - -m_interfaceConstitutivePairs[surfaceRegionIndex][0] = std::make_tuple( relPerm0, capPressure0, fluid0 ); -m_interfaceConstitutivePairs[surfaceRegionIndex][1] = std::make_tuple( relPerm1, capPressure1, fluid1 ); - - } - } ); - - } - - - void ImmiscibleMultiphaseFlow::updateFluidModel( ObjectManagerBase & dataGroup ) const - { - GEOS_MARK_FUNCTION; - - arrayView1d< real64 const > const pres = dataGroup.getField< fields::flow::pressure >(); - - TwoPhaseImmiscibleFluid & fluid = getConstitutiveModel< TwoPhaseImmiscibleFluid >( dataGroup, dataGroup.getReference< string >( viewKeyStruct::fluidNamesString() ) ); - - constitutiveUpdatePassThru( fluid, [&] ( auto & castedFluid ) - { - using FluidType = TYPEOFREF( castedFluid ); - typename FluidType::KernelWrapper fluidWrapper = castedFluid.createKernelWrapper(); - - FluidUpdateKernel::launch< parallelDevicePolicy<> >( dataGroup.size(), fluidWrapper, pres ); - } ); - } - - - void ImmiscibleMultiphaseFlow::updateRelPermModel( ObjectManagerBase & dataGroup ) const - { - GEOS_MARK_FUNCTION; - - - GEOS_UNUSED_VAR( dataGroup ); - - arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac = - dataGroup.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); - - string const & relPermName = dataGroup.getReference< string >( viewKeyStruct::relPermNamesString() ); - RelativePermeabilityBase & relPerm = getConstitutiveModel< RelativePermeabilityBase >( dataGroup, relPermName ); - - constitutive::constitutiveUpdatePassThru( relPerm, [&] ( auto & castedRelPerm ) - { - typename TYPEOFREF( castedRelPerm ) ::KernelWrapper relPermWrapper = castedRelPerm.createKernelWrapper(); - - isothermalCompositionalMultiphaseBaseKernels:: - RelativePermeabilityUpdateKernel:: - launch< parallelDevicePolicy<> >( dataGroup.size(), - relPermWrapper, - phaseVolFrac ); - } ); - } - - void ImmiscibleMultiphaseFlow::updateCapPressureModel( ObjectManagerBase & dataGroup ) const - { - GEOS_MARK_FUNCTION; - - if( m_hasCapPressure ) - { - arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac = - dataGroup.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); - - string const & cappresName = dataGroup.getReference< string >( viewKeyStruct::capPressureNamesString() ); - CapillaryPressureBase & capPressure = getConstitutiveModel< CapillaryPressureBase >( dataGroup, cappresName ); - - constitutive::constitutiveUpdatePassThru( capPressure, [&] ( auto & castedCapPres ) - { - typename TYPEOFREF( castedCapPres ) ::KernelWrapper capPresWrapper = castedCapPres.createKernelWrapper(); - - // isothermalCompositionalMultiphaseBaseKernels:: - immiscibleMultiphaseKernels:: - CapillaryPressureUpdateKernel:: - launch< parallelDevicePolicy<> >( dataGroup.size(), - capPresWrapper, - phaseVolFrac ); - } ); - } - } - - - void ImmiscibleMultiphaseFlow::updateFluidState( ElementSubRegionBase & subRegion ) const - { - GEOS_MARK_FUNCTION; - - updateFluidModel( subRegion ); - updateVolumeConstraint( subRegion ); - updatePhaseMass( subRegion ); - updateRelPermModel( subRegion ); - updatePhaseMobility( subRegion ); - updateCapPressureModel( subRegion ); - } - - - void ImmiscibleMultiphaseFlow::updatePhaseMass( ElementSubRegionBase & subRegion ) const - { - GEOS_MARK_FUNCTION; - - string const & solidName = subRegion.getReference< string >( viewKeyStruct::solidNamesString() ); - string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); - - TwoPhaseImmiscibleFluid const & fluid = getConstitutiveModel< TwoPhaseImmiscibleFluid >( subRegion, fluidName ); - CoupledSolidBase const & solid = getConstitutiveModel< CoupledSolidBase >( subRegion, solidName ); - - arrayView1d< real64 const > const volume = subRegion.getElementVolume(); - arrayView2d< real64 const > const porosity = solid.getPorosity(); - - arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac= subRegion.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); - arrayView3d< real64 const, multifluid::USD_PHASE > phaseDens = fluid.phaseDensity(); - arrayView2d< real64, immiscibleFlow::USD_PHASE > const phaseMass = subRegion.getField< fields::immiscibleMultiphaseFlow::phaseMass >(); - - // Might be needed for geomechanics????? if so, need to change the accumulation as well? - //arrayView1d< real64 > const deltaVolume = subRegion.getField< fields::flow::deltaVolume >(); - - forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const ei ) - { - real64 const poreVolume = volume[ei] * porosity[ei][0]; - for( integer ip = 0; ip < 2; ++ip ) - { - phaseMass[ei][ip] = poreVolume * phaseVolFrac[ei][ip] * phaseDens[ei][0][ip]; - } - } ); - } - - - void ImmiscibleMultiphaseFlow::updatePhaseMobility( ObjectManagerBase & dataGroup ) const - { - GEOS_MARK_FUNCTION; - - // note that the phase mobility computed here also includes phase density - string const & fluidName = dataGroup.getReference< string >( viewKeyStruct::fluidNamesString() ); - TwoPhaseImmiscibleFluid const & fluid = getConstitutiveModel< TwoPhaseImmiscibleFluid >( dataGroup, fluidName ); - - string const & relpermName = dataGroup.getReference< string >( viewKeyStruct::relPermNamesString() ); - RelativePermeabilityBase const & relperm = getConstitutiveModel< RelativePermeabilityBase >( dataGroup, relpermName ); - - immiscibleMultiphaseKernels:: - PhaseMobilityKernelFactory:: - createAndLaunch< parallelDevicePolicy<> >( m_numPhases, - dataGroup, - fluid, - relperm ); - } - - void ImmiscibleMultiphaseFlow::initializeFluidState( MeshLevel & mesh, - string_array const & regionNames ) - { - GEOS_MARK_FUNCTION; - - mesh.getElemManager().forElementSubRegions( regionNames, - [&]( localIndex const, - ElementSubRegionBase & subRegion ) - { - // 2. Assume global component fractions have been prescribed. - // Initialize constitutive state to get fluid density. - updateFluidModel( subRegion ); - - } ); - - // for some reason CUDA does not want the host_device lambda to be defined inside the generic lambda - // I need the exact type of the subRegion for updateSolidflowProperties to work well. - mesh.getElemManager().forElementSubRegions< CellElementSubRegion, - SurfaceElementSubRegion >( regionNames, [&]( localIndex const, - auto & subRegion ) - { - // 4. Initialize/update dependent state quantities - - // 4.1 Update the constitutive models that only depend on - // - the primary variables - // - the fluid constitutive quantities (as they have already been updated) - // We postpone the other constitutive models for now - // In addition, to avoid multiplying permeability/porosity bay netToGross in the assembly kernel, we do it once and for all here - arrayView1d< real64 const > const netToGross = subRegion.template getField< fields::flow::netToGross >(); - CoupledSolidBase const & porousSolid = - getConstitutiveModel< CoupledSolidBase >( subRegion, subRegion.template getReference< string >( viewKeyStruct::solidNamesString() ) ); - PermeabilityBase const & permeabilityModel = - getConstitutiveModel< PermeabilityBase >( subRegion, subRegion.template getReference< string >( viewKeyStruct::permeabilityNamesString() ) ); - permeabilityModel.scaleHorizontalPermeability( netToGross ); - porousSolid.scaleReferencePorosity( netToGross ); - saveConvergedState( subRegion ); // necessary for a meaningful porosity update in sequential schemes - updatePorosityAndPermeability( subRegion ); - - // Now, we initialize and update each constitutive model one by one - - // 4.2 Save the computed porosity into the old porosity - // - // Note: - // - This must be called after updatePorosityAndPermeability - // - This step depends on porosity - string const & solidName = subRegion.template getReference< string >( viewKeyStruct::solidNamesString() ); - CoupledSolidBase const & porousMaterial = getConstitutiveModel< CoupledSolidBase >( subRegion, solidName ); - porousMaterial.initializeState(); - - // 4.3 Initialize/update the relative permeability model using the initial phase volume fraction - // This is needed to handle relative permeability hysteresis - // Also, initialize the fluid model - // - // Note: - // - This must be called after updateVolumeConstraint - // - This step depends on phaseVolFraction - - // initialized phase volume fraction - arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac = - subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); - - string const & relpermName = subRegion.template getReference< string >( viewKeyStruct::relPermNamesString() ); - RelativePermeabilityBase & relPermMaterial = - getConstitutiveModel< RelativePermeabilityBase >( subRegion, relpermName ); - relPermMaterial.saveConvergedPhaseVolFractionState( phaseVolFrac ); // this needs to happen before calling updateRelPermModel - updateRelPermModel( subRegion ); - relPermMaterial.saveConvergedState(); // this needs to happen after calling updateRelPermModel - - // 4.4 Then, we initialize/update the capillary pressure model - // - // Note: - // - This must be called after updatePorosityAndPermeability - // - This step depends on porosity and permeability - if( m_hasCapPressure ) - { - // initialized porosity - arrayView2d< real64 const > const porosity = porousMaterial.getPorosity(); - - string const & permName = subRegion.template getReference< string >( viewKeyStruct::permeabilityNamesString() ); - PermeabilityBase const & permeabilityMaterial = getConstitutiveModel< PermeabilityBase >( subRegion, permName ); - // initialized permeability - arrayView3d< real64 const > const permeability = permeabilityMaterial.permeability(); - - string const & capPressureName = subRegion.template getReference< string >( viewKeyStruct::capPressureNamesString() ); - CapillaryPressureBase const & capPressureMaterial = - getConstitutiveModel< CapillaryPressureBase >( subRegion, capPressureName ); - capPressureMaterial.initializeRockState( porosity, permeability ); // this needs to happen before calling updateCapPressureModel - updateCapPressureModel( subRegion ); - } - - // 4.5 Update the phase mobility - // - // Note: - // - This must be called after updateRelPermModel - // - This step depends phaseRelPerm - updatePhaseMobility( subRegion ); - - } ); - - // 5. Save initial pressure - mesh.getElemManager().forElementSubRegions( regionNames, [&]( localIndex const, - ElementSubRegionBase & subRegion ) - { - arrayView1d< real64 const > const pres = subRegion.getField< fields::flow::pressure >(); - arrayView1d< real64 > const initPres = subRegion.getField< fields::flow::initialPressure >(); - arrayView1d< real64 const > const temp = subRegion.getField< fields::flow::temperature >(); - arrayView1d< real64 > const initTemp = subRegion.template getField< fields::flow::initialTemperature >(); - initPres.setValues< parallelDevicePolicy<> >( pres ); - initTemp.setValues< parallelDevicePolicy<> >( temp ); - - // TODO: Missing updatePhaseMass? - } ); - } - - - void ImmiscibleMultiphaseFlow::initializePostInitialConditionsPreSubGroups() - { - GEOS_MARK_FUNCTION; - - FlowSolverBase::initializePostInitialConditionsPreSubGroups(); - - DomainPartition & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" ); - - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel & mesh, - string_array const & regionNames ) - { - FieldIdentifiers fieldsToBeSync; - fieldsToBeSync.addElementFields( { fields::flow::pressure::key(), - fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key() }, - regionNames ); - - CommunicationTools::getInstance().synchronizeFields( fieldsToBeSync, mesh, domain.getNeighbors(), false ); - } ); - - // Retrieve the numerical methods and finite volume manager - FiniteVolumeManager const & fvManager = domain.getNumericalMethodManager().getFiniteVolumeManager(); - FluxApproximationBase const & fluxApprox = fvManager.getFluxApproximation( m_discretizationName ); - const geos::string flux_approximation_name = fluxApprox.getName(); - - // Clear the existing mapping between connector indices and interface region indices - m_interfaceRegionByConnector.clear(); - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( std::string const &, - MeshLevel & meshLevel, - string_array const & GEOS_UNUSED_PARAM( regionNames )) - { - // Access the face manager and retrieve the face set group for the current mesh level - FaceManager const & faceManager = meshLevel.getFaceManager(); - Group const & faceSetGroup = faceManager.sets(); - - // Access the connector indices map (face index → connector index) - Group & stencilGroup = - meshLevel.getGroup( FluxApproximationBase::groupKeyStruct::stencilMeshGroupString()) - .getGroup( flux_approximation_name ); - CellElementStencilTPFA & stencil = - stencilGroup.getReference< CellElementStencilTPFA >( - FluxApproximationBase::viewKeyStruct::cellStencilString()); - unordered_map< localIndex, localIndex > const & connectorIndices = stencil.getConnectorIndices(); - - // for all interface face sets to map connector indices to their corresponding interface region indices - for( size_t surfaceRegionIndex = 0; surfaceRegionIndex < m_interfaceFaceSetNames.size(); ++surfaceRegionIndex ) - { - // Iterate over each face and associate its connector index - std::string const & faceSetName = m_interfaceFaceSetNames[surfaceRegionIndex]; - for( localIndex kf : faceSetGroup.getReference< SortedArray< localIndex > >( faceSetName )) - { - auto it = connectorIndices.find( kf ); - if( it != connectorIndices.end()) - { - // Map the connector index to the corresponding surface region index - m_interfaceRegionByConnector[it->second] = surfaceRegionIndex; - } - } - } - } ); - - - initializeState( domain ); - } - - - void - ImmiscibleMultiphaseFlow::implicitStepSetup( real64 const & GEOS_UNUSED_PARAM( time_n ), - real64 const & GEOS_UNUSED_PARAM( dt ), - DomainPartition & domain ) - { - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + assembleAccumulationTerm( domain, + dofManager, + localMatrix, + localRhs ); + + + assembleFluxTerms( dt, + domain, + dofManager, + localMatrix, + localRhs ); +} + + + +void ImmiscibleMultiphaseFlow::assembleAccumulationTerm( DomainPartition & domain, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) const +{ + GEOS_MARK_FUNCTION; + + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel const & mesh, + string_array const & regionNames ) + { + mesh.getElemManager().forElementSubRegions( regionNames, + [&]( localIndex const, + ElementSubRegionBase const & subRegion ) + { + string const dofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); + string const & solidName = subRegion.getReference< string >( viewKeyStruct::solidNamesString() ); + string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); + + TwoPhaseImmiscibleFluid const & fluid = getConstitutiveModel< TwoPhaseImmiscibleFluid >( subRegion, fluidName ); + CoupledSolidBase const & solid = getConstitutiveModel< CoupledSolidBase >( subRegion, solidName ); + + immiscibleMultiphaseKernels:: + AccumulationKernelFactory:: + createAndLaunch< parallelDevicePolicy<> >( m_numPhases, + dofManager.rankOffset(), + m_useTotalMassEquation, + dofKey, + subRegion, + fluid, + solid, + localMatrix, + localRhs ); + + } ); + } ); +} + +void ImmiscibleMultiphaseFlow::assembleFluxTerms( real64 const dt, + DomainPartition & domain, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) const +{ + GEOS_MARK_FUNCTION; + + NumericalMethodsManager const & numericalMethodManager = domain.getNumericalMethodManager(); + FiniteVolumeManager const & fvManager = numericalMethodManager.getFiniteVolumeManager(); + FluxApproximationBase const & fluxApprox = fvManager.getFluxApproximation( m_discretizationName ); + + string const & dofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); + + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, MeshLevel & mesh, string_array const & regionNames ) - { - mesh.getElemManager().forElementSubRegions< CellElementSubRegion, - SurfaceElementSubRegion >( regionNames, - [&]( localIndex const, - auto & subRegion ) - { - saveConvergedState( subRegion ); - - // update porosity, permeability - updatePorosityAndPermeability( subRegion ); - // update all fluid properties - updateVolumeConstraint( subRegion ); - updateFluidState( subRegion ); - - // after the update, save the new saturation - arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac = - subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); - - arrayView2d< real64, immiscibleFlow::USD_PHASE > const phaseVolFrac_n = - subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction_n >(); - phaseVolFrac_n.setValues< parallelDevicePolicy<> >( phaseVolFrac ); - - arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const & phaseMass = - subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseMass >(); - - arrayView2d< real64, immiscibleFlow::USD_PHASE > const & phaseMass_n = - subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseMass_n >(); - phaseMass_n.setValues< parallelDevicePolicy<> >( phaseMass ); - - } ); - } ); - } - - void ImmiscibleMultiphaseFlow::assembleSystem( real64 const GEOS_UNUSED_PARAM( time_n ), - real64 const dt, - DomainPartition & domain, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) - { - GEOS_MARK_FUNCTION; - - assembleAccumulationTerm( domain, - dofManager, - localMatrix, - localRhs ); - - - assembleFluxTerms( dt, - domain, - dofManager, - localMatrix, - localRhs ); - } - - - - void ImmiscibleMultiphaseFlow::assembleAccumulationTerm( DomainPartition & domain, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) const - { - GEOS_MARK_FUNCTION; - - - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel const & mesh, - string_array const & regionNames ) - { - mesh.getElemManager().forElementSubRegions( regionNames, - [&]( localIndex const, - ElementSubRegionBase const & subRegion ) - { - string const dofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); - string const & solidName = subRegion.getReference< string >( viewKeyStruct::solidNamesString() ); - string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); - - TwoPhaseImmiscibleFluid const & fluid = getConstitutiveModel< TwoPhaseImmiscibleFluid >( subRegion, fluidName ); - CoupledSolidBase const & solid = getConstitutiveModel< CoupledSolidBase >( subRegion, solidName ); - - immiscibleMultiphaseKernels:: - AccumulationKernelFactory:: - createAndLaunch< parallelDevicePolicy<> >( m_numPhases, - dofManager.rankOffset(), - m_useTotalMassEquation, - dofKey, - subRegion, - fluid, - solid, - localMatrix, - localRhs ); - - } ); - } ); - } - - void ImmiscibleMultiphaseFlow::assembleFluxTerms( real64 const dt, - DomainPartition & domain, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) const - { - GEOS_MARK_FUNCTION; - - NumericalMethodsManager const & numericalMethodManager = domain.getNumericalMethodManager(); - FiniteVolumeManager const & fvManager = numericalMethodManager.getFiniteVolumeManager(); - FluxApproximationBase const & fluxApprox = fvManager.getFluxApproximation( m_discretizationName ); - - string const & dofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); - - - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, - MeshLevel & mesh, - string_array const & regionNames ) - { - if( m_hasCapPressure ) - { - mesh.getElemManager().forElementSubRegions( regionNames, - [&]( localIndex const, - ElementSubRegionBase & subRegion ) // Check if you need this. - { + { + if( m_hasCapPressure ) + { + mesh.getElemManager().forElementSubRegions( regionNames, + [&]( localIndex const, + ElementSubRegionBase & subRegion ) // Check if you need this. + { // // Capillary pressure wrapper // string const & cappresName = subRegion.getReference< string >( viewKeyStruct::capPressureNamesString() ); // BrooksCoreyCapillaryPressure & capPressure = getConstitutiveModel< BrooksCoreyCapillaryPressure >( subRegion, cappresName ); // CapillaryPressureBase * capPressure1 = &getConstitutiveModel< CapillaryPressureBase >( subRegion, cappresName ); // BrooksCoreyCapillaryPressure::KernelWrapper capPresWrapper = capPressure.createKernelWrapper(); - + // // Relative permeability wrapper // string const & relPermName = subRegion.getReference< string >( viewKeyStruct::relPermNamesString() ); // BrooksCoreyRelativePermeability & relPerm = getConstitutiveModel< BrooksCoreyRelativePermeability >( subRegion, relPermName ); // RelativePermeabilityBase * relPerm1 = &getConstitutiveModel< RelativePermeabilityBase >( subRegion, relPermName ); // BrooksCoreyRelativePermeability::KernelWrapper relPermWrapper = relPerm.createKernelWrapper(); - + // // fluid // string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); // TwoPhaseImmiscibleFluid * fluid = &getConstitutiveModel< TwoPhaseImmiscibleFluid >( subRegion, fluidName ); - + // // m_interfaceConstitutivePairs[0][0] = std::make_tuple( relPerm1, capPressure1, fluid ); // // m_interfaceConstitutivePairs[0][1] = std::make_tuple( relPerm1, capPressure1, fluid ); - + // auto interfaceConstitutivePairs_temp = std::make_tuple( relPerm1, capPressure1, fluid ); - - fluxApprox.forAllStencils( mesh, [&]( auto & stencil ) - { - typename TYPEOFREF( stencil ) ::KernelWrapper stencilWrapper = stencil.createKernelWrapper(); - immiscibleMultiphaseKernels:: - FluxComputeKernelFactory::createAndLaunch< parallelDevicePolicy<> >( m_numPhases, - dofManager.rankOffset(), - dofKey, - m_hasCapPressure, - m_useTotalMassEquation, - m_gravityDensityScheme == GravityDensityScheme::PhasePresence, - getName(), - mesh.getElemManager(), - stencilWrapper, - // capPresWrapper, - // relPermWrapper, - m_interfaceFaceSetNames, - m_interfaceConstitutivePairs, - m_interfaceRegionByConnector, - // interfaceConstitutivePairs_temp, - subRegion, - dt, - localMatrix.toViewConstSizes(), - localRhs.toView() ); - } ); - } ); - } - else - { - fluxApprox.forAllStencils( mesh, [&]( auto & stencil ) - { - typename TYPEOFREF( stencil ) ::KernelWrapper stencilWrapper = stencil.createKernelWrapper(); - immiscibleMultiphaseKernels:: - FluxComputeKernelFactory::createAndLaunch< parallelDevicePolicy<> >( m_numPhases, - dofManager.rankOffset(), - dofKey, - m_hasCapPressure, - m_useTotalMassEquation, - m_gravityDensityScheme == GravityDensityScheme::PhasePresence, - getName(), - mesh.getElemManager(), - stencilWrapper, - dt, - localMatrix.toViewConstSizes(), - localRhs.toView() ); - } ); - } - - } ); - } - - // Ryan: Looks like this will need to be overwritten as well... - // I have left the CompositionalMultiphaseFVM implementation for reference - void ImmiscibleMultiphaseFlow::setupDofs( DomainPartition const & domain, - DofManager & dofManager ) const - { - GEOS_UNUSED_VAR( domain, dofManager ); - // add a field for the cell-centered degrees of freedom - dofManager.addField( viewKeyStruct::elemDofFieldString(), - FieldLocation::Elem, - m_numDofPerCell, - getMeshTargets() ); - - //// this call with instruct GEOS to reorder the dof numbers - //dofManager.setLocalReorderingType( viewKeyStruct::elemDofFieldString(), - // DofManager::LocalReorderingType::ReverseCutHillMcKee ); - - NumericalMethodsManager const & numericalMethodManager = domain.getNumericalMethodManager(); - FiniteVolumeManager const & fvManager = numericalMethodManager.getFiniteVolumeManager(); - FluxApproximationBase const & fluxApprox = fvManager.getFluxApproximation( m_discretizationName ); - dofManager.addCoupling( viewKeyStruct::elemDofFieldString(), fluxApprox ); - } - - void ImmiscibleMultiphaseFlow::applyBoundaryConditions( real64 const time_n, - real64 const dt, - DomainPartition & domain, - DofManager const & dofManager, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) - { - GEOS_MARK_FUNCTION; - - // apply pressure boundary conditions. - applyDirichletBC( time_n, dt, dofManager, domain, localMatrix.toViewConstSizes(), localRhs.toView() ); - - // apply flux boundary conditions - applySourceFluxBC( time_n, dt, dofManager, domain, localMatrix.toViewConstSizes(), localRhs.toView() ); - } - - - namespace - { - char const bcLogMessage[] = - "ImmiscibleMultiphaseFlow {}: at time {}s, " - "the <{}> boundary condition '{}' is applied to the element set '{}' in subRegion '{}'. " - "\nThe scale of this boundary condition is {} and multiplies the value of the provided function (if any). " - "\nThe total number of target elements (including ghost elements) is {}. " - "\nNote that if this number is equal to zero for all subRegions, the boundary condition will not be applied on this element set."; - } - - bool ImmiscibleMultiphaseFlow::validateDirichletBC( DomainPartition & domain, - real64 const time ) const - { - constexpr integer MAX_NP = 2; - FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); - - bool bcConsistent = true; - - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel & mesh, - string_array const & ) - { - // map: regionName -> subRegionName -> setName -> numPhases to check pressure/phase are present consistent - map< string, map< string, map< string, ComponentMask< MAX_NP > > > > bcPresCompStatusMap; - - // 1. Check pressure Dirichlet BCs - fsManager.apply< ElementSubRegionBase >( time, - mesh, - fields::flow::pressure::key(), - [&]( FieldSpecificationBase const &, + + fluxApprox.forAllStencils( mesh, [&]( auto & stencil ) + { + typename TYPEOFREF( stencil ) ::KernelWrapper stencilWrapper = stencil.createKernelWrapper(); + immiscibleMultiphaseKernels:: + FluxComputeKernelFactory::createAndLaunch< parallelDevicePolicy<> >( m_numPhases, + dofManager.rankOffset(), + dofKey, + m_hasCapPressure, + m_useTotalMassEquation, + m_gravityDensityScheme == GravityDensityScheme::PhasePresence, + getName(), + mesh.getElemManager(), + stencilWrapper, + // capPresWrapper, + // relPermWrapper, + m_interfaceFaceSetNames, + m_interfaceConstitutivePairs, + m_interfaceRegionByConnector, + // interfaceConstitutivePairs_temp, + subRegion, + dt, + localMatrix.toViewConstSizes(), + localRhs.toView() ); + } ); + } ); + } + else + { + fluxApprox.forAllStencils( mesh, [&]( auto & stencil ) + { + typename TYPEOFREF( stencil ) ::KernelWrapper stencilWrapper = stencil.createKernelWrapper(); + immiscibleMultiphaseKernels:: + FluxComputeKernelFactory::createAndLaunch< parallelDevicePolicy<> >( m_numPhases, + dofManager.rankOffset(), + dofKey, + m_hasCapPressure, + m_useTotalMassEquation, + m_gravityDensityScheme == GravityDensityScheme::PhasePresence, + getName(), + mesh.getElemManager(), + stencilWrapper, + dt, + localMatrix.toViewConstSizes(), + localRhs.toView() ); + } ); + } + + } ); +} + +// Ryan: Looks like this will need to be overwritten as well... +// I have left the CompositionalMultiphaseFVM implementation for reference +void ImmiscibleMultiphaseFlow::setupDofs( DomainPartition const & domain, + DofManager & dofManager ) const +{ + GEOS_UNUSED_VAR( domain, dofManager ); + // add a field for the cell-centered degrees of freedom + dofManager.addField( viewKeyStruct::elemDofFieldString(), + FieldLocation::Elem, + m_numDofPerCell, + getMeshTargets() ); + + //// this call with instruct GEOS to reorder the dof numbers + //dofManager.setLocalReorderingType( viewKeyStruct::elemDofFieldString(), + // DofManager::LocalReorderingType::ReverseCutHillMcKee ); + + NumericalMethodsManager const & numericalMethodManager = domain.getNumericalMethodManager(); + FiniteVolumeManager const & fvManager = numericalMethodManager.getFiniteVolumeManager(); + FluxApproximationBase const & fluxApprox = fvManager.getFluxApproximation( m_discretizationName ); + dofManager.addCoupling( viewKeyStruct::elemDofFieldString(), fluxApprox ); +} + +void ImmiscibleMultiphaseFlow::applyBoundaryConditions( real64 const time_n, + real64 const dt, + DomainPartition & domain, + DofManager const & dofManager, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) +{ + GEOS_MARK_FUNCTION; + + // apply pressure boundary conditions. + applyDirichletBC( time_n, dt, dofManager, domain, localMatrix.toViewConstSizes(), localRhs.toView() ); + + // apply flux boundary conditions + applySourceFluxBC( time_n, dt, dofManager, domain, localMatrix.toViewConstSizes(), localRhs.toView() ); +} + + +namespace +{ +char const bcLogMessage[] = + "ImmiscibleMultiphaseFlow {}: at time {}s, " + "the <{}> boundary condition '{}' is applied to the element set '{}' in subRegion '{}'. " + "\nThe scale of this boundary condition is {} and multiplies the value of the provided function (if any). " + "\nThe total number of target elements (including ghost elements) is {}. " + "\nNote that if this number is equal to zero for all subRegions, the boundary condition will not be applied on this element set."; +} + +bool ImmiscibleMultiphaseFlow::validateDirichletBC( DomainPartition & domain, + real64 const time ) const +{ + constexpr integer MAX_NP = 2; + FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); + + bool bcConsistent = true; + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + string_array const & ) + { + // map: regionName -> subRegionName -> setName -> numPhases to check pressure/phase are present consistent + map< string, map< string, map< string, ComponentMask< MAX_NP > > > > bcPresCompStatusMap; + + // 1. Check pressure Dirichlet BCs + fsManager.apply< ElementSubRegionBase >( time, + mesh, + fields::flow::pressure::key(), + [&]( FieldSpecificationBase const &, + string const & setName, + SortedArrayView< localIndex const > const &, + ElementSubRegionBase & subRegion, + string const & ) + { + // Check whether pressure has already been applied to this set + string const & subRegionName = subRegion.getName(); + string const & regionName = subRegion.getParent().getParent().getName(); + + auto & subRegionSetMap = bcPresCompStatusMap[regionName][subRegionName]; + if( subRegionSetMap.count( setName ) > 0 ) + { + bcConsistent = false; + GEOS_WARNING( BCMessage::pressureConflict( regionName, subRegionName, setName, + fields::flow::pressure::key() ) ); + } + subRegionSetMap[setName].setNumComp( m_numPhases ); + } ); + // 2. Check saturation Dirichlet BCs + fsManager.apply< ElementSubRegionBase >( time, + mesh, + fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key(), + [&] ( FieldSpecificationBase const & fs, string const & setName, SortedArrayView< localIndex const > const &, ElementSubRegionBase & subRegion, string const & ) - { - // Check whether pressure has already been applied to this set - string const & subRegionName = subRegion.getName(); - string const & regionName = subRegion.getParent().getParent().getName(); - - auto & subRegionSetMap = bcPresCompStatusMap[regionName][subRegionName]; - if( subRegionSetMap.count( setName ) > 0 ) - { - bcConsistent = false; - GEOS_WARNING( BCMessage::pressureConflict( regionName, subRegionName, setName, - fields::flow::pressure::key() ) ); - } - subRegionSetMap[setName].setNumComp( m_numPhases ); - } ); - // 2. Check saturation Dirichlet BCs - fsManager.apply< ElementSubRegionBase >( time, - mesh, - fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key(), - [&] ( FieldSpecificationBase const & fs, - string const & setName, - SortedArrayView< localIndex const > const &, - ElementSubRegionBase & subRegion, - string const & ) - { - string const & subRegionName = subRegion.getName( ); - string const & regionName = subRegion.getParent().getParent().getName(); - integer const comp = fs.getComponent(); - - auto & subRegionSetMap = bcPresCompStatusMap[regionName][subRegionName]; - if( subRegionSetMap.count( setName ) == 0 ) - { - bcConsistent = false; - GEOS_WARNING( BCMessage::missingPressure( regionName, subRegionName, setName, - fields::flow::pressure::key() ) ); - } - if( comp < 0 || comp >= m_numPhases ) - { - bcConsistent = false; - GEOS_WARNING( BCMessage::invalidComponentIndex( comp, fs.getName(), - fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key() ) ); - return; // can't check next part with invalid component id - } - - ComponentMask< MAX_NP > & compMask = subRegionSetMap[setName]; - if( compMask[comp] ) - { - bcConsistent = false; - fsManager.forSubGroups< EquilibriumInitialCondition >( [&] ( EquilibriumInitialCondition const & bc ) - { - string_array const & componentNames = bc.getComponentNames(); - GEOS_WARNING( BCMessage::conflictingComposition( comp, componentNames[comp], - regionName, subRegionName, setName, - fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key() ) ); - } ); - } - compMask.set( comp ); - } ); - - // 3.2 Check consistency between composition BC applied to sets - // Note: for a temperature-only boundary condition, this loop does not do anything - for( auto const & regionEntry : bcPresCompStatusMap ) - { - for( auto const & subRegionEntry : regionEntry.second ) - { - for( auto const & setEntry : subRegionEntry.second ) - { - ComponentMask< MAX_NP > const & compMask = setEntry.second; - - fsManager.forSubGroups< EquilibriumInitialCondition >( [&] ( EquilibriumInitialCondition const & fs ) - { - string_array const & componentNames = fs.getComponentNames(); - for( size_t ic = 0; ic < componentNames.size(); ic++ ) - { - if( !compMask[ic] ) - { - bcConsistent = false; - GEOS_WARNING( BCMessage::notAppliedOnRegion( ic, componentNames[ic], - regionEntry.first, subRegionEntry.first, setEntry.first, - fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key() ) ); - } - } - } ); - } - } - } - } ); - - return bcConsistent; - } - - void ImmiscibleMultiphaseFlow::applyDirichletBC( real64 const time_n, + { + string const & subRegionName = subRegion.getName( ); + string const & regionName = subRegion.getParent().getParent().getName(); + integer const comp = fs.getComponent(); + + auto & subRegionSetMap = bcPresCompStatusMap[regionName][subRegionName]; + if( subRegionSetMap.count( setName ) == 0 ) + { + bcConsistent = false; + GEOS_WARNING( BCMessage::missingPressure( regionName, subRegionName, setName, + fields::flow::pressure::key() ) ); + } + if( comp < 0 || comp >= m_numPhases ) + { + bcConsistent = false; + GEOS_WARNING( BCMessage::invalidComponentIndex( comp, fs.getName(), + fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key() ) ); + return; // can't check next part with invalid component id + } + + ComponentMask< MAX_NP > & compMask = subRegionSetMap[setName]; + if( compMask[comp] ) + { + bcConsistent = false; + fsManager.forSubGroups< EquilibriumInitialCondition >( [&] ( EquilibriumInitialCondition const & bc ) + { + string_array const & componentNames = bc.getComponentNames(); + GEOS_WARNING( BCMessage::conflictingComposition( comp, componentNames[comp], + regionName, subRegionName, setName, + fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key() ) ); + } ); + } + compMask.set( comp ); + } ); + + // 3.2 Check consistency between composition BC applied to sets + // Note: for a temperature-only boundary condition, this loop does not do anything + for( auto const & regionEntry : bcPresCompStatusMap ) + { + for( auto const & subRegionEntry : regionEntry.second ) + { + for( auto const & setEntry : subRegionEntry.second ) + { + ComponentMask< MAX_NP > const & compMask = setEntry.second; + + fsManager.forSubGroups< EquilibriumInitialCondition >( [&] ( EquilibriumInitialCondition const & fs ) + { + string_array const & componentNames = fs.getComponentNames(); + for( size_t ic = 0; ic < componentNames.size(); ic++ ) + { + if( !compMask[ic] ) + { + bcConsistent = false; + GEOS_WARNING( BCMessage::notAppliedOnRegion( ic, componentNames[ic], + regionEntry.first, subRegionEntry.first, setEntry.first, + fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key() ) ); + } + } + } ); + } + } + } + } ); + + return bcConsistent; +} + +void ImmiscibleMultiphaseFlow::applyDirichletBC( real64 const time_n, + real64 const dt, + DofManager const & dofManager, + DomainPartition & domain, + CRSMatrixView< real64, globalIndex const > const & localMatrix, + arrayView1d< real64 > const & localRhs ) const +{ + GEOS_MARK_FUNCTION; + + // Only validate BC at the beginning of Newton loop + if( m_nonlinearSolverParameters.m_numNewtonIterations == 0 ) + { + bool const bcConsistent = validateDirichletBC( domain, time_n + dt ); + GEOS_ERROR_IF( !bcConsistent, GEOS_FMT( "ImmiscibleMultiphaseFlow {}: inconsistent boundary conditions", getDataContext() ) ); + } + + FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + string_array const & ) + { + + // 1. Apply pressure Dirichlet BCs, store in a separate field + applyFieldValue< ElementSubRegionBase >( time_n, dt, mesh, bcLogMessage, + fields::flow::pressure::key(), fields::flow::bcPressure::key() ); + // 2. Apply saturation BC (phase volume fraction) and store in a separate field + applyFieldValue< ElementSubRegionBase >( time_n, dt, mesh, bcLogMessage, + fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key(), + fields::immiscibleMultiphaseFlow::bcPhaseVolumeFraction::key() ); + + globalIndex const rankOffset = dofManager.rankOffset(); + string const dofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); + + // 3. Call constitutive update + fsManager.apply< ElementSubRegionBase >( time_n + dt, + mesh, + fields::flow::pressure::key(), + [&] ( FieldSpecificationBase const &, + string const &, + SortedArrayView< localIndex const > const & targetSet, + ElementSubRegionBase & subRegion, + string const & ) + { + + arrayView1d< real64 const > const bcPres = + subRegion.getReference< array1d< real64 > >( fields::flow::bcPressure::key() ); + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const bcPhaseVolFraction = + subRegion.getReference< array2d< real64, immiscibleFlow::LAYOUT_PHASE > >( + fields::immiscibleMultiphaseFlow::bcPhaseVolumeFraction::key() ); + + arrayView1d< integer const > const ghostRank = + subRegion.getReference< array1d< integer > >( ObjectManagerBase::viewKeyStruct::ghostRankString() ); + arrayView1d< globalIndex const > const dofNumber = + subRegion.getReference< array1d< globalIndex > >( dofKey ); + arrayView1d< real64 const > const pres = + subRegion.getReference< array1d< real64 > >( fields::flow::pressure::key() ); + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFraction = + subRegion.getReference< array2d< real64, immiscibleFlow::LAYOUT_PHASE > >( + fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key() ); + + integer const numPhase = m_numPhases; + + + forAll< parallelDevicePolicy<> >( targetSet.size(), [=] GEOS_HOST_DEVICE ( localIndex const a ) + { + localIndex const ei = targetSet[a]; + if( ghostRank[ei] >= 0 ) + { + return; + } + + globalIndex const dofIndex = dofNumber[ei]; + localIndex const localRow = dofIndex - rankOffset; + real64 rhsValue; + + // 3.1. Apply pressure value to the matrix/rhs + FieldSpecificationEqual::SpecifyFieldValue( dofIndex, + rankOffset, + localMatrix, + rhsValue, + bcPres[ei], + pres[ei] ); + localRhs[localRow] = rhsValue; + + // 3.2. For each phase, apply target saturation value + for( integer ip = 0; ip < numPhase-1; ++ip ) + { + FieldSpecificationEqual::SpecifyFieldValue( dofIndex + ip + 1, + rankOffset, + localMatrix, + rhsValue, + bcPhaseVolFraction[ei][ip], + phaseVolFraction[ei][ip] ); + localRhs[localRow + ip + 1] = rhsValue; + } + } ); + } ); + } ); +} + +void ImmiscibleMultiphaseFlow::applySourceFluxBC( real64 const time, real64 const dt, DofManager const & dofManager, DomainPartition & domain, CRSMatrixView< real64, globalIndex const > const & localMatrix, arrayView1d< real64 > const & localRhs ) const - { - GEOS_MARK_FUNCTION; - - // Only validate BC at the beginning of Newton loop - if( m_nonlinearSolverParameters.m_numNewtonIterations == 0 ) - { - bool const bcConsistent = validateDirichletBC( domain, time_n + dt ); - GEOS_ERROR_IF( !bcConsistent, GEOS_FMT( "ImmiscibleMultiphaseFlow {}: inconsistent boundary conditions", getDataContext() ) ); - } - - FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); - - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel & mesh, - string_array const & ) - { - - // 1. Apply pressure Dirichlet BCs, store in a separate field - applyFieldValue< ElementSubRegionBase >( time_n, dt, mesh, bcLogMessage, - fields::flow::pressure::key(), fields::flow::bcPressure::key() ); - // 2. Apply saturation BC (phase volume fraction) and store in a separate field - applyFieldValue< ElementSubRegionBase >( time_n, dt, mesh, bcLogMessage, - fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key(), - fields::immiscibleMultiphaseFlow::bcPhaseVolumeFraction::key() ); - - globalIndex const rankOffset = dofManager.rankOffset(); - string const dofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); - - // 3. Call constitutive update - fsManager.apply< ElementSubRegionBase >( time_n + dt, - mesh, - fields::flow::pressure::key(), - [&] ( FieldSpecificationBase const &, - string const &, - SortedArrayView< localIndex const > const & targetSet, - ElementSubRegionBase & subRegion, - string const & ) - { - - arrayView1d< real64 const > const bcPres = - subRegion.getReference< array1d< real64 > >( fields::flow::bcPressure::key() ); - arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const bcPhaseVolFraction = - subRegion.getReference< array2d< real64, immiscibleFlow::LAYOUT_PHASE > >( - fields::immiscibleMultiphaseFlow::bcPhaseVolumeFraction::key() ); - - arrayView1d< integer const > const ghostRank = - subRegion.getReference< array1d< integer > >( ObjectManagerBase::viewKeyStruct::ghostRankString() ); - arrayView1d< globalIndex const > const dofNumber = - subRegion.getReference< array1d< globalIndex > >( dofKey ); - arrayView1d< real64 const > const pres = - subRegion.getReference< array1d< real64 > >( fields::flow::pressure::key() ); - arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFraction = - subRegion.getReference< array2d< real64, immiscibleFlow::LAYOUT_PHASE > >( - fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key() ); - - integer const numPhase = m_numPhases; - - - forAll< parallelDevicePolicy<> >( targetSet.size(), [=] GEOS_HOST_DEVICE ( localIndex const a ) - { - localIndex const ei = targetSet[a]; - if( ghostRank[ei] >= 0 ) - { - return; - } - - globalIndex const dofIndex = dofNumber[ei]; - localIndex const localRow = dofIndex - rankOffset; - real64 rhsValue; - - // 3.1. Apply pressure value to the matrix/rhs - FieldSpecificationEqual::SpecifyFieldValue( dofIndex, - rankOffset, - localMatrix, - rhsValue, - bcPres[ei], - pres[ei] ); - localRhs[localRow] = rhsValue; - - // 3.2. For each phase, apply target saturation value - for( integer ip = 0; ip < numPhase-1; ++ip ) - { - FieldSpecificationEqual::SpecifyFieldValue( dofIndex + ip + 1, - rankOffset, - localMatrix, - rhsValue, - bcPhaseVolFraction[ei][ip], - phaseVolFraction[ei][ip] ); - localRhs[localRow + ip + 1] = rhsValue; - } - } ); - } ); - } ); - } - - void ImmiscibleMultiphaseFlow::applySourceFluxBC( real64 const time, - real64 const dt, - DofManager const & dofManager, - DomainPartition & domain, - CRSMatrixView< real64, globalIndex const > const & localMatrix, - arrayView1d< real64 > const & localRhs ) const - { - GEOS_MARK_FUNCTION; - - FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); - - string const dofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); - - // Step 1: count individual source flux boundary conditions - - stdMap< string, localIndex > bcNameToBcId; - localIndex bcCounter = 0; - +{ + GEOS_MARK_FUNCTION; + + FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); + + string const dofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); + + // Step 1: count individual source flux boundary conditions + + stdMap< string, localIndex > bcNameToBcId; + localIndex bcCounter = 0; + fsManager.forSubGroups< SourceFluxBoundaryCondition >( [&] ( SourceFluxBoundaryCondition const & bc ) { // collect all the bc names to idx bcNameToBcId.insert( {bc.getName(), bcCounter} ); bcCounter++; } ); - - if( bcCounter == 0 ) - { - return; - } - - // Step 2: count the set size for each source flux (each source flux may have multiple target sets) - - array1d< globalIndex > bcAllSetsSize( bcNameToBcId.size() ); - - computeSourceFluxSizeScalingFactor( time, - dt, - domain, - bcNameToBcId, - bcAllSetsSize.toView() ); - - // Step 3: we are ready to impose the boundary condition, normalized by the set size - - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel & mesh, - string_array const & ) - { - - fsManager.apply< ElementSubRegionBase, - SourceFluxBoundaryCondition >( time + dt, - mesh, - SourceFluxBoundaryCondition::catalogName(), - [&]( SourceFluxBoundaryCondition const & fs, - string const & setName, - SortedArrayView< localIndex const > const & targetSet, - ElementSubRegionBase & subRegion, - string const & ) - { - if( fs.getLogLevel() >= 1 && m_nonlinearSolverParameters.m_numNewtonIterations == 0 ) - { - globalIndex const numTargetElems = MpiWrapper::sum< globalIndex >( targetSet.size() ); - GEOS_LOG_RANK_0( GEOS_FMT( bcLogMessage, - getName(), time+dt, fs.getCatalogName(), fs.getName(), - setName, subRegion.getName(), fs.getScale(), numTargetElems ) ); - } - - if( targetSet.size() == 0 ) - { - return; - } - if( !subRegion.hasWrapper( dofKey ) ) - { - if( fs.getLogLevel() >= 1 ) - { - GEOS_LOG_RANK( GEOS_FMT( "{}: trying to apply SourceFlux, but its targetSet named '{}' intersects with non-simulated region named '{}'.", - getDataContext(), setName, subRegion.getName() ) ); - } - return; - } - - arrayView1d< globalIndex const > const dofNumber = subRegion.getReference< array1d< globalIndex > >( dofKey ); - arrayView1d< integer const > const ghostRank = subRegion.ghostRank(); - - // Step 3.1: get the values of the source boundary condition that need to be added to the rhs - - array1d< globalIndex > dofArray( targetSet.size() ); - array1d< real64 > rhsContributionArray( targetSet.size() ); - arrayView1d< real64 > rhsContributionArrayView = rhsContributionArray.toView(); - localIndex const rankOffset = dofManager.rankOffset(); - - RAJA::ReduceSum< parallelDeviceReduce, real64 > massProd( 0.0 ); - - // note that the dofArray will not be used after this step (simpler to use dofNumber instead) - fs.computeRhsContribution< FieldSpecificationAdd, - parallelDevicePolicy<> >( targetSet.toViewConst(), - time + dt, - dt, - subRegion, - dofNumber, - rankOffset, - localMatrix, - dofArray.toView(), - rhsContributionArrayView, - [] GEOS_HOST_DEVICE ( localIndex const ) - { - return 0.0; - } ); - - // Step 3.2: we are ready to add the right-hand side contributions, taking into account our equation layout - - // get the normalizer - real64 const sizeScalingFactor = bcAllSetsSize[bcNameToBcId.at( fs.getName())]; - integer const fluidPhaseId = fs.getComponent(); - integer const numFluidPhases = m_numPhases; - integer useTotalMassEquation = m_useTotalMassEquation; - forAll< parallelDevicePolicy<> >( targetSet.size(), [sizeScalingFactor, - targetSet, - rankOffset, - ghostRank, - fluidPhaseId, - numFluidPhases, - useTotalMassEquation, - dofNumber, - rhsContributionArrayView, - localRhs, - massProd] GEOS_HOST_DEVICE ( localIndex const a ) - { - // we need to filter out ghosts here, because targetSet may contain them - localIndex const ei = targetSet[a]; - if( ghostRank[ei] >= 0 ) - { - return; - } - - real64 const rhsValue = rhsContributionArrayView[a] / sizeScalingFactor; // scale the contribution by the sizeScalingFactor here! - massProd += rhsValue; - if( useTotalMassEquation > 0 ) - { - // for all "fluid components", we add the value to the total mass balance equation - globalIndex const totalMassBalanceRow = dofNumber[ei] - rankOffset; - localRhs[totalMassBalanceRow] += rhsValue; - if( fluidPhaseId < numFluidPhases - 1 ) - { - globalIndex const compMassBalanceRow = totalMassBalanceRow + fluidPhaseId + 1; // component mass bal equations are shifted - localRhs[compMassBalanceRow] += rhsValue; - } - } - else - { - globalIndex const compMassBalanceRow = dofNumber[ei] - rankOffset + fluidPhaseId; - localRhs[compMassBalanceRow] += rhsValue; - } - } ); - - SourceFluxStatsAggregator::forAllFluxStatWrappers( subRegion, fs.getName(), - [&]( SourceFluxStatsAggregator::WrappedStats & wrapper ) - { - // set the new sub-region statistics for this timestep - array1d< real64 > massProdArr{ m_numPhases }; - massProdArr[fluidPhaseId] = massProd.get(); - wrapper.gatherTimeStepStats( time, dt, massProdArr.toViewConst(), targetSet.size() ); - } ); - } ); - } ); - } - - real64 ImmiscibleMultiphaseFlow::calculateResidualNorm( real64 const & GEOS_UNUSED_PARAM( time_n ), - real64 const & GEOS_UNUSED_PARAM( dt ), - DomainPartition const & domain, - DofManager const & dofManager, - arrayView1d< real64 const > const & localRhs ) - { - GEOS_MARK_FUNCTION; - array1d< real64 > localResidualNorm; - array1d< real64 > localResidualNormalizer; - localResidualNorm.resize( numNorm ); - localResidualNormalizer.resize( numNorm ); - - physicsSolverBaseKernels::NormType const normType = getNonlinearSolverParameters().normType(); - - globalIndex const rankOffset = dofManager.rankOffset(); - string const dofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); - - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel const & mesh, - string_array const & regionNames ) - { - mesh.getElemManager().forElementSubRegions( regionNames, - [&]( localIndex const, - ElementSubRegionBase const & subRegion ) - { - real64 subRegionResidualNorm[numNorm]{}; - real64 subRegionResidualNormalizer[numNorm]{}; - - string const & solidName = subRegion.getReference< string >( viewKeyStruct::solidNamesString() ); - CoupledSolidBase const & solid = getConstitutiveModel< CoupledSolidBase >( subRegion, solidName ); - - // step 1: compute the norm in the subRegion - - real64 subRegionFlowResidualNorm[1]{}; - real64 subRegionFlowResidualNormalizer[1]{}; - - immiscibleMultiphaseKernels:: - ResidualNormKernelFactory::createAndLaunch< parallelDevicePolicy<> >( normType, - 2, - rankOffset, - dofKey, - localRhs, - subRegion, - solid, - m_nonlinearSolverParameters.m_minNormalizer, - subRegionFlowResidualNorm, - subRegionFlowResidualNormalizer ); - subRegionResidualNorm[0] = subRegionFlowResidualNorm[0]; - subRegionResidualNormalizer[0] = subRegionFlowResidualNormalizer[0]; - - // step 2: first reduction across meshBodies/regions/subRegions - if( normType == physicsSolverBaseKernels::NormType::Linf ) - { - physicsSolverBaseKernels::LinfResidualNormHelper:: - updateLocalNorm< numNorm >( subRegionResidualNorm, localResidualNorm ); - } - else - { - physicsSolverBaseKernels::L2ResidualNormHelper:: - updateLocalNorm< numNorm >( subRegionResidualNorm, subRegionResidualNormalizer, localResidualNorm, localResidualNormalizer ); - } - } ); - } ); - - real64 residualNorm = 0.0; - residualNorm = localResidualNorm[0]; - if( normType == physicsSolverBaseKernels::NormType::Linf ) - { - physicsSolverBaseKernels::LinfResidualNormHelper::computeGlobalNorm( localResidualNorm[0], residualNorm ); - } - else - { - physicsSolverBaseKernels::L2ResidualNormHelper::computeGlobalNorm( localResidualNorm[0], localResidualNormalizer[0], residualNorm ); - } - + + if( bcCounter == 0 ) + { + return; + } + + // Step 2: count the set size for each source flux (each source flux may have multiple target sets) + + array1d< globalIndex > bcAllSetsSize( bcNameToBcId.size() ); + + computeSourceFluxSizeScalingFactor( time, + dt, + domain, + bcNameToBcId, + bcAllSetsSize.toView() ); + + // Step 3: we are ready to impose the boundary condition, normalized by the set size + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + string_array const & ) + { + + fsManager.apply< ElementSubRegionBase, + SourceFluxBoundaryCondition >( time + dt, + mesh, + SourceFluxBoundaryCondition::catalogName(), + [&]( SourceFluxBoundaryCondition const & fs, + string const & setName, + SortedArrayView< localIndex const > const & targetSet, + ElementSubRegionBase & subRegion, + string const & ) + { + if( fs.getLogLevel() >= 1 && m_nonlinearSolverParameters.m_numNewtonIterations == 0 ) + { + globalIndex const numTargetElems = MpiWrapper::sum< globalIndex >( targetSet.size() ); + GEOS_LOG_RANK_0( GEOS_FMT( bcLogMessage, + getName(), time+dt, fs.getCatalogName(), fs.getName(), + setName, subRegion.getName(), fs.getScale(), numTargetElems ) ); + } + + if( targetSet.size() == 0 ) + { + return; + } + if( !subRegion.hasWrapper( dofKey ) ) + { + if( fs.getLogLevel() >= 1 ) + { + GEOS_LOG_RANK( GEOS_FMT( "{}: trying to apply SourceFlux, but its targetSet named '{}' intersects with non-simulated region named '{}'.", + getDataContext(), setName, subRegion.getName() ) ); + } + return; + } + + arrayView1d< globalIndex const > const dofNumber = subRegion.getReference< array1d< globalIndex > >( dofKey ); + arrayView1d< integer const > const ghostRank = subRegion.ghostRank(); + + // Step 3.1: get the values of the source boundary condition that need to be added to the rhs + + array1d< globalIndex > dofArray( targetSet.size() ); + array1d< real64 > rhsContributionArray( targetSet.size() ); + arrayView1d< real64 > rhsContributionArrayView = rhsContributionArray.toView(); + localIndex const rankOffset = dofManager.rankOffset(); + + RAJA::ReduceSum< parallelDeviceReduce, real64 > massProd( 0.0 ); + + // note that the dofArray will not be used after this step (simpler to use dofNumber instead) + fs.computeRhsContribution< FieldSpecificationAdd, + parallelDevicePolicy<> >( targetSet.toViewConst(), + time + dt, + dt, + subRegion, + dofNumber, + rankOffset, + localMatrix, + dofArray.toView(), + rhsContributionArrayView, + [] GEOS_HOST_DEVICE ( localIndex const ) + { + return 0.0; + } ); + + // Step 3.2: we are ready to add the right-hand side contributions, taking into account our equation layout + + // get the normalizer + real64 const sizeScalingFactor = bcAllSetsSize[bcNameToBcId.at( fs.getName())]; + integer const fluidPhaseId = fs.getComponent(); + integer const numFluidPhases = m_numPhases; + integer useTotalMassEquation = m_useTotalMassEquation; + forAll< parallelDevicePolicy<> >( targetSet.size(), [sizeScalingFactor, + targetSet, + rankOffset, + ghostRank, + fluidPhaseId, + numFluidPhases, + useTotalMassEquation, + dofNumber, + rhsContributionArrayView, + localRhs, + massProd] GEOS_HOST_DEVICE ( localIndex const a ) + { + // we need to filter out ghosts here, because targetSet may contain them + localIndex const ei = targetSet[a]; + if( ghostRank[ei] >= 0 ) + { + return; + } + + real64 const rhsValue = rhsContributionArrayView[a] / sizeScalingFactor; // scale the contribution by the sizeScalingFactor here! + massProd += rhsValue; + if( useTotalMassEquation > 0 ) + { + // for all "fluid components", we add the value to the total mass balance equation + globalIndex const totalMassBalanceRow = dofNumber[ei] - rankOffset; + localRhs[totalMassBalanceRow] += rhsValue; + if( fluidPhaseId < numFluidPhases - 1 ) + { + globalIndex const compMassBalanceRow = totalMassBalanceRow + fluidPhaseId + 1; // component mass bal equations are shifted + localRhs[compMassBalanceRow] += rhsValue; + } + } + else + { + globalIndex const compMassBalanceRow = dofNumber[ei] - rankOffset + fluidPhaseId; + localRhs[compMassBalanceRow] += rhsValue; + } + } ); + + SourceFluxStatsAggregator::forAllFluxStatWrappers( subRegion, fs.getName(), + [&]( SourceFluxStatsAggregator::WrappedStats & wrapper ) + { + // set the new sub-region statistics for this timestep + array1d< real64 > massProdArr{ m_numPhases }; + massProdArr[fluidPhaseId] = massProd.get(); + wrapper.gatherTimeStepStats( time, dt, massProdArr.toViewConst(), targetSet.size() ); + } ); + } ); + } ); +} + +real64 ImmiscibleMultiphaseFlow::calculateResidualNorm( real64 const & GEOS_UNUSED_PARAM( time_n ), + real64 const & GEOS_UNUSED_PARAM( dt ), + DomainPartition const & domain, + DofManager const & dofManager, + arrayView1d< real64 const > const & localRhs ) +{ + GEOS_MARK_FUNCTION; + array1d< real64 > localResidualNorm; + array1d< real64 > localResidualNormalizer; + localResidualNorm.resize( numNorm ); + localResidualNormalizer.resize( numNorm ); + + physicsSolverBaseKernels::NormType const normType = getNonlinearSolverParameters().normType(); + + globalIndex const rankOffset = dofManager.rankOffset(); + string const dofKey = dofManager.getKey( viewKeyStruct::elemDofFieldString() ); + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel const & mesh, + string_array const & regionNames ) + { + mesh.getElemManager().forElementSubRegions( regionNames, + [&]( localIndex const, + ElementSubRegionBase const & subRegion ) + { + real64 subRegionResidualNorm[numNorm]{}; + real64 subRegionResidualNormalizer[numNorm]{}; + + string const & solidName = subRegion.getReference< string >( viewKeyStruct::solidNamesString() ); + CoupledSolidBase const & solid = getConstitutiveModel< CoupledSolidBase >( subRegion, solidName ); + + // step 1: compute the norm in the subRegion + + real64 subRegionFlowResidualNorm[1]{}; + real64 subRegionFlowResidualNormalizer[1]{}; + + immiscibleMultiphaseKernels:: + ResidualNormKernelFactory::createAndLaunch< parallelDevicePolicy<> >( normType, + 2, + rankOffset, + dofKey, + localRhs, + subRegion, + solid, + m_nonlinearSolverParameters.m_minNormalizer, + subRegionFlowResidualNorm, + subRegionFlowResidualNormalizer ); + subRegionResidualNorm[0] = subRegionFlowResidualNorm[0]; + subRegionResidualNormalizer[0] = subRegionFlowResidualNormalizer[0]; + + // step 2: first reduction across meshBodies/regions/subRegions + if( normType == physicsSolverBaseKernels::NormType::Linf ) + { + physicsSolverBaseKernels::LinfResidualNormHelper:: + updateLocalNorm< numNorm >( subRegionResidualNorm, localResidualNorm ); + } + else + { + physicsSolverBaseKernels::L2ResidualNormHelper:: + updateLocalNorm< numNorm >( subRegionResidualNorm, subRegionResidualNormalizer, localResidualNorm, localResidualNormalizer ); + } + } ); + } ); + + real64 residualNorm = 0.0; + residualNorm = localResidualNorm[0]; + if( normType == physicsSolverBaseKernels::NormType::Linf ) + { + physicsSolverBaseKernels::LinfResidualNormHelper::computeGlobalNorm( localResidualNorm[0], residualNorm ); + } + else + { + physicsSolverBaseKernels::L2ResidualNormHelper::computeGlobalNorm( localResidualNorm[0], localResidualNormalizer[0], residualNorm ); + } + GEOS_LOG_LEVEL_RANK_0_NLR( logInfo::ResidualNorm, GEOS_FMT( " ( R{} ) = ( {:4.2e} )", coupledSolverAttributePrefix(), residualNorm )) - - return residualNorm; - } - - void ImmiscibleMultiphaseFlow::applySystemSolution( DofManager const & dofManager, - arrayView1d< real64 const > const & localSolution, - real64 const scalingFactor, - real64 const dt, - DomainPartition & domain ) - { - GEOS_UNUSED_VAR( dt ); - - DofManager::CompMask pressureMask( m_numDofPerCell, 0, 1 ); - - // 1. apply the pressure update - dofManager.addVectorToField( localSolution, - viewKeyStruct::elemDofFieldString(), - fields::flow::pressure::key(), - scalingFactor, - pressureMask ); - - // 2. apply the phaseVolumeFraction update - dofManager.addVectorToField( localSolution, - viewKeyStruct::elemDofFieldString(), - fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key(), - scalingFactor, - ~pressureMask ); - - // 3. synchronize - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, - MeshLevel & mesh, - string_array const & regionNames ) - { - std::vector< string > fields{ fields::flow::pressure::key(), fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key() }; - - FieldIdentifiers fieldsToBeSync; - fieldsToBeSync.addElementFields( fields, regionNames ); - - CommunicationTools::getInstance().synchronizeFields( fieldsToBeSync, mesh, domain.getNeighbors(), true ); - } ); - } - - - void ImmiscibleMultiphaseFlow::updateVolumeConstraint( ElementSubRegionBase & subRegion ) const - { - GEOS_MARK_FUNCTION; - - arrayView2d< real64, immiscibleFlow::USD_PHASE > const phaseVolumeFraction = subRegion.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); - - forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const ei ) - { - phaseVolumeFraction[ei][0] = fmin( 1.0, fmax( phaseVolumeFraction[ei][0], 0.0 )); ; - phaseVolumeFraction[ei][1] = 1.0 - phaseVolumeFraction[ei][0]; - } ); - } - - - void ImmiscibleMultiphaseFlow::resetStateToBeginningOfStep( DomainPartition & domain ) - { - GEOS_MARK_FUNCTION; - - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel & mesh, - string_array const & regionNames ) - { - mesh.getElemManager().forElementSubRegions< CellElementSubRegion, - SurfaceElementSubRegion >( regionNames, - [&]( localIndex const, - auto & subRegion ) - { - arrayView1d< real64 > const & pres = - subRegion.template getField< fields::flow::pressure >(); - arrayView1d< real64 const > const & pres_n = - subRegion.template getField< fields::flow::pressure_n >(); - pres.setValues< parallelDevicePolicy<> >( pres_n ); - - // after the update, save the new saturation - arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac_n = - subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction_n >(); - - arrayView2d< real64, immiscibleFlow::USD_PHASE > const phaseVolFrac = - subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); - phaseVolFrac.setValues< parallelDevicePolicy<> >( phaseVolFrac_n ); - - arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const & phaseMass_n = - subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseMass_n >(); - - arrayView2d< real64, immiscibleFlow::USD_PHASE > const & phaseMass = - subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseMass >(); - phaseMass.setValues< parallelDevicePolicy<> >( phaseMass_n ); - - if( m_isThermal ) - { - arrayView1d< real64 > const & temp = - subRegion.template getField< fields::flow::temperature >(); - arrayView1d< real64 const > const & temp_n = - subRegion.template getField< fields::flow::temperature_n >(); - temp.setValues< parallelDevicePolicy<> >( temp_n ); - } - - // update porosity, permeability - updatePorosityAndPermeability( subRegion ); - // update all fluid properties - updateFluidState( subRegion ); - } ); - } ); - } - - void ImmiscibleMultiphaseFlow::implicitStepComplete( real64 const & time, - real64 const & dt, - DomainPartition & domain ) - { - // Step 1: save the converged aquifer state - // note: we have to save the aquifer state **before** updating the pressure, - // otherwise the aquifer flux is saved with the wrong pressure time level - saveAquiferConvergedState( time, dt, domain ); - - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel & mesh, - string_array const & regionNames ) - { - mesh.getElemManager().forElementSubRegions( regionNames, - [&]( localIndex const, - ElementSubRegionBase & subRegion ) - { - // Step 3: save the converged solid state - string const & solidName = subRegion.getReference< string >( viewKeyStruct::solidNamesString() ); - CoupledSolidBase const & porousMaterial = getConstitutiveModel< CoupledSolidBase >( subRegion, solidName ); - if( m_keepVariablesConstantDuringInitStep ) - { - porousMaterial.ignoreConvergedState(); // newPorosity <- porosity_n - } - else - { - porousMaterial.saveConvergedState(); // porosity_n <- porosity - } - - // Step 4: save converged state for the relperm model to handle hysteresis - arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac = - subRegion.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); - string const & relPermName = subRegion.getReference< string >( viewKeyStruct::relPermNamesString() ); - RelativePermeabilityBase const & relPermMaterial = - getConstitutiveModel< RelativePermeabilityBase >( subRegion, relPermName ); - relPermMaterial.saveConvergedPhaseVolFractionState( phaseVolFrac ); - - // Step 5: if capillary pressure is supported, send the converged porosity and permeability to the capillary pressure model - // note: this is needed when the capillary pressure depends on porosity and permeability (Leverett J-function for instance) - if( m_hasCapPressure ) - { - arrayView2d< real64 const > const porosity = porousMaterial.getPorosity(); - - string const & permName = subRegion.getReference< string >( viewKeyStruct::permeabilityNamesString() ); - PermeabilityBase const & permeabilityMaterial = - getConstitutiveModel< PermeabilityBase >( subRegion, permName ); - arrayView3d< real64 const > const permeability = permeabilityMaterial.permeability(); - - string const & capPressName = subRegion.getReference< string >( viewKeyStruct::capPressureNamesString() ); - CapillaryPressureBase const & capPressureMaterial = - getConstitutiveModel< CapillaryPressureBase >( subRegion, capPressName ); - capPressureMaterial.saveConvergedRockState( porosity, permeability ); - } - } ); - } ); - } - - void ImmiscibleMultiphaseFlow::saveConvergedState( ElementSubRegionBase & subRegion ) const - { - FlowSolverBase::saveConvergedState( subRegion ); - - arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac = - subRegion.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); - arrayView2d< real64, immiscibleFlow::USD_PHASE > const phaseVolFrac_n = - subRegion.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction_n >(); - phaseVolFrac_n.setValues< parallelDevicePolicy<> >( phaseVolFrac ); - - arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseMass = - subRegion.getField< fields::immiscibleMultiphaseFlow::phaseMass >(); - arrayView2d< real64, immiscibleFlow::USD_PHASE > const phaseMass_n = - subRegion.getField< fields::immiscibleMultiphaseFlow::phaseMass_n >(); - phaseMass_n.setValues< parallelDevicePolicy<> >( phaseMass ); - - } - - void ImmiscibleMultiphaseFlow::updateState( DomainPartition & domain ) - { - GEOS_MARK_FUNCTION; - - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, - MeshLevel & mesh, - string_array const & regionNames ) - { - mesh.getElemManager().forElementSubRegions< CellElementSubRegion, - SurfaceElementSubRegion >( regionNames, [&]( localIndex const, - auto & subRegion ) - { - // update porosity, permeability, and solid internal energy - updatePorosityAndPermeability( subRegion ); - // update all fluid properties - updateVolumeConstraint( subRegion ); - updateFluidState( subRegion ); - } ); - } ); - } - - real64 ImmiscibleMultiphaseFlow::setNextDtBasedOnStateChange( real64 const & currentDt, - DomainPartition & domain ) - { - if( m_targetRelativePresChange >= 1.0 && - m_targetPhaseVolFracChange >= 1.0 ) - { - return LvArray::NumericLimits< real64 >::max; - } - - real64 maxRelativePresChange = 0.0; - real64 maxAbsolutePhaseVolFracChange = 0.0; - - integer const numPhase = m_numPhases; - - forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + + return residualNorm; +} + +void ImmiscibleMultiphaseFlow::applySystemSolution( DofManager const & dofManager, + arrayView1d< real64 const > const & localSolution, + real64 const scalingFactor, + real64 const dt, + DomainPartition & domain ) +{ + GEOS_UNUSED_VAR( dt ); + + DofManager::CompMask pressureMask( m_numDofPerCell, 0, 1 ); + + // 1. apply the pressure update + dofManager.addVectorToField( localSolution, + viewKeyStruct::elemDofFieldString(), + fields::flow::pressure::key(), + scalingFactor, + pressureMask ); + + // 2. apply the phaseVolumeFraction update + dofManager.addVectorToField( localSolution, + viewKeyStruct::elemDofFieldString(), + fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key(), + scalingFactor, + ~pressureMask ); + + // 3. synchronize + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&] ( string const &, MeshLevel & mesh, string_array const & regionNames ) - { - mesh.getElemManager().forElementSubRegions( regionNames, - [&]( localIndex const, - ElementSubRegionBase & subRegion ) - { - arrayView1d< integer const > const ghostRank = subRegion.ghostRank(); - - arrayView1d< real64 const > const pres = subRegion.getField< fields::flow::pressure >(); - arrayView1d< real64 const > const pres_n = subRegion.getField< fields::flow::pressure_n >(); - arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac = - subRegion.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); - arrayView2d< real64, immiscibleFlow::USD_PHASE > const phaseVolFrac_n = - subRegion.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction_n >(); - - RAJA::ReduceMax< parallelDeviceReduce, real64 > subRegionMaxPresChange( 0.0 ); - RAJA::ReduceMax< parallelDeviceReduce, real64 > subRegionMaxPhaseVolFracChange( 0.0 ); - - forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const ei ) - { - if( ghostRank[ei] < 0 ) - { - // switch from relative to absolute when values less than 1 - subRegionMaxPresChange.max( LvArray::math::abs( pres[ei] - pres_n[ei] ) / LvArray::math::max( LvArray::math::abs( pres_n[ei] ), 1.0 ) ); - for( integer ip = 0; ip < numPhase; ++ip ) - { - subRegionMaxPhaseVolFracChange.max( LvArray::math::abs( phaseVolFrac[ei][ip] - phaseVolFrac_n[ei][ip] ) ); - } - } - } ); - - maxRelativePresChange = LvArray::math::max( maxRelativePresChange, subRegionMaxPresChange.get() ); - maxAbsolutePhaseVolFracChange = LvArray::math::max( maxAbsolutePhaseVolFracChange, subRegionMaxPhaseVolFracChange.get() ); - - } ); - } ); - - maxRelativePresChange = MpiWrapper::max( maxRelativePresChange ); - maxAbsolutePhaseVolFracChange = MpiWrapper::max( maxAbsolutePhaseVolFracChange ); - - GEOS_LOG_LEVEL_RANK_0( logInfo::TimeStep, GEOS_FMT( "{}: max relative pressure change during time step = {} %", - getName(), GEOS_FMT( "{:.{}f}", 100*maxRelativePresChange, 3 ) ) ); - GEOS_LOG_LEVEL_RANK_0( logInfo::TimeStep, GEOS_FMT( "{}: max absolute phase volume fraction change during time step = {}", - getName(), GEOS_FMT( "{:.{}f}", maxAbsolutePhaseVolFracChange, 3 ) ) ); - - real64 const eps = LvArray::NumericLimits< real64 >::epsilon; - - real64 const nextDtPressure = currentDt * ( 1.0 + m_solutionChangeScalingFactor ) * m_targetRelativePresChange - / std::max( eps, maxRelativePresChange + m_solutionChangeScalingFactor * m_targetRelativePresChange ); - if( m_nonlinearSolverParameters.getLogLevel() > 0 ) - GEOS_LOG_RANK_0( GEOS_FMT( "{}: next time step based on pressure change = {}", getName(), nextDtPressure )); - real64 const nextDtPhaseVolFrac = currentDt * ( 1.0 + m_solutionChangeScalingFactor ) * m_targetPhaseVolFracChange - / std::max( eps, maxAbsolutePhaseVolFracChange + m_solutionChangeScalingFactor * m_targetPhaseVolFracChange ); - if( m_nonlinearSolverParameters.getLogLevel() > 0 ) - GEOS_LOG_RANK_0( GEOS_FMT( "{}: next time step based on phase volume fraction change = {}", getName(), nextDtPhaseVolFrac )); - - return std::min( nextDtPressure, nextDtPhaseVolFrac ); - - } - - REGISTER_CATALOG_ENTRY( PhysicsSolverBase, ImmiscibleMultiphaseFlow, string const &, Group * const ) - - } // namespace geos - + { + std::vector< string > fields{ fields::flow::pressure::key(), fields::immiscibleMultiphaseFlow::phaseVolumeFraction::key() }; + + FieldIdentifiers fieldsToBeSync; + fieldsToBeSync.addElementFields( fields, regionNames ); + + CommunicationTools::getInstance().synchronizeFields( fieldsToBeSync, mesh, domain.getNeighbors(), true ); + } ); +} + + +void ImmiscibleMultiphaseFlow::updateVolumeConstraint( ElementSubRegionBase & subRegion ) const +{ + GEOS_MARK_FUNCTION; + + arrayView2d< real64, immiscibleFlow::USD_PHASE > const phaseVolumeFraction = subRegion.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); + + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const ei ) + { + phaseVolumeFraction[ei][0] = fmin( 1.0, fmax( phaseVolumeFraction[ei][0], 0.0 ));; + phaseVolumeFraction[ei][1] = 1.0 - phaseVolumeFraction[ei][0]; + } ); +} + + +void ImmiscibleMultiphaseFlow::resetStateToBeginningOfStep( DomainPartition & domain ) +{ + GEOS_MARK_FUNCTION; + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + mesh.getElemManager().forElementSubRegions< CellElementSubRegion, + SurfaceElementSubRegion >( regionNames, + [&]( localIndex const, + auto & subRegion ) + { + arrayView1d< real64 > const & pres = + subRegion.template getField< fields::flow::pressure >(); + arrayView1d< real64 const > const & pres_n = + subRegion.template getField< fields::flow::pressure_n >(); + pres.setValues< parallelDevicePolicy<> >( pres_n ); + + // after the update, save the new saturation + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac_n = + subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction_n >(); + + arrayView2d< real64, immiscibleFlow::USD_PHASE > const phaseVolFrac = + subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); + phaseVolFrac.setValues< parallelDevicePolicy<> >( phaseVolFrac_n ); + + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const & phaseMass_n = + subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseMass_n >(); + + arrayView2d< real64, immiscibleFlow::USD_PHASE > const & phaseMass = + subRegion.template getField< fields::immiscibleMultiphaseFlow::phaseMass >(); + phaseMass.setValues< parallelDevicePolicy<> >( phaseMass_n ); + + if( m_isThermal ) + { + arrayView1d< real64 > const & temp = + subRegion.template getField< fields::flow::temperature >(); + arrayView1d< real64 const > const & temp_n = + subRegion.template getField< fields::flow::temperature_n >(); + temp.setValues< parallelDevicePolicy<> >( temp_n ); + } + + // update porosity, permeability + updatePorosityAndPermeability( subRegion ); + // update all fluid properties + updateFluidState( subRegion ); + } ); + } ); +} + +void ImmiscibleMultiphaseFlow::implicitStepComplete( real64 const & time, + real64 const & dt, + DomainPartition & domain ) +{ + // Step 1: save the converged aquifer state + // note: we have to save the aquifer state **before** updating the pressure, + // otherwise the aquifer flux is saved with the wrong pressure time level + saveAquiferConvergedState( time, dt, domain ); + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + mesh.getElemManager().forElementSubRegions( regionNames, + [&]( localIndex const, + ElementSubRegionBase & subRegion ) + { + // Step 3: save the converged solid state + string const & solidName = subRegion.getReference< string >( viewKeyStruct::solidNamesString() ); + CoupledSolidBase const & porousMaterial = getConstitutiveModel< CoupledSolidBase >( subRegion, solidName ); + if( m_keepVariablesConstantDuringInitStep ) + { + porousMaterial.ignoreConvergedState(); // newPorosity <- porosity_n + } + else + { + porousMaterial.saveConvergedState(); // porosity_n <- porosity + } + + // Step 4: save converged state for the relperm model to handle hysteresis + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac = + subRegion.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); + string const & relPermName = subRegion.getReference< string >( viewKeyStruct::relPermNamesString() ); + RelativePermeabilityBase const & relPermMaterial = + getConstitutiveModel< RelativePermeabilityBase >( subRegion, relPermName ); + relPermMaterial.saveConvergedPhaseVolFractionState( phaseVolFrac ); + + // Step 5: if capillary pressure is supported, send the converged porosity and permeability to the capillary pressure model + // note: this is needed when the capillary pressure depends on porosity and permeability (Leverett J-function for instance) + if( m_hasCapPressure ) + { + arrayView2d< real64 const > const porosity = porousMaterial.getPorosity(); + + string const & permName = subRegion.getReference< string >( viewKeyStruct::permeabilityNamesString() ); + PermeabilityBase const & permeabilityMaterial = + getConstitutiveModel< PermeabilityBase >( subRegion, permName ); + arrayView3d< real64 const > const permeability = permeabilityMaterial.permeability(); + + string const & capPressName = subRegion.getReference< string >( viewKeyStruct::capPressureNamesString() ); + CapillaryPressureBase const & capPressureMaterial = + getConstitutiveModel< CapillaryPressureBase >( subRegion, capPressName ); + capPressureMaterial.saveConvergedRockState( porosity, permeability ); + } + } ); + } ); +} + +void ImmiscibleMultiphaseFlow::saveConvergedState( ElementSubRegionBase & subRegion ) const +{ + FlowSolverBase::saveConvergedState( subRegion ); + + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac = + subRegion.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); + arrayView2d< real64, immiscibleFlow::USD_PHASE > const phaseVolFrac_n = + subRegion.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction_n >(); + phaseVolFrac_n.setValues< parallelDevicePolicy<> >( phaseVolFrac ); + + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseMass = + subRegion.getField< fields::immiscibleMultiphaseFlow::phaseMass >(); + arrayView2d< real64, immiscibleFlow::USD_PHASE > const phaseMass_n = + subRegion.getField< fields::immiscibleMultiphaseFlow::phaseMass_n >(); + phaseMass_n.setValues< parallelDevicePolicy<> >( phaseMass ); + +} + +void ImmiscibleMultiphaseFlow::updateState( DomainPartition & domain ) +{ + GEOS_MARK_FUNCTION; + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + mesh.getElemManager().forElementSubRegions< CellElementSubRegion, + SurfaceElementSubRegion >( regionNames, [&]( localIndex const, + auto & subRegion ) + { + // update porosity, permeability, and solid internal energy + updatePorosityAndPermeability( subRegion ); + // update all fluid properties + updateVolumeConstraint( subRegion ); + updateFluidState( subRegion ); + } ); + } ); +} + +real64 ImmiscibleMultiphaseFlow::setNextDtBasedOnStateChange( real64 const & currentDt, + DomainPartition & domain ) +{ + if( m_targetRelativePresChange >= 1.0 && + m_targetPhaseVolFracChange >= 1.0 ) + { + return LvArray::NumericLimits< real64 >::max; + } + + real64 maxRelativePresChange = 0.0; + real64 maxAbsolutePhaseVolFracChange = 0.0; + + integer const numPhase = m_numPhases; + + forDiscretizationOnMeshTargets( domain.getMeshBodies(), [&]( string const &, + MeshLevel & mesh, + string_array const & regionNames ) + { + mesh.getElemManager().forElementSubRegions( regionNames, + [&]( localIndex const, + ElementSubRegionBase & subRegion ) + { + arrayView1d< integer const > const ghostRank = subRegion.ghostRank(); + + arrayView1d< real64 const > const pres = subRegion.getField< fields::flow::pressure >(); + arrayView1d< real64 const > const pres_n = subRegion.getField< fields::flow::pressure_n >(); + arrayView2d< real64 const, immiscibleFlow::USD_PHASE > const phaseVolFrac = + subRegion.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction >(); + arrayView2d< real64, immiscibleFlow::USD_PHASE > const phaseVolFrac_n = + subRegion.getField< fields::immiscibleMultiphaseFlow::phaseVolumeFraction_n >(); + + RAJA::ReduceMax< parallelDeviceReduce, real64 > subRegionMaxPresChange( 0.0 ); + RAJA::ReduceMax< parallelDeviceReduce, real64 > subRegionMaxPhaseVolFracChange( 0.0 ); + + forAll< parallelDevicePolicy<> >( subRegion.size(), [=] GEOS_HOST_DEVICE ( localIndex const ei ) + { + if( ghostRank[ei] < 0 ) + { + // switch from relative to absolute when values less than 1 + subRegionMaxPresChange.max( LvArray::math::abs( pres[ei] - pres_n[ei] ) / LvArray::math::max( LvArray::math::abs( pres_n[ei] ), 1.0 ) ); + for( integer ip = 0; ip < numPhase; ++ip ) + { + subRegionMaxPhaseVolFracChange.max( LvArray::math::abs( phaseVolFrac[ei][ip] - phaseVolFrac_n[ei][ip] ) ); + } + } + } ); + + maxRelativePresChange = LvArray::math::max( maxRelativePresChange, subRegionMaxPresChange.get() ); + maxAbsolutePhaseVolFracChange = LvArray::math::max( maxAbsolutePhaseVolFracChange, subRegionMaxPhaseVolFracChange.get() ); + + } ); + } ); + + maxRelativePresChange = MpiWrapper::max( maxRelativePresChange ); + maxAbsolutePhaseVolFracChange = MpiWrapper::max( maxAbsolutePhaseVolFracChange ); + + GEOS_LOG_LEVEL_RANK_0( logInfo::TimeStep, GEOS_FMT( "{}: max relative pressure change during time step = {} %", + getName(), GEOS_FMT( "{:.{}f}", 100*maxRelativePresChange, 3 ) ) ); + GEOS_LOG_LEVEL_RANK_0( logInfo::TimeStep, GEOS_FMT( "{}: max absolute phase volume fraction change during time step = {}", + getName(), GEOS_FMT( "{:.{}f}", maxAbsolutePhaseVolFracChange, 3 ) ) ); + + real64 const eps = LvArray::NumericLimits< real64 >::epsilon; + + real64 const nextDtPressure = currentDt * ( 1.0 + m_solutionChangeScalingFactor ) * m_targetRelativePresChange + / std::max( eps, maxRelativePresChange + m_solutionChangeScalingFactor * m_targetRelativePresChange ); + if( m_nonlinearSolverParameters.getLogLevel() > 0 ) + GEOS_LOG_RANK_0( GEOS_FMT( "{}: next time step based on pressure change = {}", getName(), nextDtPressure )); + real64 const nextDtPhaseVolFrac = currentDt * ( 1.0 + m_solutionChangeScalingFactor ) * m_targetPhaseVolFracChange + / std::max( eps, maxAbsolutePhaseVolFracChange + m_solutionChangeScalingFactor * m_targetPhaseVolFracChange ); + if( m_nonlinearSolverParameters.getLogLevel() > 0 ) + GEOS_LOG_RANK_0( GEOS_FMT( "{}: next time step based on phase volume fraction change = {}", getName(), nextDtPhaseVolFrac )); + + return std::min( nextDtPressure, nextDtPhaseVolFrac ); + +} + +REGISTER_CATALOG_ENTRY( PhysicsSolverBase, ImmiscibleMultiphaseFlow, string const &, Group * const ) + +} // namespace geos diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp index f9535bbadba..d1fdeb72625 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp @@ -75,7 +75,7 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< stdVector< real64 > trappedSats2, stdVector< real64 > transHat, stdVector< real64 > dTransHat_dP, stdVector< real64 > gravCoefHat, stdVector< real64 > gravCoef, stdVector< real64 > cellCenterDuT, stdVector< real64 > cellCenterDens, stdVector< real64 > cellCenterDens_dP, std::vector< RelativePermeabilityBase * > relPerms, std::vector< CapillaryPressureBase * > capPressures, - std::vector< TwoPhaseImmiscibleFluid * > fluids, std::vector< real64 > &phi, std::vector< real64 > &grad_phi_P, std::vector< real64 > &grad_phi_S, bool &converged ) + std::vector< TwoPhaseImmiscibleFluid * > fluids, std::vector< real64 > & phi, std::vector< real64 > & grad_phi_P, std::vector< real64 > & grad_phi_S, bool & converged ) { // getting wrappers: @@ -204,8 +204,8 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< real64 density2[2]{}; real64 dDens_dP2[2][2]{}; - density2[0] = cellCenterDens[0]; - density2[1] = cellCenterDens[1]; + density2[0] = cellCenterDens[0]; + density2[1] = cellCenterDens[1]; dDens_dP2[0][0] = cellCenterDens_dP[0]; dDens_dP2[0][1] = cellCenterDens_dP[1]; @@ -452,18 +452,18 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< real64 dhalfFlux_dpc[2][2]{}; //new - real64 fluxVal[2]{}; - real64 dFlux_dP[2][2]{}; - real64 dFlux_dS[2][2]{}; + real64 fluxVal[2]{}; + real64 dFlux_dP[2][2]{}; + real64 dFlux_dS[2][2]{}; - real64 duT_dP[2]{}; - real64 duT_dS[2]{}; + real64 duT_dP[2]{}; + real64 duT_dS[2]{}; - duT_dP[0] = cellCenterDuT[0]; - duT_dP[1] = cellCenterDuT[1]; + duT_dP[0] = cellCenterDuT[0]; + duT_dP[1] = cellCenterDuT[1]; - duT_dS[0] = cellCenterDuT[2]; - duT_dS[1] = cellCenterDuT[3]; + duT_dS[0] = cellCenterDuT[2]; + duT_dS[1] = cellCenterDuT[3]; // initial guess: @@ -488,19 +488,21 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< real64 next_Pc_int = 0.0; real64 old_Pc_int = 0.0; real64 old_residual = 0.0; - - if (bisection) { + + if( bisection ) + { Pc_int = fmax( Pc1_max, Pc2_max ); next_Pc_int = fmin( Pc1_min, Pc2_min ); } - if (newton_path){ + if( newton_path ) + { Pc_int = fmax( Pc1_max, Pc2_max ); - Pc_int = 2.0e5; - next_Pc_int = (fmax( Pc1_max, Pc2_max ) - fmin( Pc1_min, Pc2_min )) / (max_iter - 1); - next_Pc_int = (2.0e5 - 5.0e4) / (max_iter - 1); + Pc_int = 2.0e5; + next_Pc_int = (fmax( Pc1_max, Pc2_max ) - fmin( Pc1_min, Pc2_min )) / (max_iter - 1); + next_Pc_int = (2.0e5 - 5.0e4) / (max_iter - 1); } - + real64 Pc_int_iterate = Pc_int; while( iter < max_iter ) @@ -538,9 +540,9 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< // truncate the capillary pressure iterate (ensures the inverse will compute a saturation bounded between 0 and 1): Pc_int = fmin( fmax( Pc1_max, Pc2_max ), fmax( Pc_int, fmin( Pc1_min, Pc2_min ) )); - - faceCapPres1[0][0][0] = fmin( Pc1_max, fmax( Pc_int, Pc1_min)); - faceCapPres2[0][0][0] = fmin( Pc2_max, fmax( Pc_int, Pc2_min)); + + faceCapPres1[0][0][0] = fmin( Pc1_max, fmax( Pc_int, Pc1_min )); + faceCapPres2[0][0][0] = fmin( Pc2_max, fmax( Pc_int, Pc2_min )); // Compute the inverse: @@ -565,8 +567,8 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< else { capPresWrapper1.computeInv( facePhaseVolFrac1[0], - faceCapPres1[0][0], - dfacePhaseVolFrac_dCapPres1[0][0] ); + faceCapPres1[0][0], + dfacePhaseVolFrac_dCapPres1[0][0] ); facePhaseVolFrac1[0][0] = fmin( 1.0, fmax( facePhaseVolFrac1[0][0], 0.0 )); facePhaseVolFrac1[0][1] = fmin( 1.0, fmax( facePhaseVolFrac1[0][1], 0.0 )); //get derivatives: @@ -597,8 +599,8 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< { // evaluating cell-center Pc: capPresWrapper2.computeInv( facePhaseVolFrac2[0], - faceCapPres2[0][0], - dfacePhaseVolFrac_dCapPres2[0][0] ); + faceCapPres2[0][0], + dfacePhaseVolFrac_dCapPres2[0][0] ); facePhaseVolFrac2[0][0] = fmin( 1.0, fmax( facePhaseVolFrac2[0][0], 0.0 )); facePhaseVolFrac2[0][1] = fmin( 1.0, fmax( facePhaseVolFrac2[0][1], 0.0 )); @@ -608,7 +610,7 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< faceCapPres2[0][0], dCapPres2_dfacePhaseVolFrac[0][0] ); } - + // compute relative permeability for both faces: using T7 = std::decay_t< decltype(castedRelPerm1) >; @@ -831,9 +833,9 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< // *** upwinding *** // compute potential gradient - real64 potGrad = presGrad[ip] - gravHead[ip]; +// real64 potGrad = presGrad[ip] - gravHead[ip]; - potGrad += capGrad[ip]; +// potGrad += capGrad[ip]; // choose upstream cell constexpr int sign[2] = {1, -1}; @@ -948,7 +950,7 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< sign[ix] * sign[ip] * mobility[0] * mobility[1] / total_mobility * (dCapGrad_dP[1][ke] - dCapGrad_dP[0][ke]); real64 dC_dS_term1 = sign[ix] * sign[ip] * (dMob_dS[0][ke] * mobility[1] * mobility[1] + dMob_dS[1][ke] * mobility[0] * mobility[0]) / (total_mobility * total_mobility) * - (capGrad[1] -capGrad[0]); + (capGrad[1] -capGrad[0]); real64 dC_dS_term2 = sign[ix] * sign[ip] * (mobility[0] * mobility[1]) / total_mobility; @@ -959,12 +961,15 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< dC1_dS[ip][ke] = dC_dS_term1 + dC_dS_term2 * dC_dS_term3; dhalfFlux1_dP[ip][ke] -= dC_dP; dhalfFlux1_dS[ip][ke] -= dC1_dS[ip][ke]; - if (std::fabs(facePhaseVolFrac1[0][0] - 1.0) > 1e-8){ + if( std::fabs( facePhaseVolFrac1[0][0] - 1.0 ) > 1e-8 ) + { dC1_dpc[ip][ke] = dC1_dS[ip][ke] * dfacePhaseVolFrac_dCapPres1[0][0][0][0]; - } else { + } + else + { dC1_dpc[ip][ke] = dC_dS_term1 * dfacePhaseVolFrac_dCapPres1[0][0][0][0]; } - + // GEOS_UNUSED_VAR( dC1_dpc[ip][ke] ); } else @@ -972,9 +977,12 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< dC2_dS[ip][ke] = dC_dS_term1 + dC_dS_term2 * dC_dS_term3; dhalfFlux2_dP[ip][ke] -= dC_dP; dhalfFlux2_dS[ip][ke] -= dC2_dS[ip][ke]; - if (std::fabs(facePhaseVolFrac2[0][0] - 1.0) > 1e-8){ + if( std::fabs( facePhaseVolFrac2[0][0] - 1.0 ) > 1e-8 ) + { dC2_dpc[ip][ke] = dC2_dS[ip][ke] * dfacePhaseVolFrac_dCapPres2[0][0][0][0]; - } else { + } + else + { dC2_dpc[ip][ke] = dC_dS_term1 * dfacePhaseVolFrac_dCapPres2[0][0][0][0]; } // GEOS_UNUSED_VAR( dC2_dpc[ip][ke] ); @@ -1040,7 +1048,7 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< } else { - if( std::fabs( halfFluxVal[ip][0] ) < 1e-20 ) + if( std::fabs( halfFluxVal[ip][0] ) < 1e-20 ) { k_up_0_check[ip] = k_up_0_b; } @@ -1107,7 +1115,7 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< if( std::fabs( local_residual ) < tol ) { // if( std::fabs( dhalfFlux_dpc[0][0] - dhalfFlux_dpc[0][1] ) saturations, stdVector< } else if( div > 1 ) { - local_jacobian = 0.0; - std::cout << "**********************Diverged*******************" << std::endl; - iter = max_iter; + local_jacobian = 0.0; + std::cout << "**********************Diverged*******************" << std::endl; + iter = max_iter; } } else @@ -1141,46 +1149,55 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< if( std::fabs( local_residual ) < tol ) { - // if( std::fabs( dhalfFlux_dpc[0][0] - dhalfFlux_dpc[0][1] ) < eps2 ) { - // std::cout << "**********************ZeroJacobian*******************" << std::endl; - // } - converged = 1; + // if( std::fabs( dhalfFlux_dpc[0][0] - dhalfFlux_dpc[0][1] ) < eps2 ) { + // std::cout << "**********************ZeroJacobian*******************" << std::endl; + // } + converged = 1; break; // Converged } // Damping option: - if (damping) { - real64 max_dpc = fmax( fabs(dCapPres1_dfacePhaseVolFrac[0][0][0][0]), fabs(dCapPres2_dfacePhaseVolFrac[0][0][0][0])); - - real64 sign = std::copysign(1.0, deltaPc); - - deltaPc = fmin( fabs(deltaPc), max_dpc * 0.2 ); - deltaPc *= sign; - - } + if( damping ) + { + real64 max_dpc = fmax( fabs( dCapPres1_dfacePhaseVolFrac[0][0][0][0] ), fabs( dCapPres2_dfacePhaseVolFrac[0][0][0][0] )); - if (bisection && iter < 7){ - if ( iter == 0 ){ + real64 sign = std::copysign( 1.0, deltaPc ); + + deltaPc = fmin( fabs( deltaPc ), max_dpc * 0.2 ); + deltaPc *= sign; + + } + + if( bisection && iter < 7 ) + { + if( iter == 0 ) + { old_Pc_int = Pc_int; Pc_int = next_Pc_int; old_residual = local_residual; - } else if (old_residual * local_residual < 0.0 ) { - + } + else if( old_residual * local_residual < 0.0 ) + { + Pc_int = (next_Pc_int + old_Pc_int) / 2.0; old_residual = local_residual; old_Pc_int = next_Pc_int; next_Pc_int = Pc_int; - } else if (old_residual * local_residual > 0.0 ) { - + } + else if( old_residual * local_residual > 0.0 ) + { + Pc_int = old_Pc_int; old_residual = local_residual; old_Pc_int = next_Pc_int; next_Pc_int = Pc_int; - } else { + } + else + { Pc_int = old_Pc_int; old_residual = local_residual; @@ -1189,15 +1206,19 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< } - } else if (newton_path){ - Pc_int -= next_Pc_int; + } + else if( newton_path ) + { + Pc_int -= next_Pc_int; + + } + else + { - } else { + Pc_int -= deltaPc; - Pc_int -= deltaPc; + } - } - // truncate the updated capillary pressure (extended capillary pressure condition) for reporting/plotting: @@ -1205,7 +1226,7 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< real64 faceCapPres2_plot = fmin( Pc2_max, fmax( Pc_int, Pc2_min )); faceCapPres1_plot = fmin( Pc2_max, fmax( faceCapPres1_plot, Pc2_min )); faceCapPres2_plot = fmin( Pc1_max, fmax( faceCapPres2_plot, Pc1_min )); - + // Write data to the file outFile << GEOS_FMT( "{:10.10e}", local_jacobian ); outFile << GEOS_FMT( ",{:10.10e}", local_residual ); @@ -1238,7 +1259,7 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< } - + } // while loop if( converged ) @@ -1266,11 +1287,13 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< fluxVal[0] = halfFluxVal[0][0] * density2[0]; fluxVal[1] = halfFluxVal[1][0] * density2[1]; - } else { + } + else + { std::cout << "**********************Diverged*******************" << std::endl; } - + phi[0] = fluxVal[0]; phi[1] = fluxVal[1]; @@ -1342,7 +1365,7 @@ class FluxComputeKernelBase fields::cappres::phaseCapPressure, fields::cappres::dPhaseCapPressure_dPhaseVolFraction >; - // ,fields::cappres::jFuncMultiplier >; + // ,fields::cappres::jFuncMultiplier >; using PermeabilityAccessors = @@ -2085,8 +2108,8 @@ class FluxComputeInterfaceConditionKernel : public FluxComputeKernel< NUM_EQN, N FluxComputeInterfaceConditionKernel( integer const numPhases, globalIndex const rankOffset, STENCILWRAPPER const & stencilWrapper, - // CAPPRESWRAPPER const & capPressureWrapper, - // RELPERMWRAPPER const & relPermWrapper, + // CAPPRESWRAPPER const & capPressureWrapper, + // RELPERMWRAPPER const & relPermWrapper, DofNumberAccessor const & dofNumberAccessor, ImmiscibleMultiphaseFlowAccessors const & multiPhaseFlowAccessors, MultiphaseFluidAccessors const & fluidAccessors, @@ -2103,9 +2126,9 @@ class FluxComputeInterfaceConditionKernel : public FluxComputeKernel< NUM_EQN, N constitutive::CapillaryPressureBase *, constitutive::TwoPhaseImmiscibleFluid * >, 2 > > const & interfaceConstitutivePairs, unordered_map< localIndex, localIndex > const & interfaceRegionByConnector, - // std::tuple< constitutive::RelativePermeabilityBase *, - // constitutive::CapillaryPressureBase *, - // constitutive::TwoPhaseImmiscibleFluid * > const & interfaceConstitutivePairs_temp, + // std::tuple< constitutive::RelativePermeabilityBase *, + // constitutive::CapillaryPressureBase *, + // constitutive::TwoPhaseImmiscibleFluid * > const & interfaceConstitutivePairs_temp, localIndex const GEOS_UNUSED_PARAM( domainSize ) ) : Base( numPhases, rankOffset, @@ -2145,12 +2168,13 @@ class FluxComputeInterfaceConditionKernel : public FluxComputeKernel< NUM_EQN, N FUNC && kernelOp = NoOpFunc{} ) const { - bool connectorHasInterfaceConditionQ = false; - bool anyInterfaceConditionsQ = not m_interfaceConstitutivePairs.empty(); - if (anyInterfaceConditionsQ) { - connectorHasInterfaceConditionQ = - m_interfaceRegionByConnector.find(iconn) != m_interfaceRegionByConnector.end(); - } + bool connectorHasInterfaceConditionQ = false; + bool anyInterfaceConditionsQ = not m_interfaceConstitutivePairs.empty(); + if( anyInterfaceConditionsQ ) + { + connectorHasInterfaceConditionQ = + m_interfaceRegionByConnector.find( iconn ) != m_interfaceRegionByConnector.end(); + } @@ -2470,8 +2494,9 @@ class FluxComputeInterfaceConditionKernel : public FluxComputeKernel< NUM_EQN, N // this determines whether the local solver is needed becuase of heterogeneous capillary pressure regions - // bool notOnInterface = std::fabs( jFMultiplier[0][0] - jFMultiplier[0][1] ) < 1 && std::fabs( jFMultiplier[1][0] - jFMultiplier[1][1] ) < 1; - bool notOnInterface = !connectorHasInterfaceConditionQ; + // bool notOnInterface = std::fabs( jFMultiplier[0][0] - jFMultiplier[0][1] ) < 1 && std::fabs( jFMultiplier[1][0] - + // jFMultiplier[1][1] ) < 1; + bool notOnInterface = !connectorHasInterfaceConditionQ; if( notOnInterface ) { for( integer ip = 0; ip < 2; ++ip ) @@ -2526,47 +2551,50 @@ class FluxComputeInterfaceConditionKernel : public FluxComputeKernel< NUM_EQN, N stdVector< real64 > cellCenterDuTdS = {duT_dP[0], duT_dP[1], duT_dS[0], duT_dS[1]}; stdVector< real64 > cellCenterDens = {density2[0], density2[1]}; stdVector< real64 > cellCenterDens_dP = {dDens_dP2[0][0], dDens_dP2[0][1], dDens_dP2[1][0], dDens_dP2[1][1]}; - // std::vector< RelativePermeabilityBase * > relPerms = {std::get< 0 >( m_interfaceConstitutivePairs_temp ), std::get< 0 >( m_interfaceConstitutivePairs_temp )}; - // std::vector< CapillaryPressureBase * > capPressures = {std::get< 1 >( m_interfaceConstitutivePairs_temp ), std::get< 1 >( m_interfaceConstitutivePairs_temp )}; - // std::vector< TwoPhaseImmiscibleFluid * > fluids = {std::get< 2 >( m_interfaceConstitutivePairs_temp ), std::get< 2 >( m_interfaceConstitutivePairs_temp )}; + // std::vector< RelativePermeabilityBase * > relPerms = {std::get< 0 >( m_interfaceConstitutivePairs_temp ), std::get< 0 >( + // m_interfaceConstitutivePairs_temp )}; + // std::vector< CapillaryPressureBase * > capPressures = {std::get< 1 >( m_interfaceConstitutivePairs_temp ), std::get< 1 >( + // m_interfaceConstitutivePairs_temp )}; + // std::vector< TwoPhaseImmiscibleFluid * > fluids = {std::get< 2 >( m_interfaceConstitutivePairs_temp ), std::get< 2 >( + // m_interfaceConstitutivePairs_temp )}; // auto const & pairArray = m_interfaceConstitutivePairs[0]; - localIndex const surfaceRegionIndex = m_interfaceRegionByConnector.at(iconn); -auto const & pairArray = m_interfaceConstitutivePairs[surfaceRegionIndex]; + localIndex const surfaceRegionIndex = m_interfaceRegionByConnector.at( iconn ); + auto const & pairArray = m_interfaceConstitutivePairs[surfaceRegionIndex]; -std::vector< constitutive::RelativePermeabilityBase * > relPerms = { - std::get<0>( pairArray[0] ), - std::get<0>( pairArray[1] ) -}; + std::vector< constitutive::RelativePermeabilityBase * > relPerms = { + std::get< 0 >( pairArray[0] ), + std::get< 0 >( pairArray[1] ) + }; -std::vector< constitutive::CapillaryPressureBase * > capPressures = { - std::get<1>( pairArray[0] ), - std::get<1>( pairArray[1] ) -}; + std::vector< constitutive::CapillaryPressureBase * > capPressures = { + std::get< 1 >( pairArray[0] ), + std::get< 1 >( pairArray[1] ) + }; -std::vector< constitutive::TwoPhaseImmiscibleFluid * > fluids = { - std::get<2>( pairArray[0] ), - std::get<2>( pairArray[1] ) -}; + std::vector< constitutive::TwoPhaseImmiscibleFluid * > fluids = { + std::get< 2 >( pairArray[0] ), + std::get< 2 >( pairArray[1] ) + }; stdVector< real64 > phi = {halfFluxVal[0][0], halfFluxVal[0][1]}; stdVector< real64 > grad_phi_P = {0.0, 0.0, 0.0, 0.0}; stdVector< real64 > grad_phi_S = {0.0, 0.0, 0.0, 0.0}; - local_solver( uT, saturations, pressures, JFMultipliers, trappedSats1, trappedSats2, transHats, dTransHats_dP, gravCoefHats, gravCoefs, - cellCenterDuTdS, cellCenterDens, cellCenterDens_dP, relPerms, capPressures, fluids, phi, grad_phi_P, grad_phi_S, converged ); - - - fluxVal[0] = phi[0]; - fluxVal[1] = phi[1]; - dFlux_dP[0][0] = grad_phi_P[0]; - dFlux_dP[0][1] = grad_phi_P[1]; - dFlux_dP[1][0] = grad_phi_P[2]; - dFlux_dP[1][1] = grad_phi_P[3]; - dFlux_dS[0][0] = grad_phi_S[0]; - dFlux_dS[0][1] = grad_phi_S[1]; - dFlux_dS[1][0] = grad_phi_S[2]; - dFlux_dS[1][1] = grad_phi_S[3]; + local_solver( uT, saturations, pressures, JFMultipliers, trappedSats1, trappedSats2, transHats, dTransHats_dP, gravCoefHats, gravCoefs, + cellCenterDuTdS, cellCenterDens, cellCenterDens_dP, relPerms, capPressures, fluids, phi, grad_phi_P, grad_phi_S, converged ); + + + fluxVal[0] = phi[0]; + fluxVal[1] = phi[1]; + dFlux_dP[0][0] = grad_phi_P[0]; + dFlux_dP[0][1] = grad_phi_P[1]; + dFlux_dP[1][0] = grad_phi_P[2]; + dFlux_dP[1][1] = grad_phi_P[3]; + dFlux_dS[0][0] = grad_phi_S[0]; + dFlux_dS[0][1] = grad_phi_S[1]; + dFlux_dS[1][0] = grad_phi_S[2]; + dFlux_dS[1][1] = grad_phi_S[3]; // Global residual and jacobian update: for( integer ip = 0; ip < m_numPhases; ++ip ) @@ -2701,16 +2729,16 @@ class FluxComputeKernelFactory string const & solverName, ElementRegionManager const & elemManager, STENCILWRAPPER const & stencilWrapper, - // CAPPRESWRAPPER const & capPresWrapper, - // RELPERMWRAPPER const & relPermWrapper, + // CAPPRESWRAPPER const & capPresWrapper, + // RELPERMWRAPPER const & relPermWrapper, string_array const & interfaceFaceSetNames, stdVector< std::array< std::tuple< constitutive::RelativePermeabilityBase *, constitutive::CapillaryPressureBase *, constitutive::TwoPhaseImmiscibleFluid * >, 2 > > const & interfaceConstitutivePairs, unordered_map< localIndex, localIndex > const & interfaceRegionByConnector, - // std::tuple< constitutive::RelativePermeabilityBase *, - // constitutive::CapillaryPressureBase *, - // constitutive::TwoPhaseImmiscibleFluid * > const & interfaceConstitutivePairs_temp, + // std::tuple< constitutive::RelativePermeabilityBase *, + // constitutive::CapillaryPressureBase *, + // constitutive::TwoPhaseImmiscibleFluid * > const & interfaceConstitutivePairs_temp, ElementSubRegionBase const & subRegion, real64 const & dt, CRSMatrixView< real64, globalIndex const > const & localMatrix, @@ -2724,7 +2752,7 @@ class FluxComputeKernelFactory dofNumberAccessor.setName( solverName + "/accessors/" + dofKey ); // using kernelType = FluxComputeInterfaceConditionKernel< NUM_EQN, NUM_DOF, STENCILWRAPPER, CAPPRESWRAPPER, RELPERMWRAPPER >; - using kernelType = FluxComputeInterfaceConditionKernel< NUM_EQN, NUM_DOF, STENCILWRAPPER >; + using kernelType = FluxComputeInterfaceConditionKernel< NUM_EQN, NUM_DOF, STENCILWRAPPER >; typename kernelType::ImmiscibleMultiphaseFlowAccessors flowAccessors( elemManager, solverName ); typename kernelType::MultiphaseFluidAccessors fluidAccessors( elemManager, solverName ); typename kernelType::CapPressureAccessors capPressureAccessors( elemManager, solverName ); @@ -2733,7 +2761,8 @@ class FluxComputeKernelFactory // kernelType kernel( numPhases, rankOffset, stencilWrapper, capPresWrapper, relPermWrapper, dofNumberAccessor, // flowAccessors, fluidAccessors, capPressureAccessors, permAccessors, // dt, localMatrix, localRhs, hasCapPressure, useTotalMassEquation, - // checkPhasePresenceInGravity, interfaceFaceSetNames, interfaceConstitutivePairs, interfaceRegionByConnector, interfaceConstitutivePairs_temp, domainSize ); + // checkPhasePresenceInGravity, interfaceFaceSetNames, interfaceConstitutivePairs, interfaceRegionByConnector, + // interfaceConstitutivePairs_temp, domainSize ); kernelType kernel( numPhases, rankOffset, stencilWrapper, dofNumberAccessor, flowAccessors, fluidAccessors, capPressureAccessors, permAccessors, dt, localMatrix, localRhs, hasCapPressure, useTotalMassEquation, From 3ec780e381dc9428d9a377c04738987a85d622d6 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Wed, 4 Feb 2026 22:48:57 -0800 Subject: [PATCH 097/104] Update testImmiscibleInterfaceConditions.cpp --- .../testImmiscibleInterfaceConditions.cpp | 224 +++++++++--------- 1 file changed, 112 insertions(+), 112 deletions(-) diff --git a/src/coreComponents/integrationTests/fluidFlowTests/testImmiscibleInterfaceConditions.cpp b/src/coreComponents/integrationTests/fluidFlowTests/testImmiscibleInterfaceConditions.cpp index be96c05aa4d..e3fd4cdb38e 100644 --- a/src/coreComponents/integrationTests/fluidFlowTests/testImmiscibleInterfaceConditions.cpp +++ b/src/coreComponents/integrationTests/fluidFlowTests/testImmiscibleInterfaceConditions.cpp @@ -47,7 +47,7 @@ CommandLineOptions g_commandLineOptions; TwoPhaseImmiscibleFluid * makeTwoPhaseImmiscibleFluid( TwoPhaseImmiscibleFluid & fluid ) { - + FunctionManager & functionManager = FunctionManager::getInstance(); // 1D table with linear interpolation @@ -56,44 +56,44 @@ TwoPhaseImmiscibleFluid * makeTwoPhaseImmiscibleFluid( TwoPhaseImmiscibleFluid & real64_array densityCoordPhase0; // fill( densityCoordPhase0, Feed< Naxis >{ 0.22, 0.3, 0.5, 0.6, 0.8, 1.0 } ); - for (auto v : {0.0}) - densityCoordPhase0.emplace_back(v); + for( auto v : {0.0} ) + densityCoordPhase0.emplace_back( v ); real64_array densityValuesPhase0; // fill( densityValuesPhase0, Feed< Naxis >{ 0.00603, 0.04224, 0.04224, 0.22423, 0.31311, 0.40203 } ); - for (auto v : {1000.0}) - densityValuesPhase0.emplace_back(v); + for( auto v : {1000.0} ) + densityValuesPhase0.emplace_back( v ); real64_array densityCoordPhase1; // fill( densityCoordPhase1, Feed< Naxis >{ 1.22, 1.3, 1.5, 1.6, 1.8, 2.0 } ); - for (auto v : {0.0}) - densityCoordPhase1.emplace_back(v); + for( auto v : {0.0} ) + densityCoordPhase1.emplace_back( v ); real64_array densityValuesPhase1; // fill( densityValuesPhase1, Feed< Naxis >{ 0.00603, 0.04224, 0.04224, 0.22423, 0.31311, 0.40203 } ); - for (auto v : {100.0}) - densityValuesPhase1.emplace_back(v); + for( auto v : {100.0} ) + densityValuesPhase1.emplace_back( v ); real64_array viscosityCoordPhase0; // fill( viscosityCoordPhase0, Feed< Naxis >{ 0.22, 0.3, 0.5, 0.6, 0.8, 1.0 } ); - for (auto v : {0.0}) - viscosityCoordPhase0.emplace_back(v); + for( auto v : {0.0} ) + viscosityCoordPhase0.emplace_back( v ); real64_array viscosityValuesPhase0; // fill( viscosityValuesPhase0, Feed< Naxis >{ 40203, 31311, 22423, 15011, 4224, 603 } ); - for (auto v : {0.001}) - viscosityValuesPhase0.emplace_back(v); + for( auto v : {0.001} ) + viscosityValuesPhase0.emplace_back( v ); real64_array viscosityCoordPhase1; // fill( viscosityCoordPhase1, Feed< NaxisSingle >{ 0.22 } ); - for (auto v : {0.0}) - viscosityCoordPhase1.emplace_back(v); + for( auto v : {0.0} ) + viscosityCoordPhase1.emplace_back( v ); real64_array viscosityValuesPhase1; // fill( viscosityValuesPhase1, Feed< NaxisSingle >{ 45 } ); - for (auto v : {0.001}) - viscosityValuesPhase1.emplace_back(v); + for( auto v : {0.001} ) + viscosityValuesPhase1.emplace_back( v ); TableFunction & table_density0 = dynamicCast< TableFunction & >( *functionManager.createChild( "TableFunction", "densityTablePhase0" ) ); - array1d coords_density0; - coords_density0.emplace_back(densityCoordPhase0); + array1d< real64_array > coords_density0; + coords_density0.emplace_back( densityCoordPhase0 ); table_density0.setTableCoordinates( coords_density0, { units::Dimensionless } ); table_density0.setTableValues( densityValuesPhase0, units::Dimensionless ); table_density0.reInitializeFunction(); @@ -101,8 +101,8 @@ TwoPhaseImmiscibleFluid * makeTwoPhaseImmiscibleFluid( TwoPhaseImmiscibleFluid & table_density0.setInterpolationMethod( TableFunction::InterpolationType::Linear ); TableFunction & table_density1 = dynamicCast< TableFunction & >( *functionManager.createChild( "TableFunction", "densityTablePhase1" ) ); - array1d coords_density1; - coords_density1.emplace_back(densityCoordPhase1); + array1d< real64_array > coords_density1; + coords_density1.emplace_back( densityCoordPhase1 ); table_density1.setTableCoordinates( coords_density1, { units::Dimensionless } ); table_density1.setTableValues( densityValuesPhase1, units::Dimensionless ); table_density1.reInitializeFunction(); @@ -110,8 +110,8 @@ TwoPhaseImmiscibleFluid * makeTwoPhaseImmiscibleFluid( TwoPhaseImmiscibleFluid & table_density1.setInterpolationMethod( TableFunction::InterpolationType::Linear ); TableFunction & table_viscosity0 = dynamicCast< TableFunction & >( *functionManager.createChild( "TableFunction", "viscosityTablePhase0" ) ); - array1d coords_viscosity0; - coords_viscosity0.emplace_back(viscosityCoordPhase0); + array1d< real64_array > coords_viscosity0; + coords_viscosity0.emplace_back( viscosityCoordPhase0 ); table_viscosity0.setTableCoordinates( coords_viscosity0, { units::Dimensionless } ); table_viscosity0.setTableValues( viscosityValuesPhase0, units::Dimensionless ); table_viscosity0.reInitializeFunction(); @@ -119,8 +119,8 @@ TwoPhaseImmiscibleFluid * makeTwoPhaseImmiscibleFluid( TwoPhaseImmiscibleFluid & table_viscosity0.setInterpolationMethod( TableFunction::InterpolationType::Linear ); TableFunction & table_viscosity1 = dynamicCast< TableFunction & >( *functionManager.createChild( "TableFunction", "viscosityTablePhase1" ) ); - array1d coords_viscosity1; - coords_viscosity1.emplace_back(viscosityCoordPhase1); + array1d< real64_array > coords_viscosity1; + coords_viscosity1.emplace_back( viscosityCoordPhase1 ); table_viscosity1.setTableCoordinates( coords_viscosity1, { units::Dimensionless } ); table_viscosity1.setTableValues( viscosityValuesPhase1, units::Dimensionless ); table_viscosity1.reInitializeFunction(); @@ -482,7 +482,7 @@ class ImmiscibleInterfaceConditionsTest : public FluidModelTest< TwoPhaseImmisci { public: ImmiscibleInterfaceConditionsTest(): state( std::make_unique< CommandLineOptions >( g_commandLineOptions )), - m_parent( "TestParentGroup", m_node ) + m_parent( "TestParentGroup", m_node ) {} @@ -510,9 +510,9 @@ TEST_F( ImmiscibleInterfaceConditionsTest, LocalNonlinearSolverConvergence ) // using Base = FluidModelTest< TwoPhaseImmiscibleFluid, 2 >; createFluid( "fluid", [this]( TwoPhaseImmiscibleFluid & fluid ){ makeTwoPhaseImmiscibleFluid( fluid ); - - // getting constitutive models: - RelativePermeabilityBase & relPerm = makeBrooksCoreyRelPerm( "relPerm" , this->m_parent); + + // getting constitutive models: + RelativePermeabilityBase & relPerm = makeBrooksCoreyRelPerm( "relPerm", this->m_parent ); RelativePermeabilityBase * relPermPtr = &relPerm; // CapillaryPressureBase & capPressure0 = makeJFunctionCapPressureTwoPhase( "capPressure0", this->m_parent ); // CapillaryPressureBase * capPressurePtr0 = &capPressure0; @@ -527,64 +527,64 @@ TEST_F( ImmiscibleInterfaceConditionsTest, LocalNonlinearSolverConvergence ) // CapillaryPressureBase & capPressure1 = makeBrooksCoreyCapPressureTwoPhase2( "capPressure1", this->m_parent ); // CapillaryPressureBase * capPressurePtr1 = &capPressure1; - - std::vector< RelativePermeabilityBase * > relPerms = {relPermPtr, relPermPtr}; - std::vector< CapillaryPressureBase * > capPressures = {capPressurePtr0, capPressurePtr1}; - std::vector< TwoPhaseImmiscibleFluid * > fluids = { &fluid, &fluid }; + + std::vector< RelativePermeabilityBase * > relPerms = {relPermPtr, relPermPtr}; + std::vector< CapillaryPressureBase * > capPressures = {capPressurePtr0, capPressurePtr1}; + std::vector< TwoPhaseImmiscibleFluid * > fluids = { &fluid, &fluid }; // real64 uT = 3.2864545889999906e-05; - - // real64 uT = -3.3e-5; - real64 uT = 1e-17; + + // real64 uT = -3.3e-5; + real64 uT = 1e-17; // real64 uT = 1e-7; - stdVector< real64 > saturations = {0.2, 0.4}; - stdVector< real64 > trappedSats1 = {phase0MinSat1, phase1MinSat1}; - stdVector< real64 > trappedSats2 = {phase0MinSat2, phase1MinSat2}; - stdVector< real64 > pressures = {1e7, 1e7}; - stdVector< real64 > JFMultipliers = {45016.662822296035, 30011.108548197357}; - stdVector< real64 > transHats = {1.9738466000000002e-12, 4.4411548500000007e-12}; - stdVector< real64 > dTransHats_dP = {0.0, 0.0}; - stdVector< real64 > gravCoefHats = {490.5, 490.5}; - stdVector< real64 > gravCoefs = {465.97500000000002, 515.02499999999998}; - - - std::vector< real64 > phi = {0.0, 0.0}; - std::vector< real64 > grad_phi = {0.0, 0.0, 0.0, 0.0}; - - std::ofstream outFile( "local_solver_results.csv" ); - - - // Write data to the file - outFile << "Si"; - outFile << ","; - outFile << "Sj"; - outFile << ","; - outFile << "Fw_alpha"; - outFile << ","; - outFile << "Fn_alpha"; - outFile << ","; - outFile << "Residual_initial"; - outFile << ","; - outFile << "Pc_int"; - outFile << ","; - outFile << "Residual"; - outFile << ","; - outFile << "newton"; - outFile << std::endl; - - real64 const start_sat = 0.0; - real64 const end_sat = 1.0; - real64 const dS = 1e-2; - real64 Si = 0.0; - real64 Sj = 0.9; - - // for( real64 Si = start_sat; Si <= end_sat + 1e-8; Si += dS ) - // { - // for( real64 Sj = start_sat; Sj <= end_sat + 1e-8; Sj += dS ) - // { - saturations[0] = Si; - saturations[1] = Sj; - - auto t0 = std::chrono::high_resolution_clock::now(); + stdVector< real64 > saturations = {0.2, 0.4}; + stdVector< real64 > trappedSats1 = {phase0MinSat1, phase1MinSat1}; + stdVector< real64 > trappedSats2 = {phase0MinSat2, phase1MinSat2}; + stdVector< real64 > pressures = {1e7, 1e7}; + stdVector< real64 > JFMultipliers = {45016.662822296035, 30011.108548197357}; + stdVector< real64 > transHats = {1.9738466000000002e-12, 4.4411548500000007e-12}; + stdVector< real64 > dTransHats_dP = {0.0, 0.0}; + stdVector< real64 > gravCoefHats = {490.5, 490.5}; + stdVector< real64 > gravCoefs = {465.97500000000002, 515.02499999999998}; + + + std::vector< real64 > phi = {0.0, 0.0}; + std::vector< real64 > grad_phi = {0.0, 0.0, 0.0, 0.0}; + + std::ofstream outFile( "local_solver_results.csv" ); + + + // Write data to the file + outFile << "Si"; + outFile << ","; + outFile << "Sj"; + outFile << ","; + outFile << "Fw_alpha"; + outFile << ","; + outFile << "Fn_alpha"; + outFile << ","; + outFile << "Residual_initial"; + outFile << ","; + outFile << "Pc_int"; + outFile << ","; + outFile << "Residual"; + outFile << ","; + outFile << "newton"; + outFile << std::endl; + + real64 const start_sat = 0.0; + real64 const end_sat = 1.0; + real64 const dS = 1e-2; + real64 Si = 0.0; + real64 Sj = 0.9; + + // for( real64 Si = start_sat; Si <= end_sat + 1e-8; Si += dS ) + // { + // for( real64 Sj = start_sat; Sj <= end_sat + 1e-8; Sj += dS ) + // { + saturations[0] = Si; + saturations[1] = Sj; + + auto t0 = std::chrono::high_resolution_clock::now(); // Define missing arguments for the updated signature stdVector< real64 > cellCenterDuT = { 0.0, 0.0 }; @@ -594,39 +594,39 @@ TEST_F( ImmiscibleInterfaceConditionsTest, LocalNonlinearSolverConvergence ) std::vector< real64 > grad_phi_S = { 0.0, 0.0 }; bool converged; -// Call the GEOS local solver + // Call the GEOS local solver geos::immiscibleMultiphaseKernels::local_solver( uT, saturations, pressures, JFMultipliers, trappedSats1, trappedSats2, transHats, dTransHats_dP, gravCoefHats, gravCoefs, - cellCenterDuT, cellCenterDens, cellCenterDens_dP, - relPerms, capPressures, fluids, phi, grad_phi_P, grad_phi_S, converged ); - -auto t1 = std::chrono::high_resolution_clock::now(); -std::chrono::duration elapsed = t1 - t0; -std::cout << "Local solver time: " << elapsed.count() << " s" << std::endl; - - - // Write data to the file - outFile << GEOS_FMT( "{:10.10e}", saturations[0] ); - outFile << GEOS_FMT( ",{:10.10e}", saturations[1] ); - outFile << GEOS_FMT( ",{:10.10e}", phi[0] ); - outFile << GEOS_FMT( ",{:10.10e}", phi[1] ); - outFile << GEOS_FMT( ",{:10.10e}", grad_phi_P[0] ); - outFile << GEOS_FMT( ",{:10.10e}", grad_phi_P[1] ); - outFile << GEOS_FMT( ",{:10.10e}", grad_phi_S[0] ); - outFile << GEOS_FMT( ",{:10.10e}", grad_phi_S[1] ); - outFile << std::endl; - phi[0] = 0; - phi[1] = 0; - grad_phi_P[0] = 0; - grad_phi_P[1] = 0; - grad_phi_S[0] = 0; - grad_phi_S[1] = 0; + cellCenterDuT, cellCenterDens, cellCenterDens_dP, + relPerms, capPressures, fluids, phi, grad_phi_P, grad_phi_S, converged ); + + auto t1 = std::chrono::high_resolution_clock::now(); + std::chrono::duration< double > elapsed = t1 - t0; + std::cout << "Local solver time: " << elapsed.count() << " s" << std::endl; + + + // Write data to the file + outFile << GEOS_FMT( "{:10.10e}", saturations[0] ); + outFile << GEOS_FMT( ",{:10.10e}", saturations[1] ); + outFile << GEOS_FMT( ",{:10.10e}", phi[0] ); + outFile << GEOS_FMT( ",{:10.10e}", phi[1] ); + outFile << GEOS_FMT( ",{:10.10e}", grad_phi_P[0] ); + outFile << GEOS_FMT( ",{:10.10e}", grad_phi_P[1] ); + outFile << GEOS_FMT( ",{:10.10e}", grad_phi_S[0] ); + outFile << GEOS_FMT( ",{:10.10e}", grad_phi_S[1] ); + outFile << std::endl; + phi[0] = 0; + phi[1] = 0; + grad_phi_P[0] = 0; + grad_phi_P[1] = 0; + grad_phi_S[0] = 0; + grad_phi_S[1] = 0; // } // } - outFile.close(); + outFile.close(); -} ); + } ); } int main( int argc, char * *argv ) From 0c2b288791d98e7e81f3c9bfa8874d728483beb8 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Wed, 4 Feb 2026 23:11:01 -0800 Subject: [PATCH 098/104] Update uni_directional_flow_base.xml --- .../3D_case/uni_directional_flow_base.xml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/uni_directional_flow_base.xml b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/uni_directional_flow_base.xml index eeeefa8277d..79938ce570f 100644 --- a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/uni_directional_flow_base.xml +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/uni_directional_flow_base.xml @@ -10,17 +10,18 @@ discretization="TPFA" temperature="300" initialDt="0.001" - targetRegions="{ region_left, region_right }" - interfaceFaceSetNames = "{ Interface }"> + targetRegions="{ region_left, region_right }"> + - + + From 11bfa6049aa8ac2a344fe5b9e0db7dc6fda1a797 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Wed, 4 Feb 2026 23:34:22 -0800 Subject: [PATCH 099/104] wip --- .../3D_case/uni_directional_flow_base.xml | 13 +++++++++---- .../uni_directional_flow_interface_condition.xml | 6 +++--- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/uni_directional_flow_base.xml b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/uni_directional_flow_base.xml index 79938ce570f..a07cd1eb482 100644 --- a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/uni_directional_flow_base.xml +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/uni_directional_flow_base.xml @@ -13,15 +13,20 @@ targetRegions="{ region_left, region_right }"> + maxTimeStepCuts="50" + maxSubSteps="100" + lineSearchAction="None" + timeStepDecreaseFactor="0.9" + timeStepIncreaseFactor="1.5" + timeStepDecreaseIterLimit="0.8" + timeStepIncreaseIterLimit="0.6"/> - + diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/uni_directional_flow_interface_condition.xml b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/uni_directional_flow_interface_condition.xml index faea9a0d2e4..3c85d4906ed 100644 --- a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/uni_directional_flow_interface_condition.xml +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/uni_directional_flow_interface_condition.xml @@ -13,9 +13,9 @@ xCoords="{ 0, 10 }" yCoords="{ 0, 6 }" zCoords="{ 0, 5, 10 }" - nx="{ 10 }" - ny="{ 6 }" - nz="{ 10, 10 }" + nx="{ 20 }" + ny="{ 12 }" + nz="{ 20, 20 }" cellBlockNames="{ cb_left, cb_right }"/> From 3d8563943397dd7f8bb71d28fb427e8c3d3bd6e8 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Wed, 4 Feb 2026 23:54:48 -0800 Subject: [PATCH 100/104] wip: --- .../3D_case/uni_directional_flow_base.xml | 6 +++--- .../3D_case/uni_directional_flow_interface_condition.xml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/uni_directional_flow_base.xml b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/uni_directional_flow_base.xml index a07cd1eb482..17de13549e4 100644 --- a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/uni_directional_flow_base.xml +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/uni_directional_flow_base.xml @@ -6,12 +6,12 @@ gravityVector="{ 0.0, 0.0, 9.81 }"> - + targetRegions="{ region_left, region_right }" + interfaceFaceSetNames = "{ Interface }"> From cbbf98cab9c1378366cc22f50e91944a858d0758 Mon Sep 17 00:00:00 2001 From: Omar Duran Date: Wed, 4 Feb 2026 23:56:21 -0800 Subject: [PATCH 101/104] Update uni_directional_flow_base.xml --- .../3D_case/uni_directional_flow_base.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/uni_directional_flow_base.xml b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/uni_directional_flow_base.xml index 17de13549e4..3982a2b12c6 100644 --- a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/uni_directional_flow_base.xml +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/uni_directional_flow_base.xml @@ -10,8 +10,8 @@ discretization="TPFA" temperature="300" initialDt="0.001" - targetRegions="{ region_left, region_right }" - interfaceFaceSetNames = "{ Interface }"> + targetRegions="{ region_left, region_right }"> + Date: Thu, 5 Feb 2026 00:03:10 -0800 Subject: [PATCH 102/104] Update uni_directional_flow_interface_condition.xml --- .../3D_case/uni_directional_flow_interface_condition.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/uni_directional_flow_interface_condition.xml b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/uni_directional_flow_interface_condition.xml index bac81aa6c20..9bac844ae7b 100644 --- a/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/uni_directional_flow_interface_condition.xml +++ b/inputFiles/immiscibleMultiphaseFlow/immiscibleTwoPhase_interface_conditions/3D_case/uni_directional_flow_interface_condition.xml @@ -14,7 +14,7 @@ yCoords="{ 0, 6 }" zCoords="{ 0, 5, 10 }" nx="{ 40 }" - ny="{ 24 }" + ny="{ 1 }" nz="{ 40, 40 }" cellBlockNames="{ cb_left, cb_right }"/> From c0e2cc793eda291f0b2b79da72f49441d36364d4 Mon Sep 17 00:00:00 2001 From: Ammara-14 Date: Mon, 9 Feb 2026 10:01:33 -0800 Subject: [PATCH 103/104] Adding hysteresis and updating the unitTest --- src/coreComponents/common/logger/Logger.hpp | 1 + .../constitutive/CMakeLists.txt | 4 + .../constitutive/KilloughHysteresis.cpp | 144 ++ .../constitutive/KilloughHysteresis.hpp | 179 ++ .../BrooksCoreyCapillaryPressure.cpp | 1 + .../BrooksCoreyCapillaryPressure.hpp | 2 + .../CapillaryPressureBase.cpp | 17 +- .../CapillaryPressureBase.hpp | 56 + .../CapillaryPressureFields.hpp | 115 +- .../CapillaryPressureSelector.hpp | 23 +- .../InverseCapillaryPressure.cpp | 2 + .../JFunctionCapillaryPressure.cpp | 3 + .../JFunctionCapillaryPressure.hpp | 1 + .../TableCapillaryPressure.cpp | 3 + .../TableCapillaryPressure.hpp | 4 + .../TableCapillaryPressureHelpers.cpp | 38 +- .../TableCapillaryPressureHelpers.hpp | 4 +- .../TableCapillaryPressureHysteresis.cpp | 2267 +++++++++++++++++ .../TableCapillaryPressureHysteresis.hpp | 597 +++++ .../VanGenuchtenCapillaryPressure.cpp | 1 + .../VanGenuchtenCapillaryPressure.hpp | 2 + .../BrooksCoreyBakerRelativePermeability.hpp | 6 +- .../BrooksCoreyRelativePermeability.hpp | 5 +- .../BrooksCoreyStone2RelativePermeability.hpp | 2 +- .../KilloughHysteresis.hpp | 14 +- .../RelativePermeabilityBase.cpp | 1 + .../RelativePermeabilityBase.hpp | 41 +- .../TableRelativePermeability.hpp | 6 +- .../TableRelativePermeabilityHelpers.cpp | 2 +- .../TableRelativePermeabilityHysteresis.cpp | 217 +- .../TableRelativePermeabilityHysteresis.hpp | 93 +- .../VanGenuchtenBakerRelativePermeability.hpp | 6 +- ...VanGenuchtenStone2RelativePermeability.hpp | 2 +- .../unitTests/constitutiveTestHelpers.hpp | 4 +- .../relativePermeability/RelpermDriver.cpp | 6 +- .../RelpermDriverRunTest.hpp | 16 +- .../finiteVolume/SurfaceElementStencil.hpp | 4 +- .../constitutiveTests/CMakeLists.txt | 12 +- .../testRelPermHysteresis.cpp | 33 +- .../fluidFlowTests/CMakeLists.txt | 1 + .../testImmiscibleInterfaceConditions.cpp | 145 +- .../fluidFlow/CompositionalMultiphaseBase.cpp | 19 +- .../fluidFlow/CompositionalMultiphaseBase.hpp | 5 + .../fluidFlow/ImmiscibleMultiphaseFlow.cpp | 265 +- .../ImmiscibleMultiphaseKernels.hpp | 521 +++- src/coreComponents/schema/schema.xsd.other | 8 + src/docs/doxygen/GeosxConfig.hpp | 2 +- 47 files changed, 4431 insertions(+), 469 deletions(-) create mode 100644 src/coreComponents/constitutive/KilloughHysteresis.cpp create mode 100644 src/coreComponents/constitutive/KilloughHysteresis.hpp create mode 100644 src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressureHysteresis.cpp create mode 100644 src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressureHysteresis.hpp diff --git a/src/coreComponents/common/logger/Logger.hpp b/src/coreComponents/common/logger/Logger.hpp index e59cfa05256..1224ec6ee66 100644 --- a/src/coreComponents/common/logger/Logger.hpp +++ b/src/coreComponents/common/logger/Logger.hpp @@ -978,6 +978,7 @@ struct InputError : public std::runtime_error InputError( std::exception const & subException, std::string const & msgToInsert ); }; + /** * @brief Exception class used to report errors in user input. */ diff --git a/src/coreComponents/constitutive/CMakeLists.txt b/src/coreComponents/constitutive/CMakeLists.txt index f4d46708e56..bfb182dfe89 100644 --- a/src/coreComponents/constitutive/CMakeLists.txt +++ b/src/coreComponents/constitutive/CMakeLists.txt @@ -27,12 +27,14 @@ set( constitutive_headers ConstitutivePassThruHandler.hpp ExponentialRelation.hpp NullModel.hpp + KilloughHysteresis.hpp capillaryPressure/BrooksCoreyCapillaryPressure.hpp capillaryPressure/CapillaryPressureBase.hpp capillaryPressure/CapillaryPressureFields.hpp capillaryPressure/InverseCapillaryPressure.hpp capillaryPressure/JFunctionCapillaryPressure.hpp capillaryPressure/TableCapillaryPressure.hpp + capillaryPressure/TableCapillaryPressureHysteresis.hpp capillaryPressure/TableCapillaryPressureHelpers.hpp capillaryPressure/VanGenuchtenCapillaryPressure.hpp capillaryPressure/CapillaryPressureSelector.hpp @@ -226,11 +228,13 @@ set( constitutive_sources ConstitutiveBase.cpp ConstitutiveManager.cpp NullModel.cpp + KilloughHysteresis.cpp capillaryPressure/BrooksCoreyCapillaryPressure.cpp capillaryPressure/CapillaryPressureBase.cpp capillaryPressure/InverseCapillaryPressure.cpp capillaryPressure/JFunctionCapillaryPressure.cpp capillaryPressure/TableCapillaryPressure.cpp + capillaryPressure/TableCapillaryPressureHysteresis.cpp capillaryPressure/TableCapillaryPressureHelpers.cpp capillaryPressure/VanGenuchtenCapillaryPressure.cpp contact/BartonBandis.cpp diff --git a/src/coreComponents/constitutive/KilloughHysteresis.cpp b/src/coreComponents/constitutive/KilloughHysteresis.cpp new file mode 100644 index 00000000000..453a8b0585b --- /dev/null +++ b/src/coreComponents/constitutive/KilloughHysteresis.cpp @@ -0,0 +1,144 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2018-2020 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2020 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2018-2020 TotalEnergies + * Copyright (c) 2019- GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/*** + * @file KilloughHysteresis.cpp + */ + +#include "KilloughHysteresis.hpp" + + +namespace geos +{ + +using namespace dataRepository; + +namespace constitutive +{ + + +void KilloughHysteresis::postProcessInput(real64 const &jerauldParam_a, real64 const &jerauldParam_b, + real64 const &killoughCurvatureParamRelPerm, + real64 const &killoughCurvatureParamPc) +{ + GEOS_THROW_IF( jerauldParam_a < 0, + GEOS_FMT( "{}: the parameter {} must be positive", + catalogName(), + viewKeyStruct::jerauldParameterAString() ), + InputError ); + + GEOS_THROW_IF( jerauldParam_b < 0, + GEOS_FMT( "{}: the paramater {} must be postitive", + catalogName(), + viewKeyStruct::jerauldParameterBString() ), + InputError ); + + GEOS_THROW_IF( killoughCurvatureParamRelPerm < 0, + GEOS_FMT( "{}: the paramater {} must be postitive", + catalogName(), + viewKeyStruct::killoughCurvatureParameterRelPermString() ), + InputError ); + + GEOS_THROW_IF( killoughCurvatureParamPc < 0, + GEOS_FMT( "{}: the paramater {} must be postitive", + catalogName(), + viewKeyStruct::killoughCurvatureParameterPcString() ), + InputError ); + +} + + + +//TODO +void KilloughHysteresis::computeLandCoefficient( KilloughHysteresis::HysteresisCurve const & hcurve, + real64 & landParam ) +{ + + // Note: for simplicity, the notations are taken from IX documentation (although this breaks our phaseVolFrac naming convention) + + // Step 1: Land parameter for the wetting phase + if( hcurve.isWetting() ) + { + real64 const Scrd = hcurve.oppositeBoundPhaseVolFraction; + real64 const Smxd = hcurve.drainageExtremaPhaseVolFraction; + real64 const Smxi = hcurve.imbibitionExtremaPhaseVolFraction; + real64 const Swc = Scrd; + GEOS_THROW_IF( (Smxi - Smxd) > 0, + GEOS_FMT( "{}: For wetting phase hysteresis, imbibition end-point saturation Smxi( {} ) must be smaller than the drainage saturation end-point Smxd( {} ).\n" + "Crossing relative permeability curves.\n", + catalogName(), + Smxi, + Smxd ), + InputError ); + + landParam = ( Smxd - Swc ) / LvArray::math::max( KilloughHysteresis::minScriMinusScrd, ( Smxd - Smxi ) ) - 1.0; + } + else + // Step 2: Land parameter for the non-wetting phase + + { + real64 const Smx = hcurve.oppositeBoundPhaseVolFraction; + real64 const Scrd = hcurve.drainageExtremaPhaseVolFraction; + real64 const Scri = hcurve.imbibitionExtremaPhaseVolFraction; + GEOS_THROW_IF( (Scrd - Scri) > 0, + GEOS_FMT( "{}: For non-wetting phase hysteresis, drainage trapped saturation Scrd( {} ) must be smaller than the imbibition saturation Scri( {} ).\n" + "Crossing relative permeability curves.\n", + catalogName(), + Scrd, + Scri ), + InputError ); + + landParam = ( Smx - Scrd ) / LvArray::math::max( KilloughHysteresis::minScriMinusScrd, ( Scri - Scrd ) ) - 1.0; + } +} + +GEOS_HOST_DEVICE +void +KilloughHysteresis:: + computeTrappedCriticalPhaseVolFraction( HysteresisCurve const & hcurve, + real64 const & Shy, + real64 const & landParam, + real64 const & jerauldParam_a, + real64 const & jerauldParam_b, + real64 & Scrt ) +{ + + if( hcurve.isWetting()) + { + //unpack values + real64 const Smxd = hcurve.drainageExtremaPhaseVolFraction; + real64 const Swc = hcurve.oppositeBoundPhaseVolFraction; + + real64 const A = 1 + jerauldParam_a * (Shy - Swc); + real64 const numerator = Shy - Smxd; + real64 const denom = A + landParam * pow((Smxd - Shy) / (Smxd - Swc), 1 + jerauldParam_b / landParam ); + Scrt = Smxd + numerator / denom; + } + else + { + //unpack values + real64 const Scrd = hcurve.drainageExtremaPhaseVolFraction; + real64 const Smx = hcurve.oppositeBoundPhaseVolFraction; + + real64 const A = 1 + jerauldParam_a * (Smx - Shy); + real64 const numerator = Shy - Scrd; + real64 const denom = A + landParam * pow((Shy - Scrd) / (Smx - Scrd), 1 + jerauldParam_b / landParam ); + Scrt = LvArray::math::max( 0.0, + Scrd + numerator / denom ); // trapped critical saturation from equation 2.162 + } + +} + +}//end namespace +}//end namespace diff --git a/src/coreComponents/constitutive/KilloughHysteresis.hpp b/src/coreComponents/constitutive/KilloughHysteresis.hpp new file mode 100644 index 00000000000..ce151f3aeae --- /dev/null +++ b/src/coreComponents/constitutive/KilloughHysteresis.hpp @@ -0,0 +1,179 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2018-2020 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2020 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2018-2020 TotalEnergies + * Copyright (c) 2019- GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/** + * @file TableRelativePermeabilityHysteresis.hpp + */ + +#ifndef GEOS_KILLOUGHHYSTERESIS_HPP +#define GEOS_KILLOUGHHYSTERESIS_HPP + +#include "constitutive/ConstitutiveBase.hpp" +#include "functions/TableFunction.hpp" + +#include "relativePermeability/Layouts.hpp" +#include "capillaryPressure/Layouts.hpp" + +namespace geos +{ + +using namespace dataRepository; + +namespace constitutive +{ + +/*** + * @brief KilloughHysteresis is designed to hold Killough hystereis model parameters and + * be in charge of all compuration related to this model (trapped Saturation,Land Coefficient?) + */ + + + +//should be up to constitutiveBase or some new SCALConstitutiveBase but for now let's POC on relativePermeabilityBase +class KilloughHysteresis +{ +public: + + static constexpr real64 minScriMinusScrd = 1e-12; + /// To avoid frequent changes from drainage to imbibition and vice versa, we use this buffer + static constexpr real64 flowReversalBuffer = 1e-12; + + struct PhaseWettability + { + enum : integer + { + WETTING = 0, + NONWETTING = 1 + }; + }; + + /** + * @brief struct to represent hysteresis curves (relperm or capillary pressure) + * whether they are wetting or non wetting, storing key point as pairs of + * saturations and value, being either the relperm value (S,kr) or capillary pressure value (S,pc). + * this way we can tell wetting curve from non wetting by the ordering of drainage/imbibition key values. + * Indeed if imbibition comes at lower saturation than drainage then it is wetting curve, on the opposite + * if drainage comes before imbibition this is a non-wetting hysteresis. This is completed by an opposite + * point that is either the connate wetting saturation Swc or the maximum non wetting saturation Sgmax. + * @param oppositeBoundPhaseVolFraction represents either Swc or Sgmax depending if a wetting curve or nonwetting is described + * @param imbibitionExtremaPhaseVolFraction represents in wetting case the imibibition max and in non-wetting the imbibition residual + * @param drainageExtremaPhaseVolFraction represents in wetting case the drainage max and in non-wetting the drainage residual + * @param oppositeBoundSCALValue represents the associate relperm or capillary pressure value + * @param imbibitionExtremaSCALValue represents the associate relperm or capillary pressure value + * @param drainageExtremaSCALValue represents the associate relperm or capillary pressure value + */ + + struct HysteresisCurve + { + real64 oppositeBoundPhaseVolFraction = -1.; + real64 imbibitionExtremaPhaseVolFraction = -1.; + real64 drainageExtremaPhaseVolFraction = -1.; + + real64 oppositeBoundSCALValue = -1.; + real64 imbibitionExtremaSCALValue = -1.; + real64 drainageExtremaSCALValue = -1.; + + HysteresisCurve() = default; + + HysteresisCurve( std::pair< real64, real64 > const & opp, std::pair< real64, real64 > const & imbE, std::pair< real64, real64 > const & drainE ) + { + setPoints( opp, imbE, drainE ); + } + + void setPoints( std::pair< real64, real64 > const & opp, std::pair< real64, real64 > const & imbE, std::pair< real64, real64 > const & drainE ) + { + oppositeBoundPhaseVolFraction = opp.first; + imbibitionExtremaPhaseVolFraction = imbE.first; + drainageExtremaPhaseVolFraction = drainE.first; + + oppositeBoundSCALValue = opp.second; + imbibitionExtremaSCALValue = imbE.second; + drainageExtremaSCALValue = drainE.second; + } + + //tODO (jacques) check if relevant to invert relation with same SCAL value // might be misleading for kr + HysteresisCurve toWetting() const + { + if(!isWetting()) + return HysteresisCurve({1.-oppositeBoundPhaseVolFraction,oppositeBoundSCALValue}, + {1.- imbibitionExtremaPhaseVolFraction,imbibitionExtremaSCALValue}, + {1.-drainageExtremaPhaseVolFraction,drainageExtremaSCALValue}); + else + return *this; + } + + HysteresisCurve toNonWetting() const + { + if(isWetting()) + return HysteresisCurve({1.-oppositeBoundPhaseVolFraction,oppositeBoundSCALValue}, + {1.-imbibitionExtremaPhaseVolFraction,imbibitionExtremaSCALValue}, + {1.-drainageExtremaPhaseVolFraction,drainageExtremaSCALValue}); + else + return *this; + } + + bool isWetting() const + { + return ((drainageExtremaPhaseVolFraction > oppositeBoundPhaseVolFraction) ? PhaseWettability::WETTING : PhaseWettability::NONWETTING) == PhaseWettability::WETTING; + } + bool isZero() const + { + return (oppositeBoundPhaseVolFraction <= 0.0) && (imbibitionExtremaPhaseVolFraction <= 0.0) && (drainageExtremaPhaseVolFraction <= 0.0); + } + + }; + +// void setRelPermParameters( real64 const & jerauldA, real64 const & jerauldB, real64 const & relpermCurv ); + + static std::string catalogName() { return "KilloughHysteresis"; } + + static void postProcessInput(real64 const &jerauldParam_a, real64 const &jerauldParam_b, + real64 const &killoughCurvatureParamRelPerm, + real64 const &killoughCurvatureParamPc); + + GEOS_HOST_DEVICE + static void computeLandCoefficient( HysteresisCurve const & hcruve, real64 & landParam ); + /** + * @brief Function computing the trapped critical phase volume fraction + * @param[in] hcurve the hysteresis curve to be used and dispatched on + * @param[in] Shy the max historical phase volume fraction + * @param[in] landParam Land trapping parameter + * @param[in] jerauldParam_a jerauld expononent + * @param[in] jerauldParam_b jerauld expononent + * @param[out] Scrt the trapped critical phase volume fraction + */ + GEOS_HOST_DEVICE + static void computeTrappedCriticalPhaseVolFraction( HysteresisCurve const & hcurve, + real64 const & Shy, + real64 const & landParam, + real64 const & jerauldParam_a, + real64 const & jerauldParam_b, + real64 & Scrt ); + + struct viewKeyStruct + { + static constexpr char const * jerauldParameterAString() { return "jerauldParameterA"; } + static constexpr char const * jerauldParameterBString() { return "jerauldParameterB"; } + + static constexpr char const * killoughCurvatureParameterRelPermString() { return "killoughCurvatureParameterRelPerm"; } + static constexpr char const * killoughCurvatureParameterPcString() { return "killoughCurvatureParameterPc"; } + }; + +}; + +} + +} + +#endif //GEOS_KILLOUGHHYSTERESIS_HPP diff --git a/src/coreComponents/constitutive/capillaryPressure/BrooksCoreyCapillaryPressure.cpp b/src/coreComponents/constitutive/capillaryPressure/BrooksCoreyCapillaryPressure.cpp index f068365eb35..d7cc96a1dd1 100644 --- a/src/coreComponents/constitutive/capillaryPressure/BrooksCoreyCapillaryPressure.cpp +++ b/src/coreComponents/constitutive/capillaryPressure/BrooksCoreyCapillaryPressure.cpp @@ -114,6 +114,7 @@ BrooksCoreyCapillaryPressure::createKernelWrapper() m_volFracScale, m_phaseTypes, m_phaseOrder, + m_phaseTrappedVolFrac, m_phaseCapPressure, m_dPhaseCapPressure_dPhaseVolFrac ); } diff --git a/src/coreComponents/constitutive/capillaryPressure/BrooksCoreyCapillaryPressure.hpp b/src/coreComponents/constitutive/capillaryPressure/BrooksCoreyCapillaryPressure.hpp index 0d71fcbc948..4de52bf8d52 100644 --- a/src/coreComponents/constitutive/capillaryPressure/BrooksCoreyCapillaryPressure.hpp +++ b/src/coreComponents/constitutive/capillaryPressure/BrooksCoreyCapillaryPressure.hpp @@ -39,10 +39,12 @@ class BrooksCoreyCapillaryPressureUpdate final : public CapillaryPressureBaseUpd real64 const volFracScale, arrayView1d< integer const > const & phaseTypes, arrayView1d< integer const > const & phaseOrder, + arrayView3d< real64, cappres::USD_CAPPRES > const & phaseTrapped, arrayView3d< real64, cappres::USD_CAPPRES > const & phaseCapPressure, arrayView4d< real64, cappres::USD_CAPPRES_DS > const & dPhaseCapPressure_dPhaseVolFrac ) : CapillaryPressureBaseUpdate( phaseTypes, phaseOrder, + phaseTrapped, phaseCapPressure, dPhaseCapPressure_dPhaseVolFrac ), m_phaseMinVolumeFraction( phaseMinVolumeFraction ), diff --git a/src/coreComponents/constitutive/capillaryPressure/CapillaryPressureBase.cpp b/src/coreComponents/constitutive/capillaryPressure/CapillaryPressureBase.cpp index 9f1db0231ed..aea0662a591 100644 --- a/src/coreComponents/constitutive/capillaryPressure/CapillaryPressureBase.cpp +++ b/src/coreComponents/constitutive/capillaryPressure/CapillaryPressureBase.cpp @@ -52,6 +52,7 @@ CapillaryPressureBase::CapillaryPressureBase( string const & name, registerField< fields::cappres::phaseCapPressure >( &m_phaseCapPressure ); registerField< fields::cappres::dPhaseCapPressure_dPhaseVolFraction >( &m_dPhaseCapPressure_dPhaseVolFrac ); + registerField< fields::cappres::phaseTrappedVolFraction >( &m_phaseTrappedVolFrac ); } void CapillaryPressureBase::postInputInitialization() @@ -93,19 +94,31 @@ void CapillaryPressureBase::postInputInitialization() void CapillaryPressureBase::allocateConstitutiveData( Group & parent, localIndex const numPts ) { integer const NP = numFluidPhases(); - + //phase trapped for stats + m_phaseTrappedVolFrac.resize( 0, numPts, NP ); + m_phaseTrappedVolFrac.zero(); m_phaseCapPressure.resize( 0, numPts, NP ); m_dPhaseCapPressure_dPhaseVolFrac.resize( 0, numPts, NP, NP ); - + ConstitutiveBase::allocateConstitutiveData( parent, numPts ); } void CapillaryPressureBase::setLabels() { + getField< fields::cappres::phaseTrappedVolFraction >(). + setDimLabels( 2, m_phaseNames ); getField< fields::cappres::phaseCapPressure >(). setDimLabels( 2, m_phaseNames ); } +void CapillaryPressureBase::resizeFields( localIndex const size, localIndex const numPts ) +{ + integer const NP = numFluidPhases(); + m_phaseTrappedVolFrac.resize( size, numPts, NP ); + m_phaseCapPressure.resize( size, numPts, NP ); + m_dPhaseCapPressure_dPhaseVolFrac.resize( size, numPts, NP, NP ); +} + } // namespace constitutive } // namespace geos diff --git a/src/coreComponents/constitutive/capillaryPressure/CapillaryPressureBase.hpp b/src/coreComponents/constitutive/capillaryPressure/CapillaryPressureBase.hpp index b0617841488..34a4701b957 100644 --- a/src/coreComponents/constitutive/capillaryPressure/CapillaryPressureBase.hpp +++ b/src/coreComponents/constitutive/capillaryPressure/CapillaryPressureBase.hpp @@ -60,16 +60,19 @@ class CapillaryPressureBaseUpdate CapillaryPressureBaseUpdate( arrayView1d< integer const > const & phaseTypes, arrayView1d< integer const > const & phaseOrder, + arrayView3d< real64, cappres::USD_CAPPRES > const & phaseTrapped, arrayView3d< real64, cappres::USD_CAPPRES > const & phaseCapPressure, arrayView4d< real64, cappres::USD_CAPPRES_DS > const & dPhaseCapPressure_dPhaseVolFrac ) : m_phaseTypes( phaseTypes ), m_phaseOrder( phaseOrder ), + m_phaseTrappedVolFrac( phaseTrapped ), m_phaseCapPressure( phaseCapPressure ), m_dPhaseCapPressure_dPhaseVolFrac( dPhaseCapPressure_dPhaseVolFrac ) {} arrayView1d< integer const > m_phaseTypes; arrayView1d< integer const > m_phaseOrder; + arrayView3d< real64, cappres::USD_CAPPRES > m_phaseTrappedVolFrac; arrayView3d< real64, cappres::USD_CAPPRES > m_phaseCapPressure; arrayView4d< real64, cappres::USD_CAPPRES_DS > m_dPhaseCapPressure_dPhaseVolFrac; @@ -130,6 +133,14 @@ class CapillaryPressureBase : public ConstitutiveBase arrayView3d< real64 const > const & convergedPermeability ) const { GEOS_UNUSED_VAR( convergedPorosity, convergedPermeability ); } + + /** + * @brief Save converged phase volume fraction at the end of a time step (needed for hysteresis) + * @param[in] phaseVolFraction an array containing the phase volume fractions at the end of a converged time step + */ + virtual void saveConvergedPhaseVolFractionState( arrayView2d< real64 const, compflow::USD_PHASE > const & phaseVolFraction ) const + { GEOS_UNUSED_VAR( phaseVolFraction ); } + /* * @brief Getter for the number of fluid phases * @return the number of fluid phases @@ -182,9 +193,17 @@ class CapillaryPressureBase : public ConstitutiveBase void setLabels(); protected: +/** + * @brief Function called internally to resize member arrays + * @param size primary dimension (e.g. number of cells) + * @param numPts secondary dimension (e.g. number of gauss points per cell) + */ + virtual void resizeFields( localIndex const size, localIndex const numPts ); virtual void postInputInitialization() override; + std::tuple phaseIndex(const arrayView1d &phaseOrder); + // phase names read from input string_array m_phaseNames; @@ -198,8 +217,45 @@ class CapillaryPressureBase : public ConstitutiveBase // output quantities array3d< real64, cappres::LAYOUT_CAPPRES > m_phaseCapPressure; array4d< real64, cappres::LAYOUT_CAPPRES_DS > m_dPhaseCapPressure_dPhaseVolFrac; + + // trapped fraction + array3d< real64, cappres::LAYOUT_CAPPRES > m_phaseTrappedVolFrac; }; + inline std::tuple< integer, integer > CapillaryPressureBase::phaseIndex( arrayView1d< integer const > const & phaseOrder ) + { + using PT = PhaseType; + integer const ipWater = phaseOrder[PT::WATER]; + integer const ipOil = phaseOrder[PT::OIL]; + integer const ipGas = phaseOrder[PT::GAS]; + + integer ipWetting = -1, ipNonWetting = -1; + + if( ipWater >= 0 && ipOil >= 0 && ipGas >= 0 ) + { + ipWetting = ipWater; + ipNonWetting = ipGas; + } + else if( ipWater < 0 ) + { + ipWetting = ipOil; + ipNonWetting = ipGas; + } + else if( ipOil < 0 ) + { + ipWetting = ipWater; + ipNonWetting = ipGas; + } + else if( ipGas < 0 ) + { + ipWetting = ipWater; + ipNonWetting = ipOil; + } + + //maybe a bit too pythonic + return std::make_tuple( ipWetting, ipNonWetting ); + } + } // namespace constitutive } // namespace geos diff --git a/src/coreComponents/constitutive/capillaryPressure/CapillaryPressureFields.hpp b/src/coreComponents/constitutive/capillaryPressure/CapillaryPressureFields.hpp index 653b7faeda8..b3cdb79645e 100644 --- a/src/coreComponents/constitutive/capillaryPressure/CapillaryPressureFields.hpp +++ b/src/coreComponents/constitutive/capillaryPressure/CapillaryPressureFields.hpp @@ -23,45 +23,86 @@ #include "constitutive/capillaryPressure/Layouts.hpp" #include "mesh/MeshFields.hpp" -namespace geos -{ - -namespace fields -{ - -namespace cappres -{ - -using array3dLayoutCapPressure = array3d< real64, constitutive::cappres::LAYOUT_CAPPRES >; -using array4dLayoutCapPressure_dS = array4d< real64, constitutive::cappres::LAYOUT_CAPPRES_DS >; - -DECLARE_FIELD( phaseCapPressure, - "phaseCapPressure", - array3dLayoutCapPressure, - 0, - LEVEL_0, - WRITE_AND_READ, - "Phase capillary pressure" ); - -DECLARE_FIELD( dPhaseCapPressure_dPhaseVolFraction, - "dPhaseCapPressure_dPhaseVolFraction", - array4dLayoutCapPressure_dS, - 0, - NOPLOT, - WRITE_AND_READ, - "Derivative of phase capillary pressure with respect to phase volume fraction" ); - -DECLARE_FIELD( jFuncMultiplier, - "jFuncMultiplier", - array2d< real64 >, - 0, - NOPLOT, - WRITE_AND_READ, - "Multiplier for the Leverett J-function" ); +namespace geos { -} + namespace fields { -} + namespace cappres { + + using array2dLayoutPhase = array2d; + using array3dLayoutCapPressure = array3d; + using array4dLayoutCapPressure_dS = array4d; + + + + enum ModeIndexType : integer { + DRAINAGE = 0,//to be used in array of Kernels + IMBIBITION = 1, + DRAINAGE_TO_IMBIBITION = 2, + IMBIBITION_TO_DRAINAGE = 3 + }; + + DECLARE_FIELD(phaseCapPressure, + "phaseCapPressure", + array3dLayoutCapPressure, + 0, + LEVEL_0, + WRITE_AND_READ, + "Phase capillary pressure"); + + DECLARE_FIELD(dPhaseCapPressure_dPhaseVolFraction, + "dPhaseCapPressure_dPhaseVolFraction", + array4dLayoutCapPressure_dS, + 0, + NOPLOT, + WRITE_AND_READ, + "Derivative of phase capillary pressure with respect to phase volume fraction"); + + DECLARE_FIELD(jFuncMultiplier, + "jFuncMultiplier", + array2d, + 0, + NOPLOT, + WRITE_AND_READ, + "Multiplier for the Leverett J-function"); + + DECLARE_FIELD(phaseTrappedVolFraction, + "phaseTrappedVolumeFraction", + array3dLayoutCapPressure, + 0, + LEVEL_0, + WRITE_AND_READ, + "Phase Trapped Volume Fraction"); + + DECLARE_FIELD(mode, + "Hysteresis Mode", + array1d, + 0, + LEVEL_0, + WRITE_AND_READ, + "Hysteresis mode"); + + + DECLARE_FIELD(phaseMaxHistoricalVolFraction, + "phaseMaxHistoricalVolFraction", + array2dLayoutPhase, + 0, + LEVEL_0, + WRITE_AND_READ, + "Phase max historical phase volume fraction"); + + DECLARE_FIELD(phaseMinHistoricalVolFraction, + "phaseMinHistoricalVolFraction", + array2dLayoutPhase, + 0, + LEVEL_0, + WRITE_AND_READ, + "Phase min historical phase volume fraction"); + + + } + + } } diff --git a/src/coreComponents/constitutive/capillaryPressure/CapillaryPressureSelector.hpp b/src/coreComponents/constitutive/capillaryPressure/CapillaryPressureSelector.hpp index c9b96e018b7..a8382183ba4 100644 --- a/src/coreComponents/constitutive/capillaryPressure/CapillaryPressureSelector.hpp +++ b/src/coreComponents/constitutive/capillaryPressure/CapillaryPressureSelector.hpp @@ -24,6 +24,7 @@ #include "constitutive/capillaryPressure/BrooksCoreyCapillaryPressure.hpp" #include "constitutive/capillaryPressure/JFunctionCapillaryPressure.hpp" #include "constitutive/capillaryPressure/TableCapillaryPressure.hpp" +#include "constitutive/capillaryPressure/TableCapillaryPressureHysteresis.hpp" #include "constitutive/capillaryPressure/VanGenuchtenCapillaryPressure.hpp" namespace geos @@ -36,24 +37,22 @@ template< typename LAMBDA > void constitutiveUpdatePassThru( CapillaryPressureBase const & capPres, LAMBDA && lambda ) { - ConstitutivePassThruHandler< - BrooksCoreyCapillaryPressure, - JFunctionCapillaryPressure, - TableCapillaryPressure, - VanGenuchtenCapillaryPressure - >::execute( capPres, std::forward< LAMBDA >( lambda ) ); + ConstitutivePassThruHandler< BrooksCoreyCapillaryPressure, + JFunctionCapillaryPressure, + TableCapillaryPressure, + TableCapillaryPressureHysteresis, + VanGenuchtenCapillaryPressure >::execute( capPres, std::forward< LAMBDA >( lambda ) ); } template< typename LAMBDA > void constitutiveUpdatePassThru( CapillaryPressureBase & capPres, LAMBDA && lambda ) { - ConstitutivePassThruHandler< - BrooksCoreyCapillaryPressure, - JFunctionCapillaryPressure, - TableCapillaryPressure, - VanGenuchtenCapillaryPressure - >::execute( capPres, std::forward< LAMBDA >( lambda ) ); + ConstitutivePassThruHandler< BrooksCoreyCapillaryPressure, + JFunctionCapillaryPressure, + TableCapillaryPressure, + TableCapillaryPressureHysteresis, + VanGenuchtenCapillaryPressure >::execute( capPres, std::forward< LAMBDA >( lambda ) ); } } // namespace constitutive diff --git a/src/coreComponents/constitutive/capillaryPressure/InverseCapillaryPressure.cpp b/src/coreComponents/constitutive/capillaryPressure/InverseCapillaryPressure.cpp index 534037c55f4..0156d06ab67 100644 --- a/src/coreComponents/constitutive/capillaryPressure/InverseCapillaryPressure.cpp +++ b/src/coreComponents/constitutive/capillaryPressure/InverseCapillaryPressure.cpp @@ -20,6 +20,7 @@ #include "InverseCapillaryPressure.hpp" #include "constitutive/capillaryPressure/BrooksCoreyCapillaryPressure.hpp" #include "constitutive/capillaryPressure/TableCapillaryPressure.hpp" +#include "constitutive/capillaryPressure/TableCapillaryPressureHysteresis.hpp" #include "constitutive/capillaryPressure/VanGenuchtenCapillaryPressure.hpp" #include "constitutive/capillaryPressure/JFunctionCapillaryPressure.hpp" @@ -317,6 +318,7 @@ void InverseCapillaryPressure< CAP_PRESSURE >::calculateJFunctionIndex( integer template class InverseCapillaryPressure< BrooksCoreyCapillaryPressure >; template class InverseCapillaryPressure< TableCapillaryPressure >; +template class InverseCapillaryPressure< TableCapillaryPressureHysteresis >; template class InverseCapillaryPressure< JFunctionCapillaryPressure >; template class InverseCapillaryPressure< VanGenuchtenCapillaryPressure >; template class InverseCapillaryPressure< NoOpCapillaryPressure >; diff --git a/src/coreComponents/constitutive/capillaryPressure/JFunctionCapillaryPressure.cpp b/src/coreComponents/constitutive/capillaryPressure/JFunctionCapillaryPressure.cpp index 320c940716c..fbb31266692 100644 --- a/src/coreComponents/constitutive/capillaryPressure/JFunctionCapillaryPressure.cpp +++ b/src/coreComponents/constitutive/capillaryPressure/JFunctionCapillaryPressure.cpp @@ -376,10 +376,12 @@ JFunctionCapillaryPressure::KernelWrapper:: arrayView2d< real64 const > const & jFuncMultiplier, arrayView1d< integer const > const & phaseTypes, arrayView1d< integer const > const & phaseOrder, + arrayView3d< real64, cappres::USD_CAPPRES > const & phaseTrapped, arrayView3d< real64, cappres::USD_CAPPRES > const & phaseCapPres, arrayView4d< real64, cappres::USD_CAPPRES_DS > const & dPhaseCapPres_dPhaseVolFrac ) : CapillaryPressureBaseUpdate( phaseTypes, phaseOrder, + phaseTrapped, phaseCapPres, dPhaseCapPres_dPhaseVolFrac ), m_jFuncKernelWrappers( jFuncKernelWrappers ), @@ -396,6 +398,7 @@ JFunctionCapillaryPressure::createKernelWrapper() m_jFuncMultiplier, m_phaseTypes, m_phaseOrder, + m_phaseTrappedVolFrac, m_phaseCapPressure, m_dPhaseCapPressure_dPhaseVolFrac ); } diff --git a/src/coreComponents/constitutive/capillaryPressure/JFunctionCapillaryPressure.hpp b/src/coreComponents/constitutive/capillaryPressure/JFunctionCapillaryPressure.hpp index 5e2f885cbf6..29e7692bd95 100644 --- a/src/coreComponents/constitutive/capillaryPressure/JFunctionCapillaryPressure.hpp +++ b/src/coreComponents/constitutive/capillaryPressure/JFunctionCapillaryPressure.hpp @@ -69,6 +69,7 @@ class JFunctionCapillaryPressure : public CapillaryPressureBase arrayView2d< real64 const > const & jFuncMultiplier, arrayView1d< integer const > const & phaseTypes, arrayView1d< integer const > const & phaseOrder, + arrayView3d< real64, cappres::USD_CAPPRES > const & phaseTrapped, arrayView3d< real64, cappres::USD_CAPPRES > const & phaseCapPres, arrayView4d< real64, cappres::USD_CAPPRES_DS > const & dPhaseCapPres_dPhaseVolFrac ); diff --git a/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressure.cpp b/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressure.cpp index 1fbc230a03e..a65049b23c3 100644 --- a/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressure.cpp +++ b/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressure.cpp @@ -222,10 +222,12 @@ TableCapillaryPressure::KernelWrapper:: arrayView1d< TableFunction::KernelWrapper const > const & inverseCapPresWrappers, arrayView1d< integer const > const & phaseTypes, arrayView1d< integer const > const & phaseOrder, + arrayView3d< real64, cappres::USD_CAPPRES > const & phaseTrapped, arrayView3d< real64, cappres::USD_CAPPRES > const & phaseCapPres, arrayView4d< real64, cappres::USD_CAPPRES_DS > const & dPhaseCapPres_dPhaseVolFrac ) : CapillaryPressureBaseUpdate( phaseTypes, phaseOrder, + phaseTrapped, phaseCapPres, dPhaseCapPres_dPhaseVolFrac ), m_capPresKernelWrappers( capPresKernelWrappers ), @@ -240,6 +242,7 @@ TableCapillaryPressure::createKernelWrapper() m_inverseCapPresWrappers, m_phaseTypes, m_phaseOrder, + m_phaseTrappedVolFrac, m_phaseCapPressure, m_dPhaseCapPressure_dPhaseVolFrac ); } diff --git a/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressure.hpp b/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressure.hpp index 7a018204287..a4ce6691d7f 100644 --- a/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressure.hpp +++ b/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressure.hpp @@ -58,6 +58,7 @@ class TableCapillaryPressure : public CapillaryPressureBase arrayView1d< TableFunction::KernelWrapper const > const & inverseCapPresWrappers, arrayView1d< integer const > const & phaseTypes, arrayView1d< integer const > const & phaseOrder, + arrayView3d< real64, cappres::USD_CAPPRES > const & phaseTrapped, arrayView3d< real64, cappres::USD_CAPPRES > const & phaseCapPres, arrayView4d< real64, cappres::USD_CAPPRES_DS > const & dPhaseCapPres_dPhaseVolFrac ); @@ -228,6 +229,9 @@ TableCapillaryPressure::KernelWrapper:: compute( phaseVolFraction, m_phaseCapPressure[k][q], m_dPhaseCapPressure_dPhaseVolFrac[k][q] ); + + std::cerr << "cell :" << k << "\n phaseCap " << m_phaseCapPressure[k][q] << std::endl; + std::cerr << "dPhaseCap_dS" << m_phaseCapPressure[k][q] << std::endl; } } // namespace constitutive diff --git a/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressureHelpers.cpp b/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressureHelpers.cpp index 619e69a22db..d412260e7c5 100644 --- a/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressureHelpers.cpp +++ b/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressureHelpers.cpp @@ -130,18 +130,46 @@ void TableCapillaryPressureHelpers::populateMinPhaseVolumeFraction( } void -TableCapillaryPressureHelpers::validateCapillaryPressureTable( geos::TableFunction const & capPresTable, - geos::string const & fullConstitutiveName, - bool const capPresMustBeIncreasing, - geos::real64 & phaseMax, geos::real64 & phaseMin ) +TableCapillaryPressureHelpers::validateCapillaryPressureTable( const geos::TableFunction & capPresTable, + const geos::string & fullConstitutiveName, + const bool capPresMustBeIncreasing, + geos::real64 & phaseMax, + geos::real64 & phaseMin, + geos::real64 & phaseCapPresMinEndPoint, + geos::real64 & phaseCapPresMaxEndPoint ) { TableCapillaryPressureHelpers::validateCapillaryPressureTable( capPresTable, fullConstitutiveName, capPresMustBeIncreasing ); ArrayOfArraysView< real64 const > coords = capPresTable.getCoordinates(); arraySlice1d< real64 const > phaseVolFrac = coords[0]; + arrayView1d< real64 const > const capPres = capPresTable.getValues(); + phaseMin = phaseVolFrac[0]; + phaseCapPresMinEndPoint = capPres[0]; phaseMax = phaseVolFrac[phaseVolFrac.size()-1]; -} + phaseCapPresMaxEndPoint = capPres[phaseVolFrac.size()-1]; + + + if(capPresMustBeIncreasing) { + + for( localIndex i = 1; i < coords.sizeOfArray( 0 ); ++i ) { + if (isZero(capPres[i - 1]) && !isZero(capPres[i])) { + phaseMin = phaseVolFrac[i - 1]; + phaseCapPresMinEndPoint = capPres[i - 1]; + } + } + } + else + { + for( localIndex i = coords.sizeOfArray( 0 )-2; i>0; --i ) { + if (isZero(capPres[i + 1]) && !isZero(capPres[i])) { + phaseMax = phaseVolFrac[i + 1]; + phaseCapPresMaxEndPoint = capPres[i + 1]; + } + } + + } + } } // namespace constitutive diff --git a/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressureHelpers.hpp b/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressureHelpers.hpp index a691637002c..276d8c3eb92 100644 --- a/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressureHelpers.hpp +++ b/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressureHelpers.hpp @@ -47,7 +47,9 @@ struct TableCapillaryPressureHelpers string const & fullConstitutiveName, bool const capPresMustBeIncreasing, real64 & phaseMax, - real64 & phaseMin ); + real64 & phaseMin, + real64 & phaseCapPresMinEndPoint, + real64 & phaseCapPresMaxEndPoint ); /** * @brief Populates the minimum phase volume fraction for each phase from the ends of the provided tables diff --git a/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressureHysteresis.cpp b/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressureHysteresis.cpp new file mode 100644 index 00000000000..9a479d97b0c --- /dev/null +++ b/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressureHysteresis.cpp @@ -0,0 +1,2267 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2018-2020 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2020 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2018-2020 TotalEnergies + * Copyright (c) 2019- GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + + +#include "TableCapillaryPressureHysteresis.hpp" + +#include "constitutive/capillaryPressure/TableCapillaryPressureHelpers.hpp" +#include "functions/FunctionManager.hpp" +#include "constitutive/ConstitutiveManager.hpp" + +namespace geos { + + using namespace dataRepository; + + namespace constitutive { + + TableCapillaryPressureHysteresis::TableCapillaryPressureHysteresis(const std::string &name, + dataRepository::Group *const parent) + : CapillaryPressureBase(name, parent) { + + registerWrapper(viewKeyStruct::phaseHasHysteresisString(), &m_phaseHasHysteresis). + setInputFlag(InputFlags::FALSE) + . // will be deduced from tables + setSizedFromParent(0); + + registerWrapper(viewKeyStruct::landParameterString(), &m_landParam). + setInputFlag(InputFlags::FALSE). // will be deduced from tables + setSizedFromParent(0); + + //2phase + registerWrapper(viewKeyStruct::drainageWettingNonWettingCapPresTableNameString(), + &m_drainageWettingNonWettingCapPresTableName). + setInputFlag(InputFlags::OPTIONAL). + setDescription("Name of the drainage two-phase table for capillary pressure curve. \n" + "If you want to use 3-phase flow please use instead " + + string(viewKeyStruct::drainageWettingIntermediateCapPresTableNameString()) + + " and " + + string(viewKeyStruct::drainageNonWettingIntermediateCapPresTableNameString()) + + "to specify the tables names"); + registerWrapper(viewKeyStruct::imbibitionWettingNonWettingCapPresTableNameString(), + &m_imbibitionWettingNonWettingCapPresTableName). + setInputFlag(InputFlags::OPTIONAL). + setDescription("Name of the drainage two-phase table for capillary pressure curve. \n" + "If you want to use 3-phase flow please use instead " + + string(viewKeyStruct::imbibitionWettingIntermediateCapPresTableNameString()) + + " and " + + string(viewKeyStruct::imbibitionNonWettingIntermediateCapPresTableNameString()) + + "to specify the tables names"); + //3phase + registerWrapper(viewKeyStruct::drainageWettingIntermediateCapPresTableNameString(), + &m_drainageWettingIntermediateCapPresTableName). + setInputFlag(InputFlags::OPTIONAL). + setDescription( + "Drainage wetting/intermediate (e.g. w/o) capillary pressure table name for the wetting phase.\n" + "To neglect hysteresis on this phase, just use the same table name for the drainage and imbibition curves"); + registerWrapper(viewKeyStruct::drainageNonWettingIntermediateCapPresTableNameString(), + &m_drainageNonWettingIntermediateCapPresTableName). + setInputFlag(InputFlags::OPTIONAL). + setDescription( + "Drainage non-wetting/intermediate (e.g. o/g) capillary pressure table name for the non-wetting phase.\n" + "To neglect hysteresis on this phase, just use the same table name for the drainage and imbibition curves"); + registerWrapper(viewKeyStruct::imbibitionWettingIntermediateCapPresTableNameString(), + &m_imbibitionWettingIntermediateCapPresTableName). + setInputFlag(InputFlags::OPTIONAL). + setDescription("Imbibition wetting/intermediate (e.g. w/o) table name for the wetting phase.\n" + "To neglect hysteresis on this phase, just use the same table name for the drainage and imbibition curves"); + registerWrapper(viewKeyStruct::imbibitionNonWettingIntermediateCapPresTableNameString(), + &m_imbibitionNonWettingIntermediateCapPresTableName). + setInputFlag(InputFlags::OPTIONAL). + setDescription("Imbibition non-wetting/intermediate (e.g. o/g) table name for the wetting phase.\n" + "To neglect hysteresis on this phase, just use the same table name for the drainage and imbibition curves"); + + // kernels + //2p + registerWrapper(viewKeyStruct::wettingNonWettingCapillaryPressureKernelWrappersString(), + &m_wettingNonWettingCapillaryPressureKernelWrappers) + .setSizedFromParent(0).setRestartFlags(RestartFlags::NO_WRITE); + //3p + registerWrapper(viewKeyStruct::wettingIntermediateCapillaryPressureKernelWrappersString(), + &m_wettingIntermediateCapillaryPressureKernelWrappers) + .setSizedFromParent(0).setRestartFlags(RestartFlags::NO_WRITE); + registerWrapper(viewKeyStruct::nonWettingIntermediateCapillaryPressureKernelWrappersString(), + &m_nonWettingIntermediateCapillaryPressureKernelWrappers) + .setSizedFromParent(0).setRestartFlags(RestartFlags::NO_WRITE); + + + registerWrapper(viewKeyStruct::wettingCurveString(), &m_wettingCurve). + setInputFlag( + InputFlags::FALSE). // will be deduced from tables + setSizedFromParent( + 0) + .setRestartFlags(RestartFlags::NO_WRITE); + + registerWrapper(viewKeyStruct::nonWettingCurveString(), &m_nonWettingCurve). + setInputFlag( + InputFlags::FALSE). // will be deduced from tables + setSizedFromParent( + 0) + .setRestartFlags(RestartFlags::NO_WRITE); + + //Forwarded to KilloughHysteresis + registerWrapper(KilloughHysteresis::viewKeyStruct::jerauldParameterAString(), &m_jerauldParam_a). + setInputFlag(InputFlags::OPTIONAL). + setApplyDefaultValue(0.1). + setDescription( + "First parameter (modification parameter) introduced by Jerauld in the Land trapping model (see RTD documentation)."); + + registerWrapper(KilloughHysteresis::viewKeyStruct::jerauldParameterBString(), &m_jerauldParam_b). + setInputFlag(InputFlags::OPTIONAL). + setApplyDefaultValue(0.0). + setDescription( + "Second parameter (modification parameter) introduced by Jerauld in the Land trapping model (see RTD documentation)."); + + + registerWrapper(KilloughHysteresis::viewKeyStruct::killoughCurvatureParameterPcString(), + &m_killoughCurvatureParamCapPres). + setInputFlag( + InputFlags::OPTIONAL). + setApplyDefaultValue( + .1). + setDescription( + "Curvature parameter introduced by Killough for wetting-phase hysteresis (see RTD documentation)."); + + //misc + registerWrapper(viewKeyStruct::phaseIntermediateMinVolFractionString(), &m_phaseIntermediateMinVolFraction). + setInputFlag(InputFlags::FALSE).setDescription("min vol fraction of intermediate if exist"). + // will be deduced from tables + setSizedFromParent(0); + + registerField< fields::cappres::mode >( &m_mode ); + + + registerField< fields::cappres::phaseMaxHistoricalVolFraction >( + &m_phaseMaxHistoricalVolFraction ); + registerField< fields::cappres::phaseMinHistoricalVolFraction >( + &m_phaseMinHistoricalVolFraction ); + + } + +/// usual utils + + void TableCapillaryPressureHysteresis::postProcessInput() { + + using TPP = ThreePhasePairPhaseType; + + integer const numPhases = m_phaseNames.size(); + GEOS_THROW_IF(numPhases != 2 && numPhases != 3, + GEOS_FMT("{}: the expected number of fluid phases is either two, or three", + getFullName()), + InputError); + + m_phaseHasHysteresis.resize(2); + + if (numPhases == 2) { + GEOS_THROW_IF(m_drainageWettingNonWettingCapPresTableName.empty(), + GEOS_FMT( + "{}: for a two-phase flow simulation, we must use {} to specify the capillary pressure table for the drainage pair (wetting phase, non-wetting phase)", + getFullName(), + viewKeyStruct::drainageWettingNonWettingCapPresTableNameString()), + InputError); + + + m_phaseHasHysteresis[TPP::INTERMEDIATE_WETTING] = (m_imbibitionWettingNonWettingCapPresTableName.empty() || + m_imbibitionWettingNonWettingCapPresTableName == + m_drainageWettingNonWettingCapPresTableName) + ? 0 : 1; + m_phaseHasHysteresis[TPP::INTERMEDIATE_NONWETTING] = m_phaseHasHysteresis[TPP::INTERMEDIATE_WETTING]; + + + } else if (numPhases == 3) { + + + GEOS_THROW_IF(m_drainageWettingIntermediateCapPresTableName.empty() || + m_drainageNonWettingIntermediateCapPresTableName.empty(), + GEOS_FMT( + "{}: for a three-phase flow simulation, we must use {} to specify the capillary pressure table " + "for the pair (wetting phase, intermediate phase), and {} to specify the capillary pressure table " + "for the pair (non-wetting phase, intermediate phase)", + getFullName(), + viewKeyStruct::drainageWettingIntermediateCapPresTableNameString(), + viewKeyStruct::drainageNonWettingIntermediateCapPresTableNameString()), + InputError); + + m_phaseHasHysteresis[TPP::INTERMEDIATE_WETTING] = (m_imbibitionWettingIntermediateCapPresTableName.empty() || + m_imbibitionWettingIntermediateCapPresTableName == + m_drainageWettingIntermediateCapPresTableName) + ? 0 : 1; + + m_phaseHasHysteresis[TPP::INTERMEDIATE_NONWETTING] = (m_imbibitionNonWettingIntermediateCapPresTableName.empty() || + m_imbibitionNonWettingIntermediateCapPresTableName == + m_drainageNonWettingIntermediateCapPresTableName) + ? 0 : 1; + } + //Killough section + //TODO improve hard coded default + KilloughHysteresis::postProcessInput(m_jerauldParam_a, m_jerauldParam_b, 0, + m_killoughCurvatureParamCapPres); + + GEOS_THROW_IF(m_phaseHasHysteresis[TPP::INTERMEDIATE_WETTING] == 0 && + m_phaseHasHysteresis[TPP::INTERMEDIATE_NONWETTING] == 0, + GEOS_FMT( + "{}: we must use {} (2-phase) / {} or {} (3-phase) to specify at least one imbibition relative permeability table", + getFullName(), + viewKeyStruct::imbibitionWettingNonWettingCapPresTableNameString(), + viewKeyStruct::imbibitionWettingIntermediateCapPresTableNameString(), + viewKeyStruct::imbibitionNonWettingIntermediateCapPresTableNameString()), + InputError); + + } + + void TableCapillaryPressureHysteresis::initializePreSubGroups() { + CapillaryPressureBase::initializePreSubGroups(); + + integer const numPhases = m_phaseNames.size(); + FunctionManager const &functionManager = FunctionManager::getInstance(); + + //equivalent to oil/gas - a.k.a two phase flow ordered by non wetting + bool const capPresMustBeIncreasing = (m_phaseOrder[PhaseType::WATER] < 0) + ? true // pc on the gas phase, function must be increasing + : false; // pc on the water phase, function must be decreasing + + + // Step 1: check sanity of drainage tables + if (numPhases == 2) { + + real64 drainageWettingPhaseMaxVolumeFraction, drainageWettingMinCapPres, + drainageNonWettingPhaseMinVolumeFraction, drainageNonWettingMinCapPres, + imbibitionWettingPhaseMaxVolumeFraction, imbibitionWettingMinCapPres, + imbibitionNonWettingPhaseMinVolumeFraction, imbibitionNonWettingMinCapPres, + wettingPhaseMinVolumeFraction, wettingMaxCapPres, + nonWettingPhaseMaxVolumeFraction, nonWettingMaxCapPres; + + { + + imbibitionNonWettingMinCapPres = 0.0; + + GEOS_THROW_IF(!functionManager.hasGroup(m_drainageWettingNonWettingCapPresTableName), + GEOS_FMT("{}: the table function named {} could not be found", + getFullName(), + m_drainageWettingNonWettingCapPresTableName), + InputError); + TableFunction const + &capPresTable = functionManager.getGroup( + m_drainageWettingNonWettingCapPresTableName); + + //w/o or w/g pair + if (!capPresMustBeIncreasing) { + TableCapillaryPressureHelpers::validateCapillaryPressureTable(capPresTable, getFullName(), + capPresMustBeIncreasing, + drainageWettingPhaseMaxVolumeFraction, + wettingPhaseMinVolumeFraction, + drainageWettingMinCapPres, + wettingMaxCapPres); + + drainageNonWettingPhaseMinVolumeFraction = 1. - drainageWettingPhaseMaxVolumeFraction; + nonWettingPhaseMaxVolumeFraction = 1. - wettingPhaseMinVolumeFraction; + + } else { // o/g pair + TableCapillaryPressureHelpers::validateCapillaryPressureTable(capPresTable, getFullName(), + capPresMustBeIncreasing, + nonWettingPhaseMaxVolumeFraction, + drainageNonWettingPhaseMinVolumeFraction, + nonWettingMaxCapPres, + drainageNonWettingMinCapPres ); + + drainageWettingPhaseMaxVolumeFraction = 1. - drainageNonWettingPhaseMinVolumeFraction; + wettingPhaseMinVolumeFraction = 1. - nonWettingPhaseMaxVolumeFraction; + } + + } + + { + GEOS_THROW_IF(!functionManager.hasGroup(m_imbibitionWettingNonWettingCapPresTableName), + GEOS_FMT("{}: the table function named {} could not be found", + getFullName(), + m_imbibitionWettingNonWettingCapPresTableName), + InputError); + TableFunction const + &capPresTable = functionManager.getGroup( + m_imbibitionWettingNonWettingCapPresTableName); + + //w/o or w/g pair + if (!capPresMustBeIncreasing) { + TableCapillaryPressureHelpers::validateCapillaryPressureTable(capPresTable, getFullName(), + capPresMustBeIncreasing, + imbibitionWettingPhaseMaxVolumeFraction, + wettingPhaseMinVolumeFraction, + imbibitionWettingMinCapPres, + wettingMaxCapPres); + + imbibitionNonWettingPhaseMinVolumeFraction = 1. - imbibitionWettingPhaseMaxVolumeFraction; + nonWettingPhaseMaxVolumeFraction = 1. - wettingPhaseMinVolumeFraction; + + } else { // o/g pair + TableCapillaryPressureHelpers::validateCapillaryPressureTable(capPresTable, getFullName(), + capPresMustBeIncreasing, + nonWettingPhaseMaxVolumeFraction, + imbibitionNonWettingPhaseMinVolumeFraction, + nonWettingMaxCapPres, + imbibitionWettingMinCapPres ); + + imbibitionWettingPhaseMaxVolumeFraction = 1. - imbibitionNonWettingPhaseMinVolumeFraction; + wettingPhaseMinVolumeFraction = 1. - nonWettingPhaseMaxVolumeFraction; + } + } + + //constructing wetting/nonwetting curves + + if(!capPresMustBeIncreasing) { + m_wettingCurve.setPoints( + {wettingPhaseMinVolumeFraction, wettingMaxCapPres}, // same as imbibition min + {imbibitionWettingPhaseMaxVolumeFraction, imbibitionWettingMinCapPres}, + {drainageWettingPhaseMaxVolumeFraction, drainageWettingMinCapPres}); + } + else { + m_nonWettingCurve.setPoints( + {nonWettingPhaseMaxVolumeFraction,nonWettingMaxCapPres}, + {imbibitionNonWettingPhaseMinVolumeFraction,imbibitionNonWettingMinCapPres}, + {drainageNonWettingPhaseMinVolumeFraction,drainageNonWettingMinCapPres} + ); + } + + } else if (numPhases == 3) { + + real64 drainageWettingPhaseMaxVolumeFraction, drainageWettingMinCapPres, + drainageNonWettingPhaseMinVolumeFraction, drainageNonWettingMinCapPres, + imbibitionWettingPhaseMaxVolumeFraction, imbibitionWettingMinCapPres, + imbibitionNonWettingPhaseMinVolumeFraction, imbibitionNonWettingMinCapPres, + wettingPhaseMinVolumeFraction, wettingMaxCapPres, + nonWettingPhaseMaxVolumeFraction, nonWettingMaxCapPres; + + GEOS_UNUSED_VAR( drainageWettingMinCapPres ); +//define scope to avoid differentiate temp var (lazy) + { + GEOS_THROW_IF(!functionManager.hasGroup(m_drainageWettingIntermediateCapPresTableName), + GEOS_FMT("{}: the table function named {} could not be found", + getFullName(), + m_drainageWettingIntermediateCapPresTableName), + InputError); + TableFunction const + &capPresTableWI = functionManager.getGroup( + m_drainageWettingIntermediateCapPresTableName); + TableCapillaryPressureHelpers::validateCapillaryPressureTable(capPresTableWI, getFullName(), false, + drainageWettingPhaseMaxVolumeFraction, + wettingPhaseMinVolumeFraction, + drainageNonWettingMinCapPres, + wettingMaxCapPres); + + GEOS_THROW_IF(!functionManager.hasGroup(m_drainageNonWettingIntermediateCapPresTableName), + GEOS_FMT("{}: the table function named {} could not be found", + getFullName(), + m_drainageNonWettingIntermediateCapPresTableName), + InputError); + TableFunction const &capPresTableNWI = + functionManager.getGroup(m_drainageNonWettingIntermediateCapPresTableName); + TableCapillaryPressureHelpers::validateCapillaryPressureTable(capPresTableNWI, getFullName(), true, + nonWettingPhaseMaxVolumeFraction, + drainageNonWettingPhaseMinVolumeFraction, + nonWettingMaxCapPres, + drainageWettingPhaseMaxVolumeFraction + ); + + m_phaseIntermediateMinVolFraction = + 1.0 - drainageWettingPhaseMaxVolumeFraction - drainageWettingPhaseMaxVolumeFraction; + } + + if (!m_imbibitionWettingIntermediateCapPresTableName.empty()) { + + GEOS_THROW_IF(!functionManager.hasGroup(m_imbibitionWettingIntermediateCapPresTableName), + GEOS_FMT("{}: the table function named {} could not be found", + getFullName(), + m_imbibitionWettingIntermediateCapPresTableName), + InputError); + TableFunction const + &capPresTableWI = functionManager.getGroup( + m_imbibitionWettingIntermediateCapPresTableName); + TableCapillaryPressureHelpers::validateCapillaryPressureTable(capPresTableWI, getFullName(), false, + imbibitionWettingPhaseMaxVolumeFraction, + wettingPhaseMinVolumeFraction, + imbibitionWettingMinCapPres, + wettingMaxCapPres + ); + + + } + + if (!m_imbibitionNonWettingIntermediateCapPresTableName.empty()) { + + GEOS_THROW_IF(!functionManager.hasGroup(m_imbibitionNonWettingIntermediateCapPresTableName), + GEOS_FMT("{}: the table function named {} could not be found", + getFullName(), + m_imbibitionNonWettingIntermediateCapPresTableName), + InputError); + TableFunction const &capPresTableNWI = + functionManager.getGroup(m_imbibitionNonWettingIntermediateCapPresTableName); + TableCapillaryPressureHelpers::validateCapillaryPressureTable(capPresTableNWI, getFullName(), true, + nonWettingPhaseMaxVolumeFraction, + imbibitionNonWettingPhaseMinVolumeFraction, + nonWettingMaxCapPres, + imbibitionNonWettingMinCapPres); + + + } + } + + // Step 2: check the sanity btw drainage and imbibition + auto const eps = 1e-15; + if (numPhases == 2) { + //TODO weak make stronger + GEOS_THROW_IF( + m_wettingCurve.isZero() && m_nonWettingCurve.isZero(), + GEOS_FMT( + "{}: Inconsistent data for capillary pressure hysteresis. No hysteresis curve is defined.", + getFullName()), + InputError); + + GEOS_THROW_IF( + !m_wettingCurve.isZero() && !m_nonWettingCurve.isZero(), + GEOS_FMT( + "{}: Inconsistent data for capillary pressure hysteresis. Both non wetting and wetting hysteresis curve are defined in two phase flow setting.", + getFullName()), + InputError); + + + } else if (numPhases == 3) { + + GEOS_THROW_IF(std::fabs(m_wettingCurve.oppositeBoundPhaseVolFraction - (1. - m_nonWettingCurve.oppositeBoundPhaseVolFraction - m_phaseIntermediateMinVolFraction)) > eps, + GEOS_FMT( + "{}: Inconsistent data for capillary pressure hysteresis. {}, {} and {} should sum up to 1.", + getFullName(), "Sw_min", "Snw_max", "Sinter_min"), + InputError); + GEOS_THROW_IF(std::fabs(m_wettingCurve.drainageExtremaPhaseVolFraction - (1. - m_nonWettingCurve.drainageExtremaPhaseVolFraction - m_phaseIntermediateMinVolFraction)) > eps, + GEOS_FMT( + "{}: Inconsistent data for capillary pressure hysteresis. {}, {} and {} should sum up to 1.", + getFullName(), "Sw_min", "Snw_max", "Sinter_min"), + InputError); + GEOS_THROW_IF(std::fabs(m_wettingCurve.imbibitionExtremaPhaseVolFraction - (1. - m_nonWettingCurve.imbibitionExtremaPhaseVolFraction - m_phaseIntermediateMinVolFraction)) > eps, + GEOS_FMT( + "{}: Inconsistent data for capillary pressure hysteresis. {}, {} and {} should sum up to 1.", + getFullName(), "Sw_min", "Snw_max", "Sinter_min"), + InputError); + + } + + + // Step 3: compute the Land coefficient + computeLandCoefficient(); + + // Step 4: Ensure arrays are properly resized if they weren't resized earlier + // This can happen if resizeFields() was called before phase names were set + if (m_phaseMaxHistoricalVolFraction.size(1) == 0 && numPhases > 0) { + localIndex const currentSize = m_phaseMaxHistoricalVolFraction.size(0); + if (currentSize > 0) { + m_phaseMaxHistoricalVolFraction.resize(currentSize, numPhases); + m_phaseMinHistoricalVolFraction.resize(currentSize, numPhases); + m_phaseMaxHistoricalVolFraction.setValues >(0.0); + m_phaseMinHistoricalVolFraction.setValues >(1.0); + } + } + } + +/// Land coeff (tb refactored out in KilloughHysteresis) and saved cvgd + + void TableCapillaryPressureHysteresis::computeLandCoefficient() { + // For now, we keep two separate Land parameters for the wetting and non-wetting phases + // For two-phase flow, we make sure that they are equal + m_landParam.resize(2); + + // Note: for simplicity, the notations are taken from IX documentation (although this breaks our phaseVolFrac naming convention) + + // Step 1: Land parameter for the wetting phase + + integer ipWetting, ipNonWetting; + std::tie(ipWetting, ipNonWetting) = phaseIndex(m_phaseOrder); + + KilloughHysteresis::computeLandCoefficient( m_wettingCurve, m_landParam[ipWetting] ); + KilloughHysteresis::computeLandCoefficient( m_nonWettingCurve, m_landParam[ipNonWetting] ); + + } + +/// common utils + void TableCapillaryPressureHysteresis::resizeFields(localIndex const size, localIndex const numPts) { + CapillaryPressureBase::resizeFields(size, numPts); + + integer const numPhases = numFluidPhases(); + + // If phase names haven't been set yet, we still need to resize m_mode + // The phase arrays will be resized properly once phase names are set + m_mode.resize(size); + + if (numPhases > 0) { + m_phaseMaxHistoricalVolFraction.resize(size, numPhases); + m_phaseMinHistoricalVolFraction.resize(size, numPhases); + m_phaseMaxHistoricalVolFraction.setValues >(0.0); + m_phaseMinHistoricalVolFraction.setValues >(1.0); + } + // If numPhases == 0, the arrays will remain uninitialized until resizeFields is called again + // after phase names are set. This should happen automatically during initialization. + } + + void TableCapillaryPressureHysteresis::saveConvergedPhaseVolFractionState( + arrayView2d const &phaseVolFraction) const { + CapillaryPressureBase::saveConvergedState(); + + arrayView2d phaseMaxHistoricalVolFraction = m_phaseMaxHistoricalVolFraction.toView(); + arrayView2d phaseMinHistoricalVolFraction = m_phaseMinHistoricalVolFraction.toView(); + + localIndex const numElems = phaseVolFraction.size(0); + integer const numPhases = numFluidPhases(); + + forAll >(numElems, [=] GEOS_HOST_DEVICE(localIndex const ei) { + for (integer ip = 0; ip < numPhases; ++ip) { + phaseMaxHistoricalVolFraction[ei][ip] = LvArray::math::max(phaseVolFraction[ei][ip], + phaseMaxHistoricalVolFraction[ei][ip]); + phaseMinHistoricalVolFraction[ei][ip] = LvArray::math::min(phaseVolFraction[ei][ip], + phaseMinHistoricalVolFraction[ei][ip]); + } + }); + + } + + void + TableCapillaryPressureHysteresis::KernelWrapper::computeImbibitionWettingCapillaryPressure( + const arrayView1d &wettingKernelWapper, + const KilloughHysteresis::HysteresisCurve &wettingCurve, + const KilloughHysteresis::HysteresisCurve &nonWettingCurve, //discard if not needed + const geos::real64 &landParam, + const geos::real64 &phaseVolFraction, + const geos::real64 &phaseMinHistoricalVolFraction, + geos::real64 &phaseTrappedVolFrac, + geos::real64 &phaseCapPressure, + geos::real64 &dPhaseCapPressure_dPhaseVolFrac, + const ModeIndexType &mode) const { + GEOS_ASSERT(wettingCurve.isWetting()); + real64 const S = phaseVolFraction; + real64 const Smxi = wettingCurve.imbibitionExtremaPhaseVolFraction; + real64 const Smxd = wettingCurve.drainageExtremaPhaseVolFraction; + real64 const Smin = wettingCurve.oppositeBoundPhaseVolFraction; + + GEOS_UNUSED_VAR( Smxi, Smxd, phaseTrappedVolFrac ); + +// if( S <= Smin ) +// { +// //below accessible range +// phaseCapPressure = CAP_INF; +// dPhaseCapPressure_dPhaseVolFrac = -CAP_INF_DERIV; +// } +// else if( S >= Smxd ) +// { +// //above accessible range +// phaseCapPressure = -CAP_INF; +// dPhaseCapPressure_dPhaseVolFrac = -CAP_INF_DERIV; +// } +// else + { + //drainage to imbibition + real64 dpci_dS, dpcd_dS; + real64 const pci = wettingKernelWapper[ModeIndexType::IMBIBITION].compute(&S, &dpci_dS); + real64 const pcd = wettingKernelWapper[ModeIndexType::DRAINAGE].compute(&S, &dpcd_dS); + real64 const Somin = m_phaseIntermediateMinVolFraction; + + // Step 1: get the trapped from wetting data + real64 const Shy = (phaseMinHistoricalVolFraction > Smin) ? phaseMinHistoricalVolFraction : Smin; + + real64 const E = m_killoughCurvatureParamCapPres; + + //Step 2. compute F as in (EQ 34.15) F = (1/(Sw-Shy+E)-1/E) / (1/(Swma-Shy+E)-1/E) + //drainage to imbibition branch + if (mode == ModeIndexType::DRAINAGE_TO_IMBIBITION) { + + real64 Scrt = 0.0; + KilloughHysteresis::computeTrappedCriticalPhaseVolFraction(nonWettingCurve, + Shy, + landParam, + m_jerauldParam_a, + m_jerauldParam_b, + Scrt); + real64 const Swma = 1 - Scrt - Somin; + real64 F = (1. / (S - Shy + E) - 1. / E) / (1. / (Swma - Shy + E) - 1. / E); + //force bound + F = LvArray::math::max(F, 0.0); + F = LvArray::math::min(F, 1.0); + + //Step 3. Eventually assemble everything following (EQ. 34.14) + phaseCapPressure = pcd + F * (pci - pcd); + dPhaseCapPressure_dPhaseVolFrac = dpcd_dS + F * (dpci_dS - dpcd_dS); + } + //imbibition to drainage + else if (mode == ModeIndexType::IMBIBITION_TO_DRAINAGE) { + real64 Scrt = 0.0; + KilloughHysteresis::computeTrappedCriticalPhaseVolFraction(wettingCurve, + Shy, + landParam, + m_jerauldParam_a, + m_jerauldParam_b, + Scrt); + + real64 F = (1. / (Shy - S + E) - 1. / E) / (1. / (Shy - Scrt + E) - 1. / E); + //force bound + F = LvArray::math::max(F, 0.0); + F = LvArray::math::min(F, 1.0); + + //Step 3. Eventually assemble everything following (EQ. 34.14) + phaseCapPressure = pci + F * (pcd - pci); + dPhaseCapPressure_dPhaseVolFrac = dpci_dS + F * (dpcd_dS - dpci_dS); + + + } else { + GEOS_THROW(GEOS_FMT("{}: State is {}.Shouldnt be used in pure DRAINAGE or IMBIBITION.", + "TableCapillaryPressureHysteresis", + (mode == ModeIndexType::DRAINAGE) ? "DRAINAGE" : ((mode == + ModeIndexType::IMBIBITION) + ? "IMBIBITION" + : "UNKNOWN")), + InputError); + } + + + } + + } + + void + TableCapillaryPressureHysteresis::KernelWrapper::computeImbibitionWettingCapillaryPressure( + const arrayView1d &wettingKernelWapper, + const KilloughHysteresis::HysteresisCurve &wettingCurve, + const geos::real64 &landParam, + const geos::real64 &phaseVolFraction, + const geos::real64 &phaseMinHistoricalVolFraction, + geos::real64 &phaseTrappedVolFrac, + geos::real64 &phaseCapPressure, + geos::real64 &dPhaseCapPressure_dPhaseVolFrac, + const ModeIndexType &mode) const { + GEOS_ASSERT(wettingCurve.isWetting()); + real64 const S = phaseVolFraction; + real64 const Smxi = wettingCurve.imbibitionExtremaPhaseVolFraction; + real64 const Smxd = wettingCurve.drainageExtremaPhaseVolFraction; + real64 const Smin = wettingCurve.oppositeBoundPhaseVolFraction; + + GEOS_UNUSED_VAR( Smxi, Smxd, phaseTrappedVolFrac ); + +// if( S <= Smin ) +// { +// //below accessible range +// phaseCapPressure = CAP_INF; +// dPhaseCapPressure_dPhaseVolFrac = -CAP_INF_DERIV; +// } +// else if( S >= Smxd ) +// { +// //above accessible range +// phaseCapPressure = -CAP_INF; +// dPhaseCapPressure_dPhaseVolFrac = -CAP_INF_DERIV; +// } +// else + { + //drainage to imbibition + real64 dpci_dS, dpcd_dS; + real64 const pci = wettingKernelWapper[ModeIndexType::IMBIBITION].compute(&S, &dpci_dS); + real64 const pcd = wettingKernelWapper[ModeIndexType::DRAINAGE].compute(&S, &dpcd_dS); + + // Step 1: get the trapped from wetting data + real64 const Shy = (phaseMinHistoricalVolFraction > Smin) ? phaseMinHistoricalVolFraction : Smin; + + real64 const E = m_killoughCurvatureParamCapPres; + + //Step 2. compute F as in (EQ 34.15) F = (1/(Sw-Shy+E)-1/E) / (1/(Swma-Shy+E)-1/E) + //drainage to imbibition branch + if (mode == ModeIndexType::DRAINAGE_TO_IMBIBITION) { + + real64 Scrt = 0.0; + KilloughHysteresis::computeTrappedCriticalPhaseVolFraction(wettingCurve, + Shy, + landParam, + m_jerauldParam_a, + m_jerauldParam_b, + Scrt); + + + + //should be the pore space accessible to the two wetting phase + real64 const Swma = 1 - (1 - Scrt); + real64 F = (1. / (S - Shy + E) - 1. / E) / (1. / (Swma - Shy + E) - 1. / E); + //force bound + F = LvArray::math::max(F, 0.0); + F = LvArray::math::min(F, 1.0); + + //Step 3. Eventually assemble everything following (EQ. 34.14) + phaseCapPressure = pcd + F * (pci - pcd); + dPhaseCapPressure_dPhaseVolFrac = dpcd_dS + F * (dpci_dS - dpcd_dS); + } + //imbibition to drainage + else if (mode == ModeIndexType::IMBIBITION_TO_DRAINAGE) { + real64 Scrt = 0.0; + KilloughHysteresis::computeTrappedCriticalPhaseVolFraction(wettingCurve, + Shy, + landParam, + m_jerauldParam_a, + m_jerauldParam_b, + Scrt); + + real64 F = (1. / (Shy - S + E) - 1. / E) / (1. / (Shy - Scrt + E) - 1. / E); + //force bound + F = LvArray::math::max(F, 0.0); + F = LvArray::math::min(F, 1.0); + + //Step 3. Eventually assemble everything following (EQ. 34.14) + phaseCapPressure = pci + F * (pcd - pci); + dPhaseCapPressure_dPhaseVolFrac = dpci_dS + F * (dpcd_dS - dpci_dS); + + + } else { + GEOS_THROW(GEOS_FMT("{}: State is {}.Shouldnt be used in pure DRAINAGE or IMBIBITION.", + "TableCapillaryPressureHysteresis", + (mode == ModeIndexType::DRAINAGE) ? "DRAINAGE" : ((mode == + ModeIndexType::IMBIBITION) + ? "IMBIBITION" + : "UNKNOWN")), + InputError); + } + + + } + + } + void TableCapillaryPressureHysteresis::KernelWrapper::computeTwoPhaseWetting(const geos::integer ipWetting, + const geos::integer GEOS_UNUSED_PARAM( ipNonWetting ), + const arraySlice1d &phaseVolFraction, + const arraySlice1d &phaseMaxHistoricalVolFraction, + const arraySlice1d &phaseMinHistoricalVolFraction, + const arraySlice1d &phaseTrappedVolFrac, + arraySlice1d const &phaseCapPressure, + arraySlice2d const &dPhaseCapPressure_dPhaseVolFrac, + ModeIndexType &mode) const { + using TTP = ThreePhasePairPhaseType; + + // Validate array sizes and indices before accessing + GEOS_ASSERT_MSG(ipWetting >= 0, "ipWetting must be non-negative"); + GEOS_ASSERT_MSG(static_cast(phaseVolFraction.size()) > ipWetting, + GEOS_FMT("phaseVolFraction array too small: size={}, ipWetting={}. " + "This usually means the arrays haven't been properly resized. " + "Ensure resizeFields() has been called before using the KernelWrapper.", + phaseVolFraction.size(), ipWetting)); + GEOS_ASSERT_MSG(static_cast(phaseMaxHistoricalVolFraction.size()) > ipWetting, + GEOS_FMT("phaseMaxHistoricalVolFraction array too small: size={}, ipWetting={}. " + "This usually means the arrays haven't been properly resized. " + "Ensure resizeFields() has been called before using the KernelWrapper.", + phaseMaxHistoricalVolFraction.size(), ipWetting)); + GEOS_ASSERT_MSG(static_cast(phaseMinHistoricalVolFraction.size()) > ipWetting, + GEOS_FMT("phaseMinHistoricalVolFraction array too small: size={}, ipWetting={}. " + "This usually means the arrays haven't been properly resized. " + "Ensure resizeFields() has been called before using the KernelWrapper.", + phaseMinHistoricalVolFraction.size(), ipWetting)); + GEOS_ASSERT_MSG(static_cast(m_wettingNonWettingCapillaryPressureKernelWrappers.size()) >= 2, + GEOS_FMT("m_wettingNonWettingCapillaryPressureKernelWrappers must have at least 2 elements, but got {}. " + "This usually means createAllTableKernelWrappers() failed to populate the arrays.", + m_wettingNonWettingCapillaryPressureKernelWrappers.size())); + + // Determine mode based on saturation condition (matching relative permeability logic) + // Use DRAINAGE when saturation is at or below minimum, use scanning curves when above minimum + // This matches the relative permeability logic: drainage when S <= S_min, imbibition (scanning) when S > S_min + bool const useDrainage = !m_phaseHasHysteresis[TTP::INTERMEDIATE_WETTING] || + phaseVolFraction[ipWetting] <= phaseMinHistoricalVolFraction[ipWetting] + flowReversalBuffer; + + //--- wetting cap pressure -- W/O or W/G two phase flow + // Use drainage curve when S <= S_min (matching relative permeability logic) + // Use scanning curves when S > S_min (matching relative permeability logic) + // DEBUG: Print mode for capillary pressure + // printf("CapPressure: mode=%d, S_w=%.6e, S_min=%.6e, S_max=%.6e, hasHyst=%d\n", + // static_cast(mode), + // phaseVolFraction[ipWetting], + // phaseMinHistoricalVolFraction[ipWetting], + // phaseMaxHistoricalVolFraction[ipWetting], + // static_cast(m_phaseHasHysteresis[TTP::INTERMEDIATE_WETTING])); + + if (useDrainage) { + // Use simple drainage curve (matching relative permeability) + mode = ModeIndexType::DRAINAGE; + phaseTrappedVolFrac[ipWetting] = LvArray::math::min(phaseVolFraction[ipWetting], + m_wettingCurve.oppositeBoundPhaseVolFraction); + // printf("CapPressure: Using DRAINAGE curve (arrayIndex=0)\n"); + GEOS_ASSERT_MSG(static_cast(m_wettingNonWettingCapillaryPressureKernelWrappers.size()) > ModeIndexType::DRAINAGE, + "Invalid array index for kernel wrapper access"); + computeBoundCapillaryPressure( + m_wettingNonWettingCapillaryPressureKernelWrappers[ModeIndexType::DRAINAGE], + phaseVolFraction[ipWetting], + phaseCapPressure[ipWetting], + dPhaseCapPressure_dPhaseVolFrac[ipWetting][ipWetting]); + } + else { + // Use scanning curves (matching relative permeability) + // When S > S_min, saturation is increasing (moving away from minimum), + // so we're transitioning from drainage to imbibition -> use DRAINAGE_TO_IMBIBITION mode + mode = ModeIndexType::DRAINAGE_TO_IMBIBITION; + // printf("CapPressure: Using IMBIBITION (scanning) curves (mode=%d)\n", static_cast(mode)); + computeImbibitionWettingCapillaryPressure(m_wettingNonWettingCapillaryPressureKernelWrappers, + m_wettingCurve, + m_landParam[ipWetting], + phaseVolFraction[ipWetting], + phaseMinHistoricalVolFraction[ipWetting], + phaseTrappedVolFrac[ipWetting], + phaseCapPressure[ipWetting], + dPhaseCapPressure_dPhaseVolFrac[ipWetting][ipWetting], + mode); + } + +// trapped vol fraction + if (mode == ModeIndexType::DRAINAGE || mode == ModeIndexType::DRAINAGE_TO_IMBIBITION) { + + + + real64 const Smin = m_wettingCurve.oppositeBoundPhaseVolFraction; + real64 const Shy = (phaseMinHistoricalVolFraction[ipWetting] < Smin) + ? phaseMinHistoricalVolFraction[ipWetting] + : Smin; + real64 Scrt = 0.0; + KilloughHysteresis::computeTrappedCriticalPhaseVolFraction(m_wettingCurve, Shy, + m_landParam[ipWetting], + m_jerauldParam_a, + m_jerauldParam_b, + Scrt); + phaseTrappedVolFrac[ipWetting] = LvArray::math::min(Scrt, phaseVolFraction[ipWetting]); + + + //keep the same Land coeff as two phase only + KilloughHysteresis::computeTrappedCriticalPhaseVolFraction(m_wettingCurve.toNonWetting(), Shy, + m_landParam[ipWetting], + m_jerauldParam_a, + m_jerauldParam_b, + Scrt); + phaseTrappedVolFrac[ipWetting] = LvArray::math::min(Scrt, phaseVolFraction[ipWetting]); + + + + + } + else if (mode == ModeIndexType::IMBIBITION || mode == ModeIndexType::IMBIBITION_TO_DRAINAGE) { + + real64 const Smax = m_wettingCurve.imbibitionExtremaPhaseVolFraction; + real64 const Shy = (phaseMaxHistoricalVolFraction[ipWetting] < Smax) + ? phaseMaxHistoricalVolFraction[ipWetting] + : Smax; + real64 Scrt = 0.0; + //TODO (jacques) check if still accurate + KilloughHysteresis::computeTrappedCriticalPhaseVolFraction(m_wettingCurve, + Shy, + m_landParam[ipWetting], + m_jerauldParam_a, + m_jerauldParam_b, + Scrt); + + phaseTrappedVolFrac[ipWetting] = LvArray::math::min(Scrt, phaseVolFraction[ipWetting]); + + //keep the same Land coeff as two phase only + KilloughHysteresis::computeTrappedCriticalPhaseVolFraction(m_wettingCurve.toNonWetting(), Shy, + m_landParam[ipWetting], + m_jerauldParam_a, + m_jerauldParam_b, + Scrt); + phaseTrappedVolFrac[ipWetting] = LvArray::math::min(Scrt, phaseVolFraction[ipWetting]); + + } + + } + + void TableCapillaryPressureHysteresis::KernelWrapper::computeTwoPhaseNonWetting(const geos::integer ipWetting, + const geos::integer ipNonWetting, + const arraySlice1d &phaseVolFraction, + const arraySlice1d &phaseMaxHistoricalVolFraction, + const arraySlice1d &phaseMinHistoricalVolFraction, + const arraySlice1d &phaseTrappedVolFrac, + arraySlice1d const &phaseCapPressure, + arraySlice2d const &dPhaseCapPressure_dPhaseVolFrac, + ModeIndexType &mode) const { + using TTP = ThreePhasePairPhaseType; + //update state + // TODO check if we can get rid of DRAINAGE_TO_IMBIBITION && IMBIBITION_TO_DRAINAGE + if (mode == ModeIndexType::DRAINAGE_TO_IMBIBITION && + phaseVolFraction[ipNonWetting] >= phaseMaxHistoricalVolFraction[ipNonWetting] + flowReversalBuffer) + mode = ModeIndexType::DRAINAGE; + if (mode == ModeIndexType::IMBIBITION_TO_DRAINAGE && + phaseVolFraction[ipWetting] <= phaseMinHistoricalVolFraction[ipNonWetting] + flowReversalBuffer) + mode = ModeIndexType::IMBIBITION; + + // Update mode based on flow direction if we're in a pure state + // For non-wetting phase: if saturation is increasing (imbibition), mode should be IMBIBITION + // If saturation is decreasing (drainage), mode should be DRAINAGE + if (mode == ModeIndexType::DRAINAGE || mode == ModeIndexType::IMBIBITION) { + // If current saturation is significantly above min historical, we're in imbibition + if (phaseVolFraction[ipNonWetting] > phaseMinHistoricalVolFraction[ipNonWetting] + flowReversalBuffer) { + if (mode == ModeIndexType::DRAINAGE) { + mode = ModeIndexType::DRAINAGE_TO_IMBIBITION; + } + } + // If current saturation is significantly below max historical, we're in drainage + else if (phaseVolFraction[ipNonWetting] < phaseMaxHistoricalVolFraction[ipNonWetting] - flowReversalBuffer) { + if (mode == ModeIndexType::IMBIBITION) { + mode = ModeIndexType::IMBIBITION_TO_DRAINAGE; + } + } + } + + // Use simple drainage/imbibition curves when: + // 1. No hysteresis enabled, OR + // 2. We're in pure DRAINAGE mode (use drainage curve), OR + // 3. We're in pure IMBIBITION mode (use imbibition curve) + // Use scanning curves only during transitions (DRAINAGE_TO_IMBIBITION or IMBIBITION_TO_DRAINAGE) + if (!m_phaseHasHysteresis[TTP::INTERMEDIATE_NONWETTING] || + mode == ModeIndexType::DRAINAGE || + mode == ModeIndexType::IMBIBITION) { + phaseTrappedVolFrac[ipNonWetting] = LvArray::math::min(phaseVolFraction[ipNonWetting], + (mode == ModeIndexType::DRAINAGE) + ? m_nonWettingCurve.drainageExtremaPhaseVolFraction + : m_nonWettingCurve.imbibitionExtremaPhaseVolFraction); + // Ensure mode is a valid array index (0 or 1) + integer const arrayIndex = (mode == ModeIndexType::DRAINAGE) ? ModeIndexType::DRAINAGE : ModeIndexType::IMBIBITION; + GEOS_ASSERT_MSG(arrayIndex >= 0 && arrayIndex < static_cast(m_wettingNonWettingCapillaryPressureKernelWrappers.size()), + "Invalid array index for kernel wrapper access"); + computeBoundCapillaryPressure( + m_wettingNonWettingCapillaryPressureKernelWrappers[arrayIndex], + phaseVolFraction[ipNonWetting], + phaseCapPressure[ipNonWetting], + dPhaseCapPressure_dPhaseVolFrac[ipNonWetting][ipNonWetting]); + // when pc is on the gas phase, we need to multiply user input by -1 + // because CompositionalMultiphaseFVM does: pres_gas = pres_oil - pc_og, so we need a negative pc_og + phaseCapPressure[ipNonWetting] *= -1; + dPhaseCapPressure_dPhaseVolFrac[ipNonWetting][ipNonWetting] *= -1; + + } else { + // We're in a transition state (DRAINAGE_TO_IMBIBITION or IMBIBITION_TO_DRAINAGE) + // Use scanning curves + + computeImbibitionNonWettingCapillaryPressure(m_wettingNonWettingCapillaryPressureKernelWrappers, + m_nonWettingCurve, + m_landParam[ipNonWetting], + phaseVolFraction[ipNonWetting], + phaseMaxHistoricalVolFraction[ipNonWetting], + phaseTrappedVolFrac[ipNonWetting], + phaseCapPressure[ipNonWetting], + dPhaseCapPressure_dPhaseVolFrac[ipNonWetting][ipNonWetting], + mode); + + // when pc is on the gas phase, we need to multiply user input by -1 + // because CompositionalMultiphaseFVM does: pres_gas = pres_oil - pc_og, so we need a negative pc_og + phaseCapPressure[ipNonWetting] *= -1; + dPhaseCapPressure_dPhaseVolFrac[ipNonWetting][ipNonWetting] *= -1; + } + +// trapped vol fraction + if (mode == ModeIndexType::DRAINAGE || mode == ModeIndexType::DRAINAGE_TO_IMBIBITION) { + + { + real64 const Smax = m_nonWettingCurve.oppositeBoundPhaseVolFraction; + real64 const Shy = (phaseMaxHistoricalVolFraction[ipNonWetting] > Smax) + ? phaseMaxHistoricalVolFraction[ipNonWetting] + : Smax; + real64 Scrt = 0.0; + KilloughHysteresis::computeTrappedCriticalPhaseVolFraction(m_nonWettingCurve, Shy, + m_landParam[ipNonWetting], + m_jerauldParam_a, m_jerauldParam_b, + Scrt); + phaseTrappedVolFrac[ipNonWetting] = LvArray::math::min(Scrt, phaseVolFraction[ipNonWetting]); + + //keep the same Land coeff as two phase only + KilloughHysteresis::computeTrappedCriticalPhaseVolFraction(m_nonWettingCurve.toWetting(), Shy, + m_landParam[ipNonWetting], + m_jerauldParam_a, m_jerauldParam_b, + Scrt); + phaseTrappedVolFrac[ipNonWetting] = LvArray::math::min(Scrt, phaseVolFraction[ipNonWetting]); + } + } else if (mode == ModeIndexType::IMBIBITION || mode == ModeIndexType::IMBIBITION_TO_DRAINAGE) { + + { + real64 const Smin = m_nonWettingCurve.imbibitionExtremaPhaseVolFraction;; + real64 const Shy = (phaseMinHistoricalVolFraction[ipNonWetting] > Smin) + ? phaseMinHistoricalVolFraction[ipNonWetting] + : Smin; + real64 Scrt = 0.0; + KilloughHysteresis::computeTrappedCriticalPhaseVolFraction(m_nonWettingCurve, Shy, + m_landParam[ipNonWetting], + m_jerauldParam_a, m_jerauldParam_b, + Scrt); + phaseTrappedVolFrac[ipNonWetting] = LvArray::math::min(Scrt, phaseVolFraction[ipNonWetting]); + + //keep the same Land coeff as two phase only + KilloughHysteresis::computeTrappedCriticalPhaseVolFraction(m_nonWettingCurve.toWetting(), Shy, + m_landParam[ipNonWetting], + m_jerauldParam_a, m_jerauldParam_b, + Scrt); + phaseTrappedVolFrac[ipNonWetting] = LvArray::math::min(Scrt, phaseVolFraction[ipNonWetting]); + } + } + + + } + + void TableCapillaryPressureHysteresis::KernelWrapper::computeThreePhase(const geos::integer ipWetting, + const geos::integer GEOS_UNUSED_PARAM( ipInter ), + const geos::integer ipNonWetting, + const arraySlice1d &phaseVolFraction, + const arraySlice1d &phaseMaxHistoricalVolFraction, + const arraySlice1d &phaseMinHistoricalVolFraction, + const arraySlice1d &phaseTrappedVolFrac, + const arraySlice1d &phaseCapPressure, + const arraySlice2d &dPhaseCapPressure_dPhaseVolFrac, + ModeIndexType &mode) const { + + + LvArray::forValuesInSlice(dPhaseCapPressure_dPhaseVolFrac, [](real64 &val) { val = 0.0; }); + using TTP = ThreePhasePairPhaseType; + + // -- wetting curve if drainage only + if (!m_phaseHasHysteresis[TTP::INTERMEDIATE_WETTING] || + (mode == ModeIndexType::DRAINAGE && + phaseVolFraction[ipWetting] <= phaseMinHistoricalVolFraction[ipWetting] + flowReversalBuffer) || + (mode == ModeIndexType::IMBIBITION && + phaseVolFraction[ipWetting] >= phaseMaxHistoricalVolFraction[ipWetting] + flowReversalBuffer)) { + // water-oil capillary pressure + phaseTrappedVolFrac[ipWetting] = LvArray::math::min(phaseVolFraction[ipWetting], + m_wettingCurve.oppositeBoundPhaseVolFraction); + phaseCapPressure[ipWetting] = + m_wettingIntermediateCapillaryPressureKernelWrappers[mode].compute( + &(phaseVolFraction)[ipWetting], + &(dPhaseCapPressure_dPhaseVolFrac)[ipWetting][ipWetting]); + } else { + mode = (mode == ModeIndexType::DRAINAGE) ? ModeIndexType::DRAINAGE_TO_IMBIBITION + : ModeIndexType::IMBIBITION_TO_DRAINAGE; + computeImbibitionWettingCapillaryPressure(m_wettingIntermediateCapillaryPressureKernelWrappers, + m_wettingCurve, + m_nonWettingCurve, + m_landParam[ipWetting], + phaseVolFraction[ipWetting], + phaseMinHistoricalVolFraction[ipWetting], + phaseTrappedVolFrac[ipWetting], + phaseCapPressure[ipWetting], + dPhaseCapPressure_dPhaseVolFrac[ipWetting][ipWetting], + mode); + + + } + + + // -- non-wetting cure if drainage only + // gas-oil capillary pressure + if (!m_phaseHasHysteresis[TTP::INTERMEDIATE_NONWETTING] || + (mode == ModeIndexType::DRAINAGE && + phaseVolFraction[ipNonWetting] >= phaseMaxHistoricalVolFraction[ipNonWetting] + flowReversalBuffer) || + (mode == ModeIndexType::IMBIBITION && + phaseVolFraction[ipNonWetting] <= phaseMinHistoricalVolFraction[ipNonWetting] + flowReversalBuffer)) { + phaseTrappedVolFrac[ipNonWetting] = LvArray::math::min(phaseVolFraction[ipNonWetting], + (mode == ModeIndexType::DRAINAGE) + ? m_nonWettingCurve.drainageExtremaPhaseVolFraction + : m_nonWettingCurve.imbibitionExtremaPhaseVolFraction); + phaseCapPressure[ipNonWetting] = + m_nonWettingIntermediateCapillaryPressureKernelWrappers[mode].compute( + &(phaseVolFraction)[ipNonWetting], + &(dPhaseCapPressure_dPhaseVolFrac)[ipNonWetting][ipNonWetting]); + + + // when pc is on the gas phase, we need to multiply user input by -1 + // because CompositionalMultiphaseFVM does: pres_gas = pres_oil - pc_og, so we need a negative pc_og + phaseCapPressure[ipNonWetting] *= -1; + dPhaseCapPressure_dPhaseVolFrac[ipNonWetting][ipNonWetting] *= -1; + } else { + + mode = (mode == ModeIndexType::DRAINAGE) ? ModeIndexType::DRAINAGE_TO_IMBIBITION + : ModeIndexType::IMBIBITION_TO_DRAINAGE; + + computeImbibitionNonWettingCapillaryPressure(m_nonWettingIntermediateCapillaryPressureKernelWrappers, + m_nonWettingCurve, + m_wettingCurve, + m_landParam[ipNonWetting], + phaseVolFraction[ipNonWetting], + phaseMinHistoricalVolFraction[ipNonWetting], + phaseTrappedVolFrac[ipNonWetting], + phaseCapPressure[ipNonWetting], + dPhaseCapPressure_dPhaseVolFrac[ipNonWetting][ipNonWetting], + mode); + // when pc is on the gas phase, we need to multiply user input by -1 + // because CompositionalMultiphaseFVM does: pres_gas = pres_oil - pc_og, so we need a negative pc_og + phaseCapPressure[ipNonWetting] *= -1; + dPhaseCapPressure_dPhaseVolFrac[ipNonWetting][ipNonWetting] *= -1; + + //update trapped fraction + if (mode == ModeIndexType::DRAINAGE || mode == ModeIndexType::DRAINAGE_TO_IMBIBITION) { + + + { + real64 const Smin = m_wettingCurve.oppositeBoundPhaseVolFraction; + real64 const Shy = (phaseMinHistoricalVolFraction[ipWetting] < Smin) + ? phaseMinHistoricalVolFraction[ipWetting] + : Smin; + real64 Scrt = 0.0; + KilloughHysteresis::computeTrappedCriticalPhaseVolFraction(m_wettingCurve, Shy, + m_landParam[ipWetting], + m_jerauldParam_a, m_jerauldParam_b, + Scrt); + phaseTrappedVolFrac[ipWetting] = LvArray::math::min(Scrt, phaseVolFraction[ipWetting]); + } + + { + real64 const Smax = m_nonWettingCurve.oppositeBoundPhaseVolFraction; + real64 const Shy = (phaseMaxHistoricalVolFraction[ipNonWetting] > Smax) + ? phaseMaxHistoricalVolFraction[ipNonWetting] + : Smax; + real64 Scrt = 0.0; + KilloughHysteresis::computeTrappedCriticalPhaseVolFraction(m_nonWettingCurve, Shy, + m_landParam[ipNonWetting], + m_jerauldParam_a, m_jerauldParam_b, + Scrt); + phaseTrappedVolFrac[ipNonWetting] = LvArray::math::min(Scrt, phaseVolFraction[ipNonWetting]); + } + } else if (mode == ModeIndexType::IMBIBITION || mode == ModeIndexType::IMBIBITION_TO_DRAINAGE) { + { + real64 const Smax = m_wettingCurve.imbibitionExtremaPhaseVolFraction; + real64 const Shy = (phaseMaxHistoricalVolFraction[ipWetting] < Smax) + ? phaseMaxHistoricalVolFraction[ipWetting] + : Smax; + real64 Scrt = 0.0; + KilloughHysteresis::computeTrappedCriticalPhaseVolFraction(m_wettingCurve, Shy, + m_landParam[ipWetting], + m_jerauldParam_a, m_jerauldParam_b, + Scrt); + phaseTrappedVolFrac[ipWetting] = LvArray::math::min(Scrt, phaseVolFraction[ipWetting]); + } + + { + real64 const Smin = m_nonWettingCurve.imbibitionExtremaPhaseVolFraction;; + real64 const Shy = (phaseMinHistoricalVolFraction[ipNonWetting] > Smin) + ? phaseMinHistoricalVolFraction[ipNonWetting] + : Smin; + real64 Scrt = 0.0; + KilloughHysteresis::computeTrappedCriticalPhaseVolFraction(m_nonWettingCurve, Shy, + m_landParam[ipNonWetting], + m_jerauldParam_a, m_jerauldParam_b, + Scrt); + phaseTrappedVolFrac[ipNonWetting] = LvArray::math::min(Scrt, phaseVolFraction[ipNonWetting]); + } + } + + + } + + + } + + + void + TableCapillaryPressureHysteresis::KernelWrapper::computeImbibitionNonWettingCapillaryPressure( + const arrayView1d &nonWettingKernelWrapper, + const KilloughHysteresis::HysteresisCurve &nonWettingCurve, + const KilloughHysteresis::HysteresisCurve &wettingCurve, + const geos::real64 &landParam, + const geos::real64 &phaseVolFraction, + const geos::real64 &phaseMaxHistoricalVolFraction, + geos::real64 &phaseTrappedVolFrac, + geos::real64 &phaseCapPressure, + geos::real64 &dPhaseCapPressure_dPhaseVolFrac, + const ModeIndexType &mode) const { + GEOS_ASSERT(!nonWettingCurve.isWetting()); + real64 const S = phaseVolFraction; + real64 const Smii = nonWettingCurve.imbibitionExtremaPhaseVolFraction; + real64 const Smid = nonWettingCurve.drainageExtremaPhaseVolFraction; + real64 const Smax = nonWettingCurve.oppositeBoundPhaseVolFraction; + + GEOS_UNUSED_VAR( Smii, Smid ); + +// if( S >= Smax ) +// { +// //above accessible range +// phaseCapPressure = CAP_INF; +// dPhaseCapPressure_dPhaseVolFrac = CAP_INF_DERIV; +// } +// else if( S <= Smid ) +// { +// //below accessible range +// phaseCapPressure = -CAP_INF; +// dPhaseCapPressure_dPhaseVolFrac = CAP_INF_DERIV; +// } +// else + { + //drainage to imbibition + real64 dpci_dS, dpcd_dS; + real64 const pci = nonWettingKernelWrapper[ModeIndexType::IMBIBITION].compute(&S, &dpci_dS); + real64 const pcd = nonWettingKernelWrapper[ModeIndexType::DRAINAGE].compute(&S, &dpcd_dS); + + // Step 1: get the trapped from wetting data + real64 const Shy = (phaseMaxHistoricalVolFraction < Smax) ? phaseMaxHistoricalVolFraction : Smax; + + //drainage to imbibition + if (mode == ModeIndexType::DRAINAGE_TO_IMBIBITION) { + real64 Scrt = 0.0; + KilloughHysteresis::computeTrappedCriticalPhaseVolFraction(nonWettingCurve, Shy, landParam, + m_jerauldParam_a, m_jerauldParam_b, + Scrt); + + real64 const E = m_killoughCurvatureParamCapPres; + + //Set 2. compute F as in (EQ 34.21) F = (1/(Shy-S+E)-1/E) / (1/(Shy - Sgcr +E)-1/E) + real64 F = (1. / (Shy - S + E) - 1. / E) / (1. / (Shy - Scrt + E) - 1. / E); + //force bound + F = LvArray::math::max(F, 0.0); + F = LvArray::math::min(F, 1.0); + + //Step 3. compute dF_dS + real64 dF_dS = (1. / (S * S)) / (1. / (Shy - Scrt + E) - 1. / E); + + //Step 4. Eventually assemble everything following (EQ. 34.20) + phaseCapPressure = pcd + F * (pci - pcd); + dPhaseCapPressure_dPhaseVolFrac = dpci_dS + F * (dpci_dS - dpcd_dS); + dPhaseCapPressure_dPhaseVolFrac += dF_dS * (pci - pcd); + + //update trapped fraction + phaseTrappedVolFrac = LvArray::math::min(Scrt, S); + + } + //imbibition to drainage + else if (mode == ModeIndexType::IMBIBITION_TO_DRAINAGE) { + real64 Scrt = 0.0; + KilloughHysteresis::computeTrappedCriticalPhaseVolFraction(wettingCurve, Shy, landParam, + m_jerauldParam_a, m_jerauldParam_b, + Scrt); + real64 Sgma = 1. - Scrt - m_phaseIntermediateMinVolFraction; + + real64 const E = m_killoughCurvatureParamCapPres; + + //Set 2. compute F as in (EQ 34.21) F = (1/(Shy-S+E)-1/E) / (1/(Shy - Sgcr +E)-1/E) + real64 F = (1. / (S - Shy + E) - 1. / E) / (1. / (Sgma - Shy + E) - 1. / E); + //force bound + F = LvArray::math::max(F, 0.0); + F = LvArray::math::min(F, 1.0); + + //Step 3. compute dF_dS + real64 dF_dS = (-1. / (S * S)) / (1. / (Shy - Scrt + E) - 1. / E); + + //Step 4. Eventually assemble everything following (EQ. 34.20) + phaseCapPressure = pci + F * (pcd - pci); + dPhaseCapPressure_dPhaseVolFrac = dpcd_dS + F * (dpcd_dS - dpci_dS); + dPhaseCapPressure_dPhaseVolFrac += dF_dS * (pcd - pci); + } else { + GEOS_THROW(GEOS_FMT("{}: State is {}.Shouldnt be used in pure DRAINAGE or IMBIBITION.", + "TableCapillaryPressureHysteresis", + (mode == ModeIndexType::DRAINAGE) ? "DRAINAGE" : ((mode == + ModeIndexType::IMBIBITION) + ? "IMBIBITION" + : "UNKNOWN")), + InputError); + } + + + } + } + + + void + TableCapillaryPressureHysteresis::KernelWrapper::computeImbibitionNonWettingCapillaryPressure( + const arrayView1d &nonWettingKernelWrapper, + const KilloughHysteresis::HysteresisCurve &nonWettingCurve, + const geos::real64 &landParam, + const geos::real64 &phaseVolFraction, + const geos::real64 &phaseMaxHistoricalVolFraction, + geos::real64 &phaseTrappedVolFrac, + geos::real64 &phaseCapPressure, + geos::real64 &dPhaseCapPressure_dPhaseVolFrac, + const ModeIndexType &mode) const { + + GEOS_ASSERT(!nonWettingCurve.isWetting()); + real64 const S = phaseVolFraction; + real64 const Smii = nonWettingCurve.imbibitionExtremaPhaseVolFraction; + real64 const Smid = nonWettingCurve.drainageExtremaPhaseVolFraction; + real64 const Smax = nonWettingCurve.oppositeBoundPhaseVolFraction; + + GEOS_UNUSED_VAR( Smii, Smid ); + +// if( S >= Smax ) +// { +// //above accessible range +// phaseCapPressure = CAP_INF; +// dPhaseCapPressure_dPhaseVolFrac = CAP_INF_DERIV; +// } +// else if( S <= Smid ) +// { +// //below accessible range +// phaseCapPressure = -CAP_INF; +// dPhaseCapPressure_dPhaseVolFrac = CAP_INF_DERIV; +// } +// else + { + //drainage to imbibition + real64 dpci_dS, dpcd_dS; + real64 const pci = nonWettingKernelWrapper[ModeIndexType::IMBIBITION].compute(&S, &dpci_dS); + real64 const pcd = nonWettingKernelWrapper[ModeIndexType::DRAINAGE].compute(&S, &dpcd_dS); + + // Step 1: get the trapped from wetting data + real64 const Shy = (phaseMaxHistoricalVolFraction < Smax) ? phaseMaxHistoricalVolFraction : Smax; + + //drainage to imbibition + if (mode == ModeIndexType::DRAINAGE_TO_IMBIBITION) { + real64 Scrt = 0.0; + KilloughHysteresis::computeTrappedCriticalPhaseVolFraction(nonWettingCurve, Shy, landParam, + m_jerauldParam_a, m_jerauldParam_b, + Scrt); + + real64 const E = m_killoughCurvatureParamCapPres; + + //Set 2. compute F as in (EQ 34.21) F = (1/(Shy-S+E)-1/E) / (1/(Shy - Sgcr +E)-1/E) + real64 F = (1. / (Shy - S + E) - 1. / E) / (1. / (Shy - Scrt + E) - 1. / E); + //force bound + F = LvArray::math::max(F, 0.0); + F = LvArray::math::min(F, 1.0); + + //Step 3. compute dF_dS + real64 dF_dS = (1. / (S * S)) / (1. / (Shy - Scrt + E) - 1. / E); + + //Step 4. Eventually assemble everything following (EQ. 34.20) + phaseCapPressure = pcd + F * (pci - pcd); + dPhaseCapPressure_dPhaseVolFrac = dpci_dS + F * (dpci_dS - dpcd_dS); + dPhaseCapPressure_dPhaseVolFrac += dF_dS * (pci - pcd); + + //update trapped fraction + phaseTrappedVolFrac = LvArray::math::min(Scrt, S); + + } + //imbibition to drainage + else if (mode == ModeIndexType::IMBIBITION_TO_DRAINAGE) { + real64 Scrt = 0.0; + KilloughHysteresis::computeTrappedCriticalPhaseVolFraction(nonWettingCurve, Shy, landParam, + m_jerauldParam_a, m_jerauldParam_b, + Scrt); + real64 Sgma = 1. - (1. - Scrt); + + real64 const E = m_killoughCurvatureParamCapPres; + + //Set 2. compute F as in (EQ 34.21) F = (1/(Shy-S+E)-1/E) / (1/(Shy - Sgcr +E)-1/E) + real64 F = (1. / (S - Shy + E) - 1. / E) / (1. / (Sgma - Shy + E) - 1. / E); + //force bound + F = LvArray::math::max(F, 0.0); + F = LvArray::math::min(F, 1.0); + + //Step 3. compute dF_dS + real64 dF_dS = (-1. / (S * S)) / (1. / (Shy - Scrt + E) - 1. / E); + + //Step 4. Eventually assemble everything following (EQ. 34.20) + phaseCapPressure = pci + F * (pcd - pci); + dPhaseCapPressure_dPhaseVolFrac = dpcd_dS + F * (dpcd_dS - dpci_dS); + dPhaseCapPressure_dPhaseVolFrac += dF_dS * (pcd - pci); + } else { + GEOS_THROW(GEOS_FMT("{}: State is {}.Shouldnt be used in pure DRAINAGE or IMBIBITION.", + "TableCapillaryPressureHysteresis", + (mode == ModeIndexType::DRAINAGE) ? "DRAINAGE" : ((mode == + ModeIndexType::IMBIBITION) + ? "IMBIBITION" + : "UNKNOWN")), + InputError); + } + + + } + } + + + void TableCapillaryPressureHysteresis::KernelWrapper::computeBoundCapillaryPressure( + const TableFunction::KernelWrapper &drainageRelpermWrapper, + const geos::real64 &phaseVolFraction, + geos::real64 &phaseCapPressure, + geos::real64 &dPhaseCapPressure_dPhaseVolFrac) const { + phaseCapPressure = drainageRelpermWrapper.compute(&phaseVolFraction, + &dPhaseCapPressure_dPhaseVolFrac); + + } + + /// Helper function to compute Pc(S) for given S, mode, and historical values + /// Used for Newton-Raphson inversion in computeInv + GEOS_HOST_DEVICE + inline real64 TableCapillaryPressureHysteresis::KernelWrapper::computeCapillaryPressureForSaturation( + real64 const S, + fields::cappres::ModeIndexType const &mode, + integer const ipPhase, + real64 const &phaseMinHistoricalVolFraction, + real64 const &phaseMaxHistoricalVolFraction, + arrayView1d const &capPresKernelWrappers, + KilloughHysteresis::HysteresisCurve const &wettingCurve, + KilloughHysteresis::HysteresisCurve const &nonWettingCurve, + real64 const &landParam, + real64 const &phaseIntermediateMinVolFraction, + real64 const &killoughCurvatureParam, + real64 const &jerauldParam_a, + real64 const &jerauldParam_b, + bool const isWettingPhase, + real64 const precomputedScrt, + real64 const precomputedDenomF, + real64 const precomputedShy) const + { + real64 pc = 0.0; + real64 dpc_dS = 0.0; + + // For pure drainage or imbibition modes, use the table directly + if (mode == fields::cappres::ModeIndexType::DRAINAGE || mode == fields::cappres::ModeIndexType::IMBIBITION) { + integer const arrayIndex = (mode == fields::cappres::ModeIndexType::DRAINAGE) ? fields::cappres::ModeIndexType::DRAINAGE : fields::cappres::ModeIndexType::IMBIBITION; + if (arrayIndex < static_cast(capPresKernelWrappers.size())) { + pc = capPresKernelWrappers[arrayIndex].compute(&S, &dpc_dS); + } + } + // For scanning curves (DRAINAGE_TO_IMBIBITION or IMBIBITION_TO_DRAINAGE) + else { + // Precomputed values should be provided by caller (from computeFlux before local_solver) + // If not provided, fall back to drainage curve to avoid calling computeTrappedCriticalPhaseVolFraction + if (precomputedScrt < 0.0) { + // Precomputed values not provided - return drainage curve value + real64 const arrayIndex = fields::cappres::ModeIndexType::DRAINAGE; + if (arrayIndex < static_cast(capPresKernelWrappers.size())) { + pc = capPresKernelWrappers[arrayIndex].compute(&S, &dpc_dS); + } + return pc; + } + + real64 dpci_dS, dpcd_dS; + real64 const pci = capPresKernelWrappers[fields::cappres::ModeIndexType::IMBIBITION].compute(&S, &dpci_dS); + real64 const pcd = capPresKernelWrappers[fields::cappres::ModeIndexType::DRAINAGE].compute(&S, &dpcd_dS); + + real64 const E = killoughCurvatureParam; + + if (isWettingPhase) { + real64 const Smin = wettingCurve.oppositeBoundPhaseVolFraction; + real64 const Shy = (precomputedShy >= 0.0) ? precomputedShy : + ((phaseMinHistoricalVolFraction > Smin) ? phaseMinHistoricalVolFraction : Smin); + + if (mode == fields::cappres::ModeIndexType::DRAINAGE_TO_IMBIBITION) { + // Use precomputed value - should have been computed before local_solver + real64 const Scrt = precomputedScrt; + real64 const Swma = 1 - Scrt - phaseIntermediateMinVolFraction; + real64 denomF = precomputedDenomF; + if (LvArray::math::abs(precomputedDenomF) < 1e-15) { + denomF = (1. / (Swma - Shy + E) - 1. / E); + } + // Guard against division by zero + real64 F = 0.0; + if (LvArray::math::abs(denomF) >= 1e-15) { + real64 const F_num = (1. / (S - Shy + E) - 1. / E); + F = F_num / denomF; + } + F = LvArray::math::max(F, 0.0); + F = LvArray::math::min(F, 1.0); + + pc = pcd + F * (pci - pcd); + dpc_dS = dpcd_dS + F * (dpci_dS - dpcd_dS); + } + else if (mode == fields::cappres::ModeIndexType::IMBIBITION_TO_DRAINAGE) { + // Use precomputed value - should have been computed before local_solver + real64 const Scrt = precomputedScrt; + + real64 denomF = precomputedDenomF; + if (LvArray::math::abs(precomputedDenomF) < 1e-15) { + denomF = (1. / (Shy - Scrt + E) - 1. / E); + } + // Guard against division by zero + real64 F = 0.0; + if (LvArray::math::abs(denomF) >= 1e-15) { + real64 const F_num = (1. / (Shy - S + E) - 1. / E); + F = F_num / denomF; + } + F = LvArray::math::max(F, 0.0); + F = LvArray::math::min(F, 1.0); + + pc = pci + F * (pcd - pci); + dpc_dS = dpci_dS + F * (dpcd_dS - dpci_dS); + } + } + else { + // Non-wetting phase + real64 const Smax = nonWettingCurve.oppositeBoundPhaseVolFraction; + real64 const Shy = (precomputedShy >= 0.0) ? precomputedShy : + ((phaseMaxHistoricalVolFraction < Smax) ? phaseMaxHistoricalVolFraction : Smax); + + if (mode == fields::cappres::ModeIndexType::DRAINAGE_TO_IMBIBITION) { + // Use precomputed value - should have been computed before local_solver + real64 const Scrt = precomputedScrt; + + real64 denomF = precomputedDenomF; + if (LvArray::math::abs(precomputedDenomF) < 1e-15) { + denomF = (1. / (Shy - Scrt + E) - 1. / E); + } + // Guard against division by zero + real64 F = 0.0; + if (LvArray::math::abs(denomF) >= 1e-15) { + real64 const F_num = (1. / (Shy - S + E) - 1. / E); + F = F_num / denomF; + } + F = LvArray::math::max(F, 0.0); + F = LvArray::math::min(F, 1.0); + + pc = pcd + F * (pci - pcd); + dpc_dS = dpci_dS + F * (dpci_dS - dpcd_dS); + // Note: there's also a dF/dS term in the non-wetting case, but for inversion we approximate + } + else if (mode == fields::cappres::ModeIndexType::IMBIBITION_TO_DRAINAGE) { + // Use precomputed value - should have been computed before local_solver + real64 const Scrt = precomputedScrt; + real64 const Sgma = 1. - Scrt - phaseIntermediateMinVolFraction; + + real64 denomF = precomputedDenomF; + if (LvArray::math::abs(precomputedDenomF) < 1e-15) { + denomF = (1. / (Sgma - Shy + E) - 1. / E); + } + // Guard against division by zero + real64 F = 0.0; + if (LvArray::math::abs(denomF) >= 1e-15) { + real64 const F_num = (1. / (S - Shy + E) - 1. / E); + F = F_num / denomF; + } + F = LvArray::math::max(F, 0.0); + F = LvArray::math::min(F, 1.0); + + pc = pci + F * (pcd - pci); + dpc_dS = dpcd_dS + F * (dpcd_dS - dpci_dS); + // Note: there's also a dF/dS term in the non-wetting case, but for inversion we approximate + } + } + } + + return pc; + } + + void + TableCapillaryPressureHysteresis::KernelWrapper::computeInv( + arraySlice1d const &phaseVolFraction, + arraySlice1d const &phaseMaxHistoricalVolFraction, + arraySlice1d const &phaseMinHistoricalVolFraction, + arraySlice1d const &phaseTrappedVolFrac, + arraySlice1d const &phaseCapPressure, + arraySlice2d const &dPhaseCapPressure_dPhaseVolFrac, + fields::cappres::ModeIndexType const &mode) const + { + LvArray::forValuesInSlice(dPhaseCapPressure_dPhaseVolFrac, [](real64 &val) { val = 0.0; }); + + using PT = CapillaryPressureBase::PhaseType; + integer const ipWater = (PT::WATER < m_phaseOrder.size()) ? m_phaseOrder[PT::WATER] : -1; + integer const ipOil = (PT::OIL < m_phaseOrder.size()) ? m_phaseOrder[PT::OIL] : -1; + integer const ipGas = (PT::GAS < m_phaseOrder.size()) ? m_phaseOrder[PT::GAS] : -1; + + // Newton-Raphson parameters + constexpr real64 tol = 1e-9; + constexpr integer maxIter = 20; + constexpr real64 minS = 0.0; + constexpr real64 maxS = 1.0; + + // Determine which phase pairs need inversion + if (ipWater >= 0 && ipOil >= 0 && ipGas >= 0) { + // Three-phase: invert wetting and non-wetting capillary pressures + + // 1. Invert wetting phase (water-oil capillary pressure) + constexpr real64 pcEpsilon = 1e-10; + if (ipWater >= 0 && LvArray::math::abs(phaseCapPressure[ipWater]) > pcEpsilon) { + real64 S_guess = phaseMaxHistoricalVolFraction[ipWater]; + if (S_guess <= phaseMinHistoricalVolFraction[ipWater] || S_guess < minS || S_guess > maxS) { + // Fall back to drainage/imbibition curve evaluation if available + real64 const Smin = m_wettingCurve.oppositeBoundPhaseVolFraction; + real64 const Smax = m_wettingCurve.drainageExtremaPhaseVolFraction; + S_guess = 0.5 * (Smin + Smax); + S_guess = LvArray::math::max(S_guess, minS); + S_guess = LvArray::math::min(S_guess, maxS); + } + + // Precomputed values should be provided by caller (from computeFlux before local_solver) + // If not provided (sentinel values), fall back to simple drainage/imbibition curves + // This avoids calling computeTrappedCriticalPhaseVolFraction inside local_solver + real64 precomputedScrt_water = -1.0; + real64 precomputedDenomF_water = 0.0; + real64 precomputedShy_water = -1.0; + + // For scanning curves without precomputed values, use drainage curve as fallback + // This avoids the floating-point exception that would occur in computeTrappedCriticalPhaseVolFraction + + real64 S = S_guess; + for (integer iter = 0; iter < maxIter; ++iter) { + // Compute Pc(S) using the helper function + real64 pc_computed = this->computeCapillaryPressureForSaturation( + S, mode, ipWater, + phaseMinHistoricalVolFraction[ipWater], + phaseMaxHistoricalVolFraction[ipWater], + m_wettingIntermediateCapillaryPressureKernelWrappers, + m_wettingCurve, + m_nonWettingCurve, + m_landParam[ipWater], + m_phaseIntermediateMinVolFraction, + m_killoughCurvatureParamCapPres, + m_jerauldParam_a, + m_jerauldParam_b, + true, // isWettingPhase + precomputedScrt_water, + precomputedDenomF_water, + precomputedShy_water); + + real64 residual = pc_computed - phaseCapPressure[ipWater]; + + if (LvArray::math::abs(residual) < tol) { + break; + } + + // Compute derivative dPc/dS (approximate using finite difference if needed) + // For simplicity, use the derivative from the table evaluation + // In a more sophisticated implementation, we could compute the analytical derivative + real64 const dS = 1e-6; + real64 const S_pert = LvArray::math::min(S + dS, maxS); + real64 const pc_pert = this->computeCapillaryPressureForSaturation( + S_pert, mode, ipWater, + phaseMinHistoricalVolFraction[ipWater], + phaseMaxHistoricalVolFraction[ipWater], + m_wettingIntermediateCapillaryPressureKernelWrappers, + m_wettingCurve, + m_nonWettingCurve, + m_landParam[ipWater], + m_phaseIntermediateMinVolFraction, + m_killoughCurvatureParamCapPres, + m_jerauldParam_a, + m_jerauldParam_b, + true, // isWettingPhase + precomputedScrt_water, + precomputedDenomF_water, + precomputedShy_water); + + real64 const dpc_dS = (pc_pert - pc_computed) / dS; + + // Avoid division by zero + if (LvArray::math::abs(dpc_dS) > 1e-12) { + S = S - residual / dpc_dS; + // Clamp to valid range + S = LvArray::math::max(S, minS); + S = LvArray::math::min(S, maxS); + } else { + // If derivative is zero, try bisection or use a small step + S = S - residual * 1e-6; // Small fixed step + S = LvArray::math::max(S, minS); + S = LvArray::math::min(S, maxS); + } + } + + phaseVolFraction[ipWater] = S; + phaseVolFraction[ipOil] = 1.0 - S - phaseVolFraction[ipGas]; + + // Compute derivative at final S + real64 dpc_dS_final = 0.0; + if (mode == fields::cappres::ModeIndexType::DRAINAGE || mode == fields::cappres::ModeIndexType::IMBIBITION) { + integer const arrayIndex = (mode == fields::cappres::ModeIndexType::DRAINAGE) ? fields::cappres::ModeIndexType::DRAINAGE : fields::cappres::ModeIndexType::IMBIBITION; + m_wettingIntermediateCapillaryPressureKernelWrappers[arrayIndex].compute(&S, &dpc_dS_final); + } + dPhaseCapPressure_dPhaseVolFrac[ipWater][ipWater] = dpc_dS_final; + } + + // 2. Invert non-wetting phase (gas-oil capillary pressure) + if (ipGas >= 0 && LvArray::math::abs(phaseCapPressure[ipGas]) > pcEpsilon) { + // Note: For non-wetting phase, the capillary pressure is typically negative + // and the relationship may be inverted (increasing Pc with decreasing S) + real64 S_guess = phaseMaxHistoricalVolFraction[ipGas]; + if (S_guess <= phaseMinHistoricalVolFraction[ipGas] || S_guess < minS || S_guess > maxS) { + real64 const Smin = m_nonWettingCurve.imbibitionExtremaPhaseVolFraction; + real64 const Smax = m_nonWettingCurve.drainageExtremaPhaseVolFraction; + S_guess = 0.5 * (Smin + Smax); + S_guess = LvArray::math::max(S_guess, minS); + S_guess = LvArray::math::min(S_guess, maxS); + } + + // Precompute fixed parameters for scanning curves (these don't change during Newton-Raphson) + real64 precomputedScrt_gas = -1.0; + real64 precomputedDenomF_gas = 0.0; + real64 precomputedShy_gas = -1.0; + + // Only precompute for scanning curves (DRAINAGE_TO_IMBIBITION or IMBIBITION_TO_DRAINAGE) + if (mode == fields::cappres::ModeIndexType::DRAINAGE_TO_IMBIBITION || + mode == fields::cappres::ModeIndexType::IMBIBITION_TO_DRAINAGE) { + real64 const Smax = m_nonWettingCurve.oppositeBoundPhaseVolFraction; + precomputedShy_gas = (phaseMaxHistoricalVolFraction[ipGas] < Smax) ? + phaseMaxHistoricalVolFraction[ipGas] : Smax; + real64 const E = m_killoughCurvatureParamCapPres; + + if (mode == fields::cappres::ModeIndexType::DRAINAGE_TO_IMBIBITION) { + // Precomputed values should be provided by caller - skip computation here + // to avoid calling computeTrappedCriticalPhaseVolFraction inside local_solver + precomputedScrt_gas = -1.0; // Indicates not precomputed + precomputedDenomF_gas = 0.0; + } + else if (mode == fields::cappres::ModeIndexType::IMBIBITION_TO_DRAINAGE) { + // Precomputed values should be provided by caller - skip computation here + // to avoid calling computeTrappedCriticalPhaseVolFraction inside local_solver + precomputedScrt_gas = -1.0; // Indicates not precomputed + precomputedDenomF_gas = 0.0; + } + } + + real64 S = S_guess; + for (integer iter = 0; iter < maxIter; ++iter) { + real64 pc_computed = this->computeCapillaryPressureForSaturation( + S, mode, ipGas, + phaseMinHistoricalVolFraction[ipGas], + phaseMaxHistoricalVolFraction[ipGas], + m_nonWettingIntermediateCapillaryPressureKernelWrappers, + m_wettingCurve, + m_nonWettingCurve, + m_landParam[ipGas], + m_phaseIntermediateMinVolFraction, + m_killoughCurvatureParamCapPres, + m_jerauldParam_a, + m_jerauldParam_b, + false, // isWettingPhase = false + precomputedScrt_gas, + precomputedDenomF_gas, + precomputedShy_gas); + + // For non-wetting phase, capillary pressure is typically multiplied by -1 + // Check which sign to use based on the input + real64 residual = pc_computed - phaseCapPressure[ipGas]; + + if (LvArray::math::abs(residual) < tol) { + break; + } + + real64 const dS = 1e-6; + real64 const S_pert = LvArray::math::min(S + dS, maxS); + real64 const pc_pert = this->computeCapillaryPressureForSaturation( + S_pert, mode, ipGas, + phaseMinHistoricalVolFraction[ipGas], + phaseMaxHistoricalVolFraction[ipGas], + m_nonWettingIntermediateCapillaryPressureKernelWrappers, + m_wettingCurve, + m_nonWettingCurve, + m_landParam[ipGas], + m_phaseIntermediateMinVolFraction, + m_killoughCurvatureParamCapPres, + m_jerauldParam_a, + m_jerauldParam_b, + false, // isWettingPhase = false + precomputedScrt_gas, + precomputedDenomF_gas, + precomputedShy_gas); + + real64 const dpc_dS = (pc_pert - pc_computed) / dS; + + if (LvArray::math::abs(dpc_dS) > 1e-12) { + S = S - residual / dpc_dS; + S = LvArray::math::max(S, minS); + S = LvArray::math::min(S, maxS); + } else { + S = S - residual * 1e-6; + S = LvArray::math::max(S, minS); + S = LvArray::math::min(S, maxS); + } + } + + phaseVolFraction[ipGas] = S; + + // Update oil phase (ensure sum = 1) + if (ipWater >= 0 && ipOil >= 0) { + phaseVolFraction[ipOil] = 1.0 - phaseVolFraction[ipWater] - phaseVolFraction[ipGas]; + phaseVolFraction[ipOil] = LvArray::math::max(phaseVolFraction[ipOil], 0.0); + phaseVolFraction[ipOil] = LvArray::math::min(phaseVolFraction[ipOil], 1.0); + } + + // Compute derivative at final S + real64 dpc_dS_final = 0.0; + if (mode == fields::cappres::ModeIndexType::DRAINAGE || mode == fields::cappres::ModeIndexType::IMBIBITION) { + integer const arrayIndex = (mode == fields::cappres::ModeIndexType::DRAINAGE) ? fields::cappres::ModeIndexType::DRAINAGE : fields::cappres::ModeIndexType::IMBIBITION; + m_nonWettingIntermediateCapillaryPressureKernelWrappers[arrayIndex].compute(&S, &dpc_dS_final); + } + dPhaseCapPressure_dPhaseVolFrac[ipGas][ipGas] = dpc_dS_final; + } + } + else if (ipWater < 0) { + // Two-phase: oil-gas (non-wetting phase) + // Similar to above but simpler + constexpr real64 pcEpsilon = 1e-10; + if (ipGas >= 0 && LvArray::math::abs(phaseCapPressure[ipGas]) > pcEpsilon) { + real64 S_guess = phaseMaxHistoricalVolFraction[ipGas]; + if (S_guess < minS || S_guess > maxS) { + S_guess = 0.5; + } + + // Precompute fixed parameters for scanning curves (these don't change during Newton-Raphson) + real64 precomputedScrt_gas = -1.0; + real64 precomputedDenomF_gas = 0.0; + real64 precomputedShy_gas = -1.0; + + // Only precompute for scanning curves (DRAINAGE_TO_IMBIBITION or IMBIBITION_TO_DRAINAGE) + if (mode == fields::cappres::ModeIndexType::DRAINAGE_TO_IMBIBITION || + mode == fields::cappres::ModeIndexType::IMBIBITION_TO_DRAINAGE) { + real64 const Smax = m_nonWettingCurve.oppositeBoundPhaseVolFraction; + precomputedShy_gas = (phaseMaxHistoricalVolFraction[ipGas] < Smax) ? + phaseMaxHistoricalVolFraction[ipGas] : Smax; + real64 const E = m_killoughCurvatureParamCapPres; + + if (mode == fields::cappres::ModeIndexType::DRAINAGE_TO_IMBIBITION) { + // Precomputed values should be provided by caller - skip computation here + // to avoid calling computeTrappedCriticalPhaseVolFraction inside local_solver + precomputedScrt_gas = -1.0; // Indicates not precomputed + precomputedDenomF_gas = 0.0; + } + else if (mode == fields::cappres::ModeIndexType::IMBIBITION_TO_DRAINAGE) { + // Precomputed values should be provided by caller - skip computation here + // to avoid calling computeTrappedCriticalPhaseVolFraction inside local_solver + precomputedScrt_gas = -1.0; // Indicates not precomputed + precomputedDenomF_gas = 0.0; + } + } + + real64 S = S_guess; + for (integer iter = 0; iter < maxIter; ++iter) { + real64 pc_computed = this->computeCapillaryPressureForSaturation( + S, mode, ipGas, + phaseMinHistoricalVolFraction[ipGas], + phaseMaxHistoricalVolFraction[ipGas], + m_wettingNonWettingCapillaryPressureKernelWrappers, + m_wettingCurve, + m_nonWettingCurve, + m_landParam[ipGas], + m_phaseIntermediateMinVolFraction, + m_killoughCurvatureParamCapPres, + m_jerauldParam_a, + m_jerauldParam_b, + false, // isWettingPhase = false + precomputedScrt_gas, + precomputedDenomF_gas, + precomputedShy_gas); + + real64 residual = pc_computed - phaseCapPressure[ipGas]; + + if (LvArray::math::abs(residual) < tol) { + break; + } + + real64 const dS = 1e-6; + real64 const S_pert = LvArray::math::min(S + dS, maxS); + real64 const pc_pert = this->computeCapillaryPressureForSaturation( + S_pert, mode, ipGas, + phaseMinHistoricalVolFraction[ipGas], + phaseMaxHistoricalVolFraction[ipGas], + m_wettingNonWettingCapillaryPressureKernelWrappers, + m_wettingCurve, + m_nonWettingCurve, + m_landParam[ipGas], + m_phaseIntermediateMinVolFraction, + m_killoughCurvatureParamCapPres, + m_jerauldParam_a, + m_jerauldParam_b, + false, // isWettingPhase = false + precomputedScrt_gas, + precomputedDenomF_gas, + precomputedShy_gas); + + real64 const dpc_dS = (pc_pert - pc_computed) / dS; + + if (LvArray::math::abs(dpc_dS) > 1e-12) { + S = S - residual / dpc_dS; + S = LvArray::math::max(S, minS); + S = LvArray::math::min(S, maxS); + } else { + S = S - residual * 1e-6; + S = LvArray::math::max(S, minS); + S = LvArray::math::min(S, maxS); + } + } + + phaseVolFraction[ipGas] = S; + if (ipOil >= 0) { + phaseVolFraction[ipOil] = 1.0 - S; + } + } + } + else { + // Two-phase: water-oil or water-gas (wetting phase) + constexpr real64 pcEpsilon = 1e-10; + if (ipWater >= 0 && LvArray::math::abs(phaseCapPressure[ipWater]) > pcEpsilon) { + real64 S_guess = phaseMaxHistoricalVolFraction[ipWater]; + if (S_guess < minS || S_guess > maxS) { + real64 const Smin = m_wettingCurve.oppositeBoundPhaseVolFraction; + real64 const Smax = m_wettingCurve.drainageExtremaPhaseVolFraction; + S_guess = 0.5 * (Smin + Smax); + S_guess = LvArray::math::max(S_guess, minS); + S_guess = LvArray::math::min(S_guess, maxS); + } + + // Precompute fixed parameters for scanning curves (these don't change during Newton-Raphson) + real64 precomputedScrt_water = -1.0; + real64 precomputedDenomF_water = 0.0; + real64 precomputedShy_water = -1.0; + + // Only precompute for scanning curves (DRAINAGE_TO_IMBIBITION or IMBIBITION_TO_DRAINAGE) + if (mode == fields::cappres::ModeIndexType::DRAINAGE_TO_IMBIBITION || + mode == fields::cappres::ModeIndexType::IMBIBITION_TO_DRAINAGE) { + real64 const Smin = m_wettingCurve.oppositeBoundPhaseVolFraction; + precomputedShy_water = (phaseMinHistoricalVolFraction[ipWater] > Smin) ? + phaseMinHistoricalVolFraction[ipWater] : Smin; + real64 const E = m_killoughCurvatureParamCapPres; + + if (mode == fields::cappres::ModeIndexType::DRAINAGE_TO_IMBIBITION) { + // Precomputed values should be provided by caller - skip computation here + // to avoid calling computeTrappedCriticalPhaseVolFraction inside local_solver + precomputedScrt_water = -1.0; // Indicates not precomputed + precomputedDenomF_water = 0.0; + } + else if (mode == fields::cappres::ModeIndexType::IMBIBITION_TO_DRAINAGE) { + // Precomputed values should be provided by caller - skip computation here + // to avoid calling computeTrappedCriticalPhaseVolFraction inside local_solver + precomputedScrt_water = -1.0; // Indicates not precomputed + precomputedDenomF_water = 0.0; + } + } + + real64 S = S_guess; + for (integer iter = 0; iter < maxIter; ++iter) { + real64 pc_computed = this->computeCapillaryPressureForSaturation( + S, mode, ipWater, + phaseMinHistoricalVolFraction[ipWater], + phaseMaxHistoricalVolFraction[ipWater], + m_wettingNonWettingCapillaryPressureKernelWrappers, + m_wettingCurve, + m_nonWettingCurve, + m_landParam[ipWater], + m_phaseIntermediateMinVolFraction, + m_killoughCurvatureParamCapPres, + m_jerauldParam_a, + m_jerauldParam_b, + true, // isWettingPhase + precomputedScrt_water, + precomputedDenomF_water, + precomputedShy_water); + + real64 residual = pc_computed - phaseCapPressure[ipWater]; + + if (LvArray::math::abs(residual) < tol) { + break; + } + + real64 const dS = 1e-6; + real64 const S_pert = LvArray::math::min(S + dS, maxS); + real64 const pc_pert = this->computeCapillaryPressureForSaturation( + S_pert, mode, ipWater, + phaseMinHistoricalVolFraction[ipWater], + phaseMaxHistoricalVolFraction[ipWater], + m_wettingNonWettingCapillaryPressureKernelWrappers, + m_wettingCurve, + m_nonWettingCurve, + m_landParam[ipWater], + m_phaseIntermediateMinVolFraction, + m_killoughCurvatureParamCapPres, + m_jerauldParam_a, + m_jerauldParam_b, + true, // isWettingPhase + precomputedScrt_water, + precomputedDenomF_water, + precomputedShy_water); + + real64 const dpc_dS = (pc_pert - pc_computed) / dS; + + if (LvArray::math::abs(dpc_dS) > 1e-12) { + S = S - residual / dpc_dS; + S = LvArray::math::max(S, minS); + S = LvArray::math::min(S, maxS); + } else { + S = S - residual * 1e-6; + S = LvArray::math::max(S, minS); + S = LvArray::math::min(S, maxS); + } + } + + phaseVolFraction[ipWater] = S; + // Set non-wetting phase + if (ipGas >= 0) { + phaseVolFraction[ipGas] = 1.0 - S; + } else if (ipOil >= 0) { + phaseVolFraction[ipOil] = 1.0 - S; + } + } + } + } + +/// kernel creation + + TableCapillaryPressureHysteresis::KernelWrapper + TableCapillaryPressureHysteresis::createKernelWrapper() { + + // we want to make sure that the wrappers are always up-to-date, so we recreate them everytime + createAllTableKernelWrappers(); + + // Validate that the arrays are properly populated + integer const numPhases = m_phaseNames.size(); + if (numPhases == 2) { + GEOS_THROW_IF(m_wettingNonWettingCapillaryPressureKernelWrappers.size() != 2, + GEOS_FMT("{}: Expected 2 kernel wrappers for two-phase flow, but got {}. " + "This usually means createAllTableKernelWrappers() failed to populate the arrays. " + "Check that table functions '{}' and '{}' exist and are properly defined.", + getFullName(), + m_wettingNonWettingCapillaryPressureKernelWrappers.size(), + m_drainageWettingNonWettingCapPresTableName, + m_imbibitionWettingNonWettingCapPresTableName.empty() ? m_drainageWettingNonWettingCapPresTableName : m_imbibitionWettingNonWettingCapPresTableName), + InputError); + } else if (numPhases == 3) { + GEOS_THROW_IF(m_wettingIntermediateCapillaryPressureKernelWrappers.size() != 2, + GEOS_FMT("{}: Expected 2 wetting-intermediate kernel wrappers for three-phase flow, but got {}", + getFullName(), + m_wettingIntermediateCapillaryPressureKernelWrappers.size()), + InputError); + GEOS_THROW_IF(m_nonWettingIntermediateCapillaryPressureKernelWrappers.size() != 2, + GEOS_FMT("{}: Expected 2 non-wetting-intermediate kernel wrappers for three-phase flow, but got {}", + getFullName(), + m_nonWettingIntermediateCapillaryPressureKernelWrappers.size()), + InputError); + } + + // Validate that m_phaseHasHysteresis is properly initialized + GEOS_THROW_IF(m_phaseHasHysteresis.size() != 2, + GEOS_FMT("{}: m_phaseHasHysteresis must have size 2, but got {}", + getFullName(), + m_phaseHasHysteresis.size()), + InputError); + + // Validate that the historical volume fraction arrays have been resized + // These arrays should be resized by resizeFields() before the KernelWrapper is used + // If they're empty, it means resizeFields() hasn't been called yet + GEOS_THROW_IF(m_phaseMaxHistoricalVolFraction.size(0) == 0 || m_phaseMaxHistoricalVolFraction.size(1) == 0, + GEOS_FMT("{}: phaseMaxHistoricalVolFraction array has not been resized (size=[{}, {}]). " + "This usually means resizeFields() has not been called yet. " + "The arrays must be resized before the KernelWrapper can be used.", + getFullName(), + m_phaseMaxHistoricalVolFraction.size(0), + m_phaseMaxHistoricalVolFraction.size(1)), + InputError); + GEOS_THROW_IF(m_phaseMinHistoricalVolFraction.size(0) == 0 || m_phaseMinHistoricalVolFraction.size(1) == 0, + GEOS_FMT("{}: phaseMinHistoricalVolFraction array has not been resized (size=[{}, {}]). " + "This usually means resizeFields() has not been called yet. " + "The arrays must be resized before the KernelWrapper can be used.", + getFullName(), + m_phaseMinHistoricalVolFraction.size(0), + m_phaseMinHistoricalVolFraction.size(1)), + InputError); + + // then we create the actual TableRelativePermeabilityHysteresis::KernelWrapper + return KernelWrapper(m_wettingNonWettingCapillaryPressureKernelWrappers, + m_wettingIntermediateCapillaryPressureKernelWrappers, + m_nonWettingIntermediateCapillaryPressureKernelWrappers, + m_phaseHasHysteresis, + m_landParam, + m_jerauldParam_a, + m_jerauldParam_b, + m_killoughCurvatureParamCapPres, + m_phaseIntermediateMinVolFraction, + m_wettingCurve, + m_nonWettingCurve, + m_phaseMinHistoricalVolFraction, + m_phaseMaxHistoricalVolFraction, + m_phaseTypes, + m_phaseOrder, + m_mode, + m_phaseTrappedVolFrac, + m_phaseCapPressure, + m_dPhaseCapPressure_dPhaseVolFrac); + } + + void TableCapillaryPressureHysteresis::createAllTableKernelWrappers() { + using TPP = ThreePhasePairPhaseType; + + FunctionManager const &functionManager = FunctionManager::getInstance(); + + integer const numPhases = m_phaseNames.size(); + + // Ensure m_phaseHasHysteresis is initialized before accessing it + // This can happen if createKernelWrapper is called before postProcessInput + if (m_phaseHasHysteresis.size() == 0) { + m_phaseHasHysteresis.resize(2); + if (numPhases == 2) { + m_phaseHasHysteresis[TPP::INTERMEDIATE_WETTING] = + (m_imbibitionWettingNonWettingCapPresTableName.empty() || + m_imbibitionWettingNonWettingCapPresTableName == m_drainageWettingNonWettingCapPresTableName) + ? 0 : 1; + m_phaseHasHysteresis[TPP::INTERMEDIATE_NONWETTING] = m_phaseHasHysteresis[TPP::INTERMEDIATE_WETTING]; + } else if (numPhases == 3) { + m_phaseHasHysteresis[TPP::INTERMEDIATE_WETTING] = + (m_imbibitionWettingIntermediateCapPresTableName.empty() || + m_imbibitionWettingIntermediateCapPresTableName == m_drainageWettingIntermediateCapPresTableName) + ? 0 : 1; + m_phaseHasHysteresis[TPP::INTERMEDIATE_NONWETTING] = + (m_imbibitionNonWettingIntermediateCapPresTableName.empty() || + m_imbibitionNonWettingIntermediateCapPresTableName == m_drainageNonWettingIntermediateCapPresTableName) + ? 0 : 1; + } + } + + // we want to make sure that the wrappers are always up-to-date, so we recreate them everytime + + m_wettingNonWettingCapillaryPressureKernelWrappers.clear(); + m_wettingIntermediateCapillaryPressureKernelWrappers.clear(); + m_nonWettingIntermediateCapillaryPressureKernelWrappers.clear(); + + if (numPhases == 2) { + GEOS_THROW_IF(m_drainageWettingNonWettingCapPresTableName.empty(), + GEOS_FMT("{}: drainageWettingNonWettingCapPressureTableName is empty for two-phase flow", + getFullName()), + InputError); + + GEOS_THROW_IF(!functionManager.hasGroup(m_drainageWettingNonWettingCapPresTableName), + GEOS_FMT("{}: the table function named '{}' could not be found", + getFullName(), + m_drainageWettingNonWettingCapPresTableName), + InputError); + TableFunction const &drainageCapPresTable = functionManager.getGroup( + m_drainageWettingNonWettingCapPresTableName); + m_wettingNonWettingCapillaryPressureKernelWrappers.emplace_back( + drainageCapPresTable.createKernelWrapper()); + + string const &imbibitionTableName = m_phaseHasHysteresis[TPP::INTERMEDIATE_WETTING] + ? m_imbibitionWettingNonWettingCapPresTableName + : m_drainageWettingNonWettingCapPresTableName; + GEOS_THROW_IF(imbibitionTableName.empty(), + GEOS_FMT("{}: imbibition table name is empty for two-phase flow", + getFullName()), + InputError); + GEOS_THROW_IF(!functionManager.hasGroup(imbibitionTableName), + GEOS_FMT("{}: the table function named '{}' could not be found", + getFullName(), + imbibitionTableName), + InputError); + TableFunction const &imbibitionWettingCapPresTable = functionManager.getGroup( + imbibitionTableName); + m_wettingNonWettingCapillaryPressureKernelWrappers.emplace_back( + imbibitionWettingCapPresTable.createKernelWrapper()); + + GEOS_THROW_IF(m_wettingNonWettingCapillaryPressureKernelWrappers.size() != 2, + GEOS_FMT("{}: Expected 2 kernel wrappers after creation, but got {}", + getFullName(), + m_wettingNonWettingCapillaryPressureKernelWrappers.size()), + InputError); + + } else if (numPhases == 3) { + TableFunction const &drainageWICapPres = functionManager.getGroup( + m_drainageWettingIntermediateCapPresTableName); + m_wettingIntermediateCapillaryPressureKernelWrappers.emplace_back( + drainageWICapPres.createKernelWrapper()); + + TableFunction const &drainageNWICapPres = functionManager.getGroup( + m_drainageNonWettingIntermediateCapPresTableName); + m_nonWettingIntermediateCapillaryPressureKernelWrappers.emplace_back( + drainageNWICapPres.createKernelWrapper()); + + TableFunction const &imbibitionWICapPres = m_phaseHasHysteresis[TPP::INTERMEDIATE_WETTING] + ? functionManager.getGroup( + m_imbibitionWettingIntermediateCapPresTableName) + : functionManager.getGroup( + m_drainageWettingIntermediateCapPresTableName); + m_wettingIntermediateCapillaryPressureKernelWrappers.emplace_back( + imbibitionWICapPres.createKernelWrapper()); + + TableFunction const &imbibitionNWICapPres = m_phaseHasHysteresis[TPP::INTERMEDIATE_NONWETTING] + ? functionManager.getGroup( + m_imbibitionNonWettingIntermediateCapPresTableName) + : functionManager.getGroup( + m_drainageNonWettingIntermediateCapPresTableName); + m_nonWettingIntermediateCapillaryPressureKernelWrappers.emplace_back( + imbibitionNWICapPres.createKernelWrapper()); + } + + } + +///kernel ctor + TableCapillaryPressureHysteresis::KernelWrapper::KernelWrapper( + arrayView1d const &wettingNonWettingCapillaryPressureKernelWrappers, + arrayView1d const &wettingIntermediateCapillaryPressureKernelWrappers, + arrayView1d const &nonWettingIntermediateCapillaryPressureKernelWrappers, + const arrayView1d &phaseHasHysteresis, + const arrayView1d &landParam, + const real64 & jerauldParam_a, + const real64 & jerauldParam_b, + const real64 & killoughCurvaturePcParam, + const geos::real64 &phaseIntermediateMinVolFraction, + const KilloughHysteresis::HysteresisCurve &wettingCurve, + const KilloughHysteresis::HysteresisCurve &nonWettingCurve, + const arrayView2d &phaseMinHistoricalVolFraction, + const arrayView2d &phaseMaxHistoricalVolFraction, + arrayView1d const &phaseTypes, + arrayView1d const &phaseOrder, + arrayView1d const &mode, + arrayView3d const &phaseTrapped, + const arrayView3d &phaseCapPressure, + const arrayView4d &dPhaseCapPressure_dPhaseVolFrac) + : + CapillaryPressureBaseUpdate(phaseTypes, + phaseOrder, + phaseTrapped, + phaseCapPressure, + dPhaseCapPressure_dPhaseVolFrac), + m_wettingNonWettingCapillaryPressureKernelWrappers(wettingNonWettingCapillaryPressureKernelWrappers), + m_wettingIntermediateCapillaryPressureKernelWrappers( + wettingIntermediateCapillaryPressureKernelWrappers), + m_nonWettingIntermediateCapillaryPressureKernelWrappers( + nonWettingIntermediateCapillaryPressureKernelWrappers), + m_phaseHasHysteresis(phaseHasHysteresis), + m_landParam(landParam), + m_jerauldParam_a(jerauldParam_a), + m_jerauldParam_b(jerauldParam_b), + m_killoughCurvatureParamCapPres(killoughCurvaturePcParam), + m_phaseIntermediateMinVolFraction(phaseIntermediateMinVolFraction), + m_wettingCurve(wettingCurve), + m_nonWettingCurve(nonWettingCurve), + m_phaseMinHistoricalVolFraction(phaseMinHistoricalVolFraction), + m_phaseMaxHistoricalVolFraction(phaseMaxHistoricalVolFraction), + m_mode(mode) {} + + + REGISTER_CATALOG_ENTRY(ConstitutiveBase, TableCapillaryPressureHysteresis, std::string const &, Group * const) + + } +} // geos diff --git a/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressureHysteresis.hpp b/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressureHysteresis.hpp new file mode 100644 index 00000000000..e0e1098245f --- /dev/null +++ b/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressureHysteresis.hpp @@ -0,0 +1,597 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2018-2020 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2020 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2018-2020 TotalEnergies + * Copyright (c) 2019- GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + + +#ifndef GEOS_CONSTITUTIVE_TABLECAPILLARYPRESSUREHYSTERESIS_HPP +#define GEOS_CONSTITUTIVE_TABLECAPILLARYPRESSUREHYSTERESIS_HPP + +#include "constitutive/capillaryPressure/CapillaryPressureBase.hpp" +#include "functions/TableFunction.hpp" + +#include "constitutive/KilloughHysteresis.hpp" +#include "CapillaryPressureFields.hpp" + +namespace geos { + + + namespace constitutive { + + class TableCapillaryPressureHysteresis : public CapillaryPressureBase { +// /// useful constant +// static constexpr real64 CAP_INF = 1e9; +//// std::numeric_limits< real64 >::max(); +// static constexpr real64 CAP_INF_DERIV = 1e9; +//// std::numeric_limits< real64 >::max(); + + typedef fields::cappres::ModeIndexType ModeIndexType; + + public: + + /// order of the phase properties for three-phase flow + struct ThreePhasePairPhaseType { + enum : integer { + INTERMEDIATE_WETTING = 0, ///< index for intermediate-wetting + INTERMEDIATE_NONWETTING = 1 ///< index for intermediate-non-wetting + }; + }; + + + TableCapillaryPressureHysteresis(std::string const &name, + dataRepository::Group *const parent); + + static std::string catalogName() { return "TableCapillaryPressureHysteresis"; } + + virtual string getCatalogName() const override { return catalogName(); } + + ///Kernel + class KernelWrapper final : public CapillaryPressureBaseUpdate { + public: + + KernelWrapper( + arrayView1d const &wettingNonWettingCapillaryPressureKernelWrappers, + arrayView1d const &wettingIntermediateCapillaryPressureKernelWrappers, + arrayView1d const &nonWettingIntermediateCapillaryPressureKernelWrappers, + arrayView1d const &phaseHasHysteresis, + arrayView1d const &landParam, + real64 const &jerauldParam_a, + real64 const &jerauldParam_b, + real64 const &killoughCurvaturePcParameter, + real64 const &phaseIntermediateMinVolFraction, + KilloughHysteresis::HysteresisCurve const &wettingCurve, + KilloughHysteresis::HysteresisCurve const &nonWettingCurve, + arrayView2d const &phaseMinHistoricalVolFraction, + arrayView2d const &phaseMaxHistoricalVolFraction, + arrayView1d const &phaseTypes, + arrayView1d const &phaseOrder, + arrayView1d const &mode, + arrayView3d const &phaseTrappedVolFrac, + arrayView3d const &phaseCapPressure, + arrayView4d const &dPhaseCapPressure_dPhaseVolFrac); + + //actual workers + GEOS_HOST_DEVICE + void computeBoundCapillaryPressure(TableFunction::KernelWrapper const &drainageCapPressureWrapper, + real64 const &phaseVolFraction, + real64 &phaseCapPressure, + real64 &dPhaseCapPressure_dPhaseVolFrac) const; + + GEOS_HOST_DEVICE + void + computeImbibitionWettingCapillaryPressure( + const arrayView1d &wettingKernelWapper, + const KilloughHysteresis::HysteresisCurve &wettingCurve, + const KilloughHysteresis::HysteresisCurve &nonWettingCurve, + const geos::real64 &landParam, + const geos::real64 &phaseVolFraction, + const geos::real64 &phaseMinHistoricalVolFraction, + geos::real64 &phaseTrappedVolFrac, + geos::real64 &phaseCapPressure, + geos::real64 &dPhaseCapPressure_dPhaseVolFrac, + const ModeIndexType &mode) const; + + //two phase flow overload + GEOS_HOST_DEVICE + void + computeImbibitionWettingCapillaryPressure( + const arrayView1d &wettingKernelWapper, + const KilloughHysteresis::HysteresisCurve &wettingCurve, + const geos::real64 &landParam, + const geos::real64 &phaseVolFraction, + const geos::real64 &phaseMinHistoricalVolFraction, + geos::real64 &phaseTrappedVolFrac, + geos::real64 &phaseCapPressure, + geos::real64 &dPhaseCapPressure_dPhaseVolFrac, + const ModeIndexType &mode) const; + + GEOS_HOST_DEVICE + void + computeImbibitionNonWettingCapillaryPressure( + const arrayView1d &nonWettingKernelWrapper, + const KilloughHysteresis::HysteresisCurve &nonWettingCurve, + const KilloughHysteresis::HysteresisCurve &wettingCurve, + const geos::real64 &landParam, + const geos::real64 &phaseVolFraction, + const geos::real64 &phaseMaxHistoricalVolFraction, + geos::real64 &phaseTrappedVolFrac, + geos::real64 &phaseCapPressure, + geos::real64 &dPhaseCapPressure_dPhaseVolFrac, + const ModeIndexType &mode) const; + + //2phase flow overload + GEOS_HOST_DEVICE + void + computeImbibitionNonWettingCapillaryPressure( + const arrayView1d &nonWettingKernelWrapper, + const KilloughHysteresis::HysteresisCurve &nonWettingCurve, + const geos::real64 &landParam, + const geos::real64 &phaseVolFraction, + const geos::real64 &phaseMaxHistoricalVolFraction, + geos::real64 &phaseTrappedVolFrac, + geos::real64 &phaseCapPressure, + geos::real64 &dPhaseCapPressure_dPhaseVolFrac, + const ModeIndexType &mode) const; + + + + //wrapper call wrt number of phase + GEOS_HOST_DEVICE + void computeTwoPhaseWetting(integer const ipWetting, + integer const ipNonWetting, + arraySlice1d const &phaseVolFraction, + arraySlice1d const &phaseMaxHistoricalVolFraction, + arraySlice1d const &phaseMinHistoricalVolFraction, + arraySlice1d const &phaseTrappedVolFrac, + arraySlice1d const &phaseCapPressure, + arraySlice2d const &dPhaseCapPressure_dPhaseVolFrac, + ModeIndexType &mode) const; + + + GEOS_HOST_DEVICE + void computeTwoPhaseNonWetting(integer const ipWetting, + integer const ipNonWetting, + arraySlice1d const &phaseVolFraction, + arraySlice1d const &phaseMaxHistoricalVolFraction, + arraySlice1d const &phaseMinHistoricalVolFraction, + arraySlice1d const &phaseTrappedVolFrac, + arraySlice1d const &phaseCapPressure, + arraySlice2d const &dPhaseCapPressure_dPhaseVolFrac, + ModeIndexType &mode) const; + + GEOS_HOST_DEVICE + void computeThreePhase(integer const ipWetting, + integer const ipInter, + integer const ipNonWetting, + arraySlice1d const &phaseVolFraction, + arraySlice1d const &phaseMaxHistoricalVolFraction, + arraySlice1d const &phaseMinHistoricalVolFraction, + arraySlice1d const &phaseTrappedVolFrac, + arraySlice1d const &phaseCapPressure, + arraySlice2d const &dPhaseCapPressure_dPhaseVolFrac, + ModeIndexType &mode) const; + + //uppermost call-wrappers + // Standard 3-argument compute method for compatibility with InverseCapillaryPressure + GEOS_HOST_DEVICE + void compute(arraySlice1d const &phaseVolFraction, + arraySlice1d const &phaseCapPressure, + arraySlice2d const &dPhaseCapPressure_dPhaseVolFrac) const; + + GEOS_HOST_DEVICE + virtual void compute(arraySlice1d const &phaseVolFraction, + arraySlice1d const &phaseMaxHistoricalVolFraction, + arraySlice1d const &phaseMinHistoricalVolFraction, + arraySlice1d const &phaseTrappedVolFrac, + arraySlice1d const &phaseCapPressure, + arraySlice2d const &dPhaseCapPressure_dPhaseVolFrac, + ModeIndexType &mode) const; + + GEOS_HOST_DEVICE + virtual void update(localIndex const k, + localIndex const q, + arraySlice1d const &phaseVolFraction) const override; + + /** + * @brief Compute phase volume fraction from capillary pressure (inverse operation). + * @param phaseVolFraction [out] Computed phase volume fractions + * @param phaseMaxHistoricalVolFraction [in] Maximum historical phase volume fractions + * @param phaseMinHistoricalVolFraction [in] Minimum historical phase volume fractions + * @param phaseTrappedVolFrac [in] Trapped phase volume fractions + * @param phaseCapPressure [in] Target capillary pressures (input) + * @param dPhaseCapPressure_dPhaseVolFrac [out] Derivatives of capillary pressure w.r.t. phase volume fraction + * @param mode [in] Hysteresis mode (DRAINAGE, IMBIBITION, DRAINAGE_TO_IMBIBITION, IMBIBITION_TO_DRAINAGE) + * + * Uses Newton-Raphson iteration to invert the capillary pressure function. + */ + GEOS_HOST_DEVICE + void computeInv(arraySlice1d const &phaseVolFraction, + arraySlice1d const &phaseMaxHistoricalVolFraction, + arraySlice1d const &phaseMinHistoricalVolFraction, + arraySlice1d const &phaseTrappedVolFrac, + arraySlice1d const &phaseCapPressure, + arraySlice2d const &dPhaseCapPressure_dPhaseVolFrac, + fields::cappres::ModeIndexType const &mode) const; + + private: + + /** + * @brief Helper function to compute Pc(S) for given S, mode, and historical values. + * @param S Phase volume fraction + * @param mode Hysteresis mode + * @param ipPhase Phase index + * @param phaseMinHistoricalVolFraction Minimum historical volume fraction + * @param phaseMaxHistoricalVolFraction Maximum historical volume fraction + * @param capPresKernelWrappers Capillary pressure kernel wrappers + * @param wettingCurve Wetting curve data + * @param nonWettingCurve Non-wetting curve data + * @param landParam Land parameter + * @param phaseIntermediateMinVolFraction Intermediate phase minimum volume fraction + * @param killoughCurvatureParam Killough curvature parameter + * @param jerauldParam_a Jerauld parameter a + * @param jerauldParam_b Jerauld parameter b + * @param isWettingPhase Whether this is the wetting phase + * @param precomputedScrt Precomputed trapped critical saturation (optional, use -1.0 to compute) + * @param precomputedDenomF Precomputed denominator for F calculation (optional, use 0.0 to compute) + * @param precomputedShy Precomputed historical saturation Shy (optional, use -1.0 to compute) + * @return Computed capillary pressure + * + * Used for Newton-Raphson inversion in computeInv. + * If precomputed values are provided (precomputedScrt >= 0, precomputedDenomF != 0, precomputedShy >= 0), + * they will be used instead of recomputing them. + */ + GEOS_HOST_DEVICE + real64 computeCapillaryPressureForSaturation( + real64 const S, + fields::cappres::ModeIndexType const &mode, + integer const ipPhase, + real64 const &phaseMinHistoricalVolFraction, + real64 const &phaseMaxHistoricalVolFraction, + arrayView1d const &capPresKernelWrappers, + KilloughHysteresis::HysteresisCurve const &wettingCurve, + KilloughHysteresis::HysteresisCurve const &nonWettingCurve, + real64 const &landParam, + real64 const &phaseIntermediateMinVolFraction, + real64 const &killoughCurvatureParam, + real64 const &jerauldParam_a, + real64 const &jerauldParam_b, + bool const isWettingPhase, + real64 const precomputedScrt = -1.0, + real64 const precomputedDenomF = 0.0, + real64 const precomputedShy = -1.0) const; + + static constexpr real64 flowReversalBuffer = KilloughHysteresis::flowReversalBuffer; +// ModeIndexType& m_mode; + + //2p + arrayView1d const m_wettingNonWettingCapillaryPressureKernelWrappers; + //3p + arrayView1d const m_wettingIntermediateCapillaryPressureKernelWrappers; + arrayView1d const m_nonWettingIntermediateCapillaryPressureKernelWrappers; + + ///Land Coeff + arrayView1d m_phaseHasHysteresis; + arrayView1d m_landParam; + + /// Parameter a introduced by Jerauld in the Land model + const real64 m_jerauldParam_a; + + /// Parameter b introduced by Jerauld in the Land model + const real64 m_jerauldParam_b; + + /// Curvature parameter in Killough wetting phase hysteresis (enpoints curvatures) + const real64 m_killoughCurvatureParamCapPres; + + /// needed in 3p-wetting hysteresis as we need to get the max accessible pore space + real64 const m_phaseIntermediateMinVolFraction; + + KilloughHysteresis::HysteresisCurve const m_wettingCurve; + KilloughHysteresis::HysteresisCurve const m_nonWettingCurve; + + /// Minimum historical phase volume fraction for each phase + arrayView2d m_phaseMinHistoricalVolFraction; + + /// Maximum historical phase volume fraction for each phase + arrayView2d m_phaseMaxHistoricalVolFraction; + + // Drainage / Imbibition flags cellwise + arrayView1d m_mode; + + }; + + /** + * @brief Create an update kernel wrapper. + * @return the wrapper + */ + KernelWrapper createKernelWrapper(); + + //might need it to be virtual one level higher --> from Killough/Hysteresis common class + virtual void saveConvergedPhaseVolFractionState( + arrayView2d const &phaseVolFraction) const override; + + + struct viewKeyStruct : CapillaryPressureBase::viewKeyStruct { + + + ///Land Coeff + static constexpr char const *landParameterString() { return "landParameter"; } + + ///flag + static constexpr char const *phaseHasHysteresisString() { return "phaseHasHysteresis"; } + + ///and packed curves data struct + static constexpr char const *wettingCurveString() { return "wettingCurve"; }; + + static constexpr char const *nonWettingCurveString() { return "nonWettingCurve"; }; + + + ///tables and assoc. wrappers + //2phase + static constexpr char const * + drainageWettingNonWettingCapPresTableNameString() { return "drainageWettingNonWettingCapPressureTableName"; } + + static constexpr char const * + imbibitionWettingNonWettingCapPresTableNameString() { return "imbibitionWettingNonWettingCapPressureTableName"; } + + //3phase + static constexpr char const * + drainageWettingIntermediateCapPresTableNameString() { return "drainageWettingIntermediateCapPressureTableName"; } + + static constexpr char const * + drainageNonWettingIntermediateCapPresTableNameString() { return "drainageNonWettingIntermediateCapPressureTableName"; } + + static constexpr char const * + imbibitionWettingIntermediateCapPresTableNameString() { return "imbibitionWettingIntermediateCapPressureTableName"; } + + static constexpr char const * + imbibitionNonWettingIntermediateCapPresTableNameString() { return "imbibitionNonWettingIntermediateCapPressureTableName"; } + + static constexpr char const * + wettingNonWettingCapillaryPressureKernelWrappersString() { return "wettingNonWettingCapillaryPressureKernelWrappers"; } + + static constexpr char const * + wettingIntermediateCapillaryPressureKernelWrappersString() { return "wettingIntermediateCapillaryPressureKernelWrappers"; } + + static constexpr char const * + nonWettingIntermediateCapillaryPressureKernelWrappersString() { return "nonWettingIntermediateCapillaryPressureKernelWrappers"; } + + //misc + static constexpr char const * + phaseIntermediateMinVolFractionString() { return "phaseIntermediateMinVolFraction"; } + //to decide wheter drainage/drainage to imbibition or imbibition/imbibition to drainage + }; + + + private: + virtual void postProcessInput(); + + virtual void initializePreSubGroups() override; + + void resizeFields(localIndex const size, + localIndex const numPts) override; + + + /** + * @brief Create all the table kernel wrappers needed for the simulation (for all the phases present) + */ + void createAllTableKernelWrappers(); + + /** + * @brief Compute the Land coefficient for the wetting and non-wetting phases + */ + void computeLandCoefficient(); + + ///data members + + + //TODO impl +// array1d< integer > m_tCurveOption; + + KilloughHysteresis::HysteresisCurve m_wettingCurve; + KilloughHysteresis::HysteresisCurve m_nonWettingCurve; + + ///tables + //2p + string m_drainageWettingNonWettingCapPresTableName; + string m_imbibitionWettingNonWettingCapPresTableName; + //3p + string m_drainageWettingIntermediateCapPresTableName; + string m_drainageNonWettingIntermediateCapPresTableName; + string m_imbibitionWettingIntermediateCapPresTableName; + string m_imbibitionNonWettingIntermediateCapPresTableName; + // kernel wrappers + /// Imbibition kernel wrappers for relative permeabilities in the following order: + /// 0- drainage + /// 1- imbibition (cf. struct ModeIndexType) + //2p + array1d m_wettingNonWettingCapillaryPressureKernelWrappers; + //3p + array1d m_wettingIntermediateCapillaryPressureKernelWrappers; + array1d m_nonWettingIntermediateCapillaryPressureKernelWrappers; + + + /// Flag to specify whether the phase has hysteresis or not (deduced from table input) + array1d m_phaseHasHysteresis; + + /// Trapping parameter from the Land model (typically called C) + array1d m_landParam; + + /// Parameter a introduced by Jerauld in the Land model + real64 m_jerauldParam_a; + + /// Parameter b introduced by Jerauld in the Land model + real64 m_jerauldParam_b; + + /// Curvature parameter in Killough wetting phase hysteresis (Scanning curves curvatures) + real64 m_killoughCurvatureParamCapPres; + + /// Cell-wise status imbibition, imbibitioon_to_drainage, ... etc + array1d m_mode; + + // Max historical saturations + /// Minimum historical phase volume fraction for each phase + array2d m_phaseMinHistoricalVolFraction; + + /// Maximum historical phase volume fraction for each phase + array2d m_phaseMaxHistoricalVolFraction; + + //needed in hysteresis of wetting phase + real64 m_phaseIntermediateMinVolFraction; + + }; + + // Standard 3-argument compute method for compatibility with InverseCapillaryPressure + // Uses zero/default values for historical fractions (no hysteresis in inverse computation) + GEOS_HOST_DEVICE + inline void TableCapillaryPressureHysteresis::KernelWrapper::compute( + arraySlice1d const &phaseVolFraction, + arraySlice1d const &phaseCapPressure, + arraySlice2d const &dPhaseCapPressure_dPhaseVolFrac + ) const { + // Create temporary arrays for historical fractions and trapped fraction + // Initialize to zero/default values since inverse computation doesn't use hysteresis + constexpr integer MAX_NUM_PHASES = CapillaryPressureBase::MAX_NUM_PHASES; + real64 phaseMaxHistoricalVolFraction[MAX_NUM_PHASES]{}; + real64 phaseMinHistoricalVolFraction[MAX_NUM_PHASES]{}; + real64 phaseTrappedVolFrac[MAX_NUM_PHASES]{}; + ModeIndexType mode = ModeIndexType::DRAINAGE; // Default to drainage mode + + // Create ArrayView from stack arrays, then get slices + integer const numPhases = LvArray::integerConversion< integer >( phaseVolFraction.size() ); + localIndex dims[1] = { numPhases }; + localIndex strides[1] = { 1 }; + + arraySlice1d< real64 const, compflow::USD_PHASE - 1 > const phaseMaxHistSlice( + phaseMaxHistoricalVolFraction, dims, strides ); + arraySlice1d< real64 const, compflow::USD_PHASE - 1 > const phaseMinHistSlice( + phaseMinHistoricalVolFraction, dims, strides ); + arraySlice1d< real64, cappres::USD_CAPPRES - 2 > phaseTrappedSlice( + phaseTrappedVolFrac, dims, strides ); + + // Call the full compute method + compute( phaseVolFraction, + phaseMaxHistSlice, + phaseMinHistSlice, + phaseTrappedSlice, + phaseCapPressure, + dPhaseCapPressure_dPhaseVolFrac, + mode ); + } + + GEOS_HOST_DEVICE + inline void TableCapillaryPressureHysteresis::KernelWrapper::compute( + arraySlice1d const &phaseVolFraction, + arraySlice1d const &phaseMaxHistoricalVolFraction, + arraySlice1d const &phaseMinHistoricalVolFraction, + arraySlice1d const &phaseTrappedVolFrac, + arraySlice1d const &phaseCapPressure, + arraySlice2d const &dPhaseCapPressure_dPhaseVolFrac, + ModeIndexType &mode + ) const { + // Early return if m_phaseOrder is empty or input arrays are empty + if( m_phaseOrder.size() == 0 || + phaseVolFraction.size() == 0 || + phaseCapPressure.size() == 0 ) + { + return; + } + + LvArray::forValuesInSlice(dPhaseCapPressure_dPhaseVolFrac, [](real64 &val) { val = 0.0; }); + + using PT = CapillaryPressureBase::PhaseType; + // Check bounds before accessing m_phaseOrder + integer const ipWater = ( PT::WATER < m_phaseOrder.size() ) ? m_phaseOrder[PT::WATER] : -1; + integer const ipOil = ( PT::OIL < m_phaseOrder.size() ) ? m_phaseOrder[PT::OIL] : -1; + integer const ipGas = ( PT::GAS < m_phaseOrder.size() ) ? m_phaseOrder[PT::GAS] : -1; + + if (ipWater >= 0 && ipOil >= 0 && ipGas >= 0) { + computeThreePhase(ipWater, // wetting + ipOil, // intermediate + ipGas, // non-wetting + phaseVolFraction, + phaseMaxHistoricalVolFraction, + phaseMinHistoricalVolFraction, + phaseTrappedVolFrac, + phaseCapPressure, + dPhaseCapPressure_dPhaseVolFrac, + mode); + + } else if (ipWater < 0) { + computeTwoPhaseNonWetting(ipOil, // leading + ipGas, // deduced + phaseVolFraction, + phaseMaxHistoricalVolFraction, + phaseMinHistoricalVolFraction, + phaseTrappedVolFrac, + phaseCapPressure, + dPhaseCapPressure_dPhaseVolFrac, + mode); + } else if (ipOil < 0) { + computeTwoPhaseWetting(ipWater, // leading + ipGas, // deduced + phaseVolFraction, + phaseMaxHistoricalVolFraction, + phaseMinHistoricalVolFraction, + phaseTrappedVolFrac, + phaseCapPressure, + dPhaseCapPressure_dPhaseVolFrac, + mode); + } else if (ipGas < 0) { + computeTwoPhaseWetting(ipWater, //leading + ipOil, //deduced + phaseVolFraction, + phaseMaxHistoricalVolFraction, + phaseMinHistoricalVolFraction, + phaseTrappedVolFrac, + phaseCapPressure, + dPhaseCapPressure_dPhaseVolFrac, + mode); + } + + + } + + GEOS_HOST_DEVICE + inline void TableCapillaryPressureHysteresis::KernelWrapper::update(const geos::localIndex k, + const geos::localIndex q, + const arraySlice1d &phaseVolFraction) const { + compute(phaseVolFraction, + m_phaseMaxHistoricalVolFraction[k], + m_phaseMinHistoricalVolFraction[k], + m_phaseTrappedVolFrac[k][q], + m_phaseCapPressure[k][q], + m_dPhaseCapPressure_dPhaseVolFrac[k][q], + m_mode[k]); + } + + + } //constitutive +} // geos + +#endif //GEOS_CONSTITUTIVE_TABLECAPILLARYPRESSUREHYSTERESIS_HPP diff --git a/src/coreComponents/constitutive/capillaryPressure/VanGenuchtenCapillaryPressure.cpp b/src/coreComponents/constitutive/capillaryPressure/VanGenuchtenCapillaryPressure.cpp index b324366f4f2..17a0a74e426 100644 --- a/src/coreComponents/constitutive/capillaryPressure/VanGenuchtenCapillaryPressure.cpp +++ b/src/coreComponents/constitutive/capillaryPressure/VanGenuchtenCapillaryPressure.cpp @@ -122,6 +122,7 @@ VanGenuchtenCapillaryPressure::createKernelWrapper() m_volFracScale, m_phaseTypes, m_phaseOrder, + m_phaseTrappedVolFrac, m_phaseCapPressure, m_dPhaseCapPressure_dPhaseVolFrac ); } diff --git a/src/coreComponents/constitutive/capillaryPressure/VanGenuchtenCapillaryPressure.hpp b/src/coreComponents/constitutive/capillaryPressure/VanGenuchtenCapillaryPressure.hpp index 798815cd877..35708bf62af 100644 --- a/src/coreComponents/constitutive/capillaryPressure/VanGenuchtenCapillaryPressure.hpp +++ b/src/coreComponents/constitutive/capillaryPressure/VanGenuchtenCapillaryPressure.hpp @@ -39,10 +39,12 @@ class VanGenuchtenCapillaryPressureUpdate final : public CapillaryPressureBaseUp real64 const volFracScale, arrayView1d< integer const > const & phaseTypes, arrayView1d< integer const > const & phaseOrder, + arrayView3d< geos::real64, cappres::USD_CAPPRES > const & phaseTrapped, arrayView3d< real64, cappres::USD_CAPPRES > const & phaseCapPressure, arrayView4d< real64, cappres::USD_CAPPRES_DS > const & dPhaseCapPressure_dPhaseVolFrac ) : CapillaryPressureBaseUpdate( phaseTypes, phaseOrder, + phaseTrapped, phaseCapPressure, dPhaseCapPressure_dPhaseVolFrac ), m_phaseMinVolumeFraction( phaseMinVolumeFraction ), diff --git a/src/coreComponents/constitutive/relativePermeability/BrooksCoreyBakerRelativePermeability.hpp b/src/coreComponents/constitutive/relativePermeability/BrooksCoreyBakerRelativePermeability.hpp index 476def9f455..21fdbe4a8a6 100644 --- a/src/coreComponents/constitutive/relativePermeability/BrooksCoreyBakerRelativePermeability.hpp +++ b/src/coreComponents/constitutive/relativePermeability/BrooksCoreyBakerRelativePermeability.hpp @@ -139,19 +139,17 @@ class BrooksCoreyBakerRelativePermeability : public RelativePermeabilityBase static constexpr char const * volFracScaleString() { return "volFracScale"; } }; - arrayView1d< real64 const > getPhaseMinVolumeFraction() const override { return m_phaseMinVolumeFraction; }; - real64 getWettingPhaseMinVolumeFraction() const override { integer ipWetting; - std::tie( ipWetting, std::ignore ) = wettingAndNonWettingPhaseIndices(); + std::tie( ipWetting, std::ignore ) = phaseIndex( getPhaseOrder()); return m_phaseMinVolumeFraction[ipWetting]; } real64 getNonWettingMinVolumeFraction() const override { integer ipNonWetting; - std::tie( std::ignore, ipNonWetting ) = wettingAndNonWettingPhaseIndices(); + std::tie( std::ignore, ipNonWetting ) = phaseIndex( getPhaseOrder()); return m_phaseMinVolumeFraction[ipNonWetting]; }; diff --git a/src/coreComponents/constitutive/relativePermeability/BrooksCoreyRelativePermeability.hpp b/src/coreComponents/constitutive/relativePermeability/BrooksCoreyRelativePermeability.hpp index 30ee2ff3692..2de3998a78e 100644 --- a/src/coreComponents/constitutive/relativePermeability/BrooksCoreyRelativePermeability.hpp +++ b/src/coreComponents/constitutive/relativePermeability/BrooksCoreyRelativePermeability.hpp @@ -105,19 +105,18 @@ class BrooksCoreyRelativePermeability : public RelativePermeabilityBase static constexpr char const * volFracScaleString() { return "volFracScale"; } }; //END_SPHINX_INCLUDE_01 - arrayView1d< real64 const > getPhaseMinVolumeFraction() const override { return m_phaseMinVolumeFraction; }; real64 getWettingPhaseMinVolumeFraction() const override { integer ipWetting; - std::tie( ipWetting, std::ignore ) = wettingAndNonWettingPhaseIndices(); + std::tie( ipWetting, std::ignore ) = phaseIndex( getPhaseOrder()); return m_phaseMinVolumeFraction[ipWetting]; } real64 getNonWettingMinVolumeFraction() const override { integer ipNonWetting; - std::tie( std::ignore, ipNonWetting ) = wettingAndNonWettingPhaseIndices(); + std::tie( std::ignore, ipNonWetting ) = phaseIndex( getPhaseOrder()); return m_phaseMinVolumeFraction[ipNonWetting]; }; diff --git a/src/coreComponents/constitutive/relativePermeability/BrooksCoreyStone2RelativePermeability.hpp b/src/coreComponents/constitutive/relativePermeability/BrooksCoreyStone2RelativePermeability.hpp index 47eefdd512a..2d83dcda597 100644 --- a/src/coreComponents/constitutive/relativePermeability/BrooksCoreyStone2RelativePermeability.hpp +++ b/src/coreComponents/constitutive/relativePermeability/BrooksCoreyStone2RelativePermeability.hpp @@ -138,7 +138,7 @@ class BrooksCoreyStone2RelativePermeability : public RelativePermeabilityBase static constexpr char const * volFracScaleString() { return "volFracScale"; } }; - arrayView1d< real64 const > getPhaseMinVolumeFraction() const override { return m_phaseMinVolumeFraction; }; + arrayView1d< real64 const > getPhaseMinVolumeFraction() const { return m_phaseMinVolumeFraction; }; real64 getWettingPhaseMinVolumeFraction() const override { diff --git a/src/coreComponents/constitutive/relativePermeability/KilloughHysteresis.hpp b/src/coreComponents/constitutive/relativePermeability/KilloughHysteresis.hpp index 58499b94b64..48d2d3deaa2 100644 --- a/src/coreComponents/constitutive/relativePermeability/KilloughHysteresis.hpp +++ b/src/coreComponents/constitutive/relativePermeability/KilloughHysteresis.hpp @@ -137,18 +137,8 @@ class KilloughHysteresis m_extremumPhaseVolFraction ), InputError ); - GEOS_THROW_IF( m_criticalImbibitionValue < 0 || m_criticalImbibitionValue > 1, - GEOS_FMT( "KilloughHysteresis: the critical imbibition relative permeability is equal to {} but must be between 0 an 1", - m_criticalImbibitionValue ), - InputError ); - GEOS_THROW_IF( m_criticalDrainageValue < 0 || m_criticalDrainageValue > 1, - GEOS_FMT( "KilloughHysteresis: the critical drainage relative permeability is equal to {} but must be between 0 an 1", - m_criticalDrainageValue ), - InputError ); - GEOS_THROW_IF( m_extremumValue < 0 || m_extremumValue > 1, - GEOS_FMT( "KilloughHysteresis: the extremum relative permeability is equal to {} but must be between 0 an 1", - m_extremumValue ), - InputError ); + // Note: value validation removed because this struct is used for both relative permeability (0-1 range) + // and capillary pressure (can be in Pa or other units, typically >> 1). The value range depends on the application. m_isWetting = m_criticalDrainagePhaseVolFraction > m_extremumPhaseVolFraction; diff --git a/src/coreComponents/constitutive/relativePermeability/RelativePermeabilityBase.cpp b/src/coreComponents/constitutive/relativePermeability/RelativePermeabilityBase.cpp index d93d335873e..57890850fab 100644 --- a/src/coreComponents/constitutive/relativePermeability/RelativePermeabilityBase.cpp +++ b/src/coreComponents/constitutive/relativePermeability/RelativePermeabilityBase.cpp @@ -153,6 +153,7 @@ std::tuple< integer, integer > RelativePermeabilityBase::wettingAndNonWettingPha return std::make_tuple( ipWetting, ipNonWetting ); } + } // namespace constitutive } // namespace geos diff --git a/src/coreComponents/constitutive/relativePermeability/RelativePermeabilityBase.hpp b/src/coreComponents/constitutive/relativePermeability/RelativePermeabilityBase.hpp index 0bc67b26a39..0600a41643a 100644 --- a/src/coreComponents/constitutive/relativePermeability/RelativePermeabilityBase.hpp +++ b/src/coreComponents/constitutive/relativePermeability/RelativePermeabilityBase.hpp @@ -165,8 +165,8 @@ class RelativePermeabilityBase : public ConstitutiveBase static std::tuple< integer, integer > phaseIndex( arrayView1d< integer const > const & phaseOrder ); arrayView1d< integer const > getPhaseOrder() const { return m_phaseOrder; } - virtual arrayView1d< real64 const > getPhaseMinVolumeFraction() const = 0; virtual real64 getWettingPhaseMinVolumeFraction() const = 0; + virtual real64 getNonWettingMinVolumeFraction() const = 0; std::tuple< integer, integer > wettingAndNonWettingPhaseIndices() const; @@ -217,6 +217,45 @@ class RelativePermeabilityBase : public ConstitutiveBase }; + +/// for use in RelpermDriver to browse the drainage curves +/// by setting the MaxHistoricalNonWettingSat to Snwmin and MinWettingSat to Sw +inline std::tuple< integer, integer > RelativePermeabilityBase::phaseIndex( arrayView1d< integer const > const & phaseOrder ) +{ + using PT = PhaseType; + integer const ipWater = phaseOrder[PT::WATER]; + integer const ipOil = phaseOrder[PT::OIL]; + integer const ipGas = phaseOrder[PT::GAS]; + + integer ipWetting = -1, ipNonWetting = -1; + + if( ipWater >= 0 && ipOil >= 0 && ipGas >= 0 ) + { + ipWetting = ipWater; + ipNonWetting = ipGas; + } + else if( ipWater < 0 ) + { + ipWetting = ipOil; + ipNonWetting = ipGas; + } + else if( ipOil < 0 ) + { + ipWetting = ipWater; + ipNonWetting = ipGas; + } + else if( ipGas < 0 ) + { + ipWetting = ipWater; + ipNonWetting = ipOil; + } + + //maybe a bit too pythonic + return std::make_tuple( ipWetting, ipNonWetting ); +} + + + } // namespace constitutive } // namespace geos diff --git a/src/coreComponents/constitutive/relativePermeability/TableRelativePermeability.hpp b/src/coreComponents/constitutive/relativePermeability/TableRelativePermeability.hpp index 7b2fb4d7bcd..255fa33aca3 100644 --- a/src/coreComponents/constitutive/relativePermeability/TableRelativePermeability.hpp +++ b/src/coreComponents/constitutive/relativePermeability/TableRelativePermeability.hpp @@ -142,19 +142,17 @@ class TableRelativePermeability : public RelativePermeabilityBase static constexpr char const * threePhaseInterpolatorString() { return "threePhaseInterpolator"; } }; - arrayView1d< real64 const > getPhaseMinVolumeFraction() const override { return m_phaseMinVolumeFraction; }; - real64 getWettingPhaseMinVolumeFraction() const override { integer ipWetting; - std::tie( ipWetting, std::ignore ) = wettingAndNonWettingPhaseIndices(); + std::tie( ipWetting, std::ignore ) = phaseIndex( getPhaseOrder()); return m_phaseMinVolumeFraction[ipWetting]; } real64 getNonWettingMinVolumeFraction() const override { integer ipNonWetting; - std::tie( std::ignore, ipNonWetting ) = wettingAndNonWettingPhaseIndices(); + std::tie( std::ignore, ipNonWetting ) = phaseIndex( getPhaseOrder()); return m_phaseMinVolumeFraction[ipNonWetting]; }; diff --git a/src/coreComponents/constitutive/relativePermeability/TableRelativePermeabilityHelpers.cpp b/src/coreComponents/constitutive/relativePermeability/TableRelativePermeabilityHelpers.cpp index 965c9278fc1..3d360fc6362 100644 --- a/src/coreComponents/constitutive/relativePermeability/TableRelativePermeabilityHelpers.cpp +++ b/src/coreComponents/constitutive/relativePermeability/TableRelativePermeabilityHelpers.cpp @@ -81,7 +81,7 @@ TableRelativePermeabilityHelpers::validateRelativePermeabilityTable( TableFuncti if( isZero( relPerm[i-1] ) && !isZero( relPerm[i] ) ) { phaseMinVolFrac = phaseVolFrac[i-1]; - phaseRelPermMinEndPoint = 0.; + phaseRelPermMinEndPoint = relPerm[i-1]; } } diff --git a/src/coreComponents/constitutive/relativePermeability/TableRelativePermeabilityHysteresis.cpp b/src/coreComponents/constitutive/relativePermeability/TableRelativePermeabilityHysteresis.cpp index 910c42cce41..69814ea81fd 100644 --- a/src/coreComponents/constitutive/relativePermeability/TableRelativePermeabilityHysteresis.cpp +++ b/src/coreComponents/constitutive/relativePermeability/TableRelativePermeabilityHysteresis.cpp @@ -22,7 +22,8 @@ #include "constitutive/relativePermeability/RelativePermeabilityFields.hpp" #include "constitutive/relativePermeability/TableRelativePermeabilityHelpers.hpp" #include "functions/FunctionManager.hpp" -#include "LogLevelsInfo.hpp" +#include "constitutiveDrivers/relativePermeability/RelpermDriver.hpp" +#include "constitutive/ConstitutiveManager.hpp" namespace geos { @@ -89,48 +90,68 @@ TableRelativePermeabilityHysteresis::TableRelativePermeabilityHysteresis( std::s "To neglect hysteresis on this phase, just use the same table name for the drainage and imbibition curves" ); // hysteresis input parameters - - registerWrapper( viewKeyStruct::landParameterString(), &m_landParam ). - setInputFlag( InputFlags::FALSE ). // will be deduced from tables + registerWrapper( viewKeyStruct::phaseHasHysteresisString(), &m_phaseHasHysteresis ). + setInputFlag( InputFlags::FALSE ) + . // will be deduced from tables setSizedFromParent( 0 ); - // forwarded to KilloughHysteresis - registerWrapper( KilloughHysteresis::viewKeyStruct::jerauldParameterAString(), &m_jerauldParam_a ). - setInputFlag( InputFlags::OPTIONAL ). - setApplyDefaultValue( 0.1 ). - setDescription( "First parameter (modification parameter) introduced by Jerauld in the Land trapping model (see RTD documentation)." ); - - registerWrapper( KilloughHysteresis::viewKeyStruct::jerauldParameterBString(), &m_jerauldParam_b ). - setInputFlag( InputFlags::OPTIONAL ). - setApplyDefaultValue( 0.0 ). - setDescription( "Second parameter (modification parameter) introduced by Jerauld in the Land trapping model (see RTD documentation)." ); - - registerWrapper( KilloughHysteresis::viewKeyStruct::killoughCurvatureParameterString(), &m_killoughCurvatureParamRelPerm ). - setInputFlag( InputFlags::OPTIONAL ). - setApplyDefaultValue( 1.0 ). - setDescription( "Curvature parameter introduced by Killough for wetting-phase hysteresis (see RTD documentation)." ); + registerField< fields::relperm::phaseMaxHistoricalVolFraction >( + &m_phaseMaxHistoricalVolFraction ); + registerField< fields::relperm::phaseMinHistoricalVolFraction >( + &m_phaseMinHistoricalVolFraction ); - // structs + /// Killough data registerWrapper( viewKeyStruct::drainageRelPermKernelWrappersString(), &m_drainageRelPermKernelWrappers ). setSizedFromParent( 0 ). - setRestartFlags( RestartFlags::NO_WRITE ); + setRestartFlags( + RestartFlags::NO_WRITE ); registerWrapper( viewKeyStruct::imbibitionRelPermKernelWrappersString(), &m_imbibitionRelPermKernelWrappers ). setSizedFromParent( 0 ). - setRestartFlags( RestartFlags::NO_WRITE ); + setRestartFlags( + RestartFlags::NO_WRITE ); - // Killough data - registerWrapper( viewKeyStruct::wettingCurveString(), &m_wettingCurve ). + registerWrapper( viewKeyStruct::landParameterString(), &m_landParam ). setInputFlag( InputFlags::FALSE ). // will be deduced from tables - setSizedFromParent( 0 ). - setRestartFlags( RestartFlags::NO_WRITE ); + setSizedFromParent( 0 ); + + + registerWrapper( viewKeyStruct::wettingCurveString(), &m_wettingCurve ). + setInputFlag( + InputFlags::FALSE ). // will be deduced from tables + setSizedFromParent( + 0 ) + .setRestartFlags( RestartFlags::NO_WRITE ); registerWrapper( viewKeyStruct::nonWettingCurveString(), &m_nonWettingCurve ). - setInputFlag( InputFlags::FALSE ). // will be deduced from tables - setSizedFromParent( 0 ). - setRestartFlags( RestartFlags::NO_WRITE ); + setInputFlag( + InputFlags::FALSE ). // will be deduced from tables + setSizedFromParent( + 0 ) + .setRestartFlags( RestartFlags::NO_WRITE ); + + //Forwarded to KilloughHysteresis + registerWrapper( KilloughHysteresis::viewKeyStruct::jerauldParameterAString(), &m_jerauldParam_a ). + setInputFlag( InputFlags::OPTIONAL ). + setApplyDefaultValue( 0.1 ). + setDescription( + "First parameter (modification parameter) introduced by Jerauld in the Land trapping model (see RTD documentation)." ); + + registerWrapper( KilloughHysteresis::viewKeyStruct::jerauldParameterBString(), &m_jerauldParam_b ). + setInputFlag( InputFlags::OPTIONAL ). + setApplyDefaultValue( 0.0 ). + setDescription( + "Second parameter (modification parameter) introduced by Jerauld in the Land trapping model (see RTD documentation)." ); + + registerWrapper(KilloughHysteresis::viewKeyStruct::killoughCurvatureParameterRelPermString(), &m_killoughCurvatureParamRelPerm ). + setInputFlag( + InputFlags::OPTIONAL ). + setApplyDefaultValue( + 1.0 ). + setDescription( + "Curvature parameter introduced by Killough for wetting-phase hysteresis (see RTD documentation)." ); registerWrapper( viewKeyStruct::waterOilMaxRelPermString(), &m_waterOilMaxRelPerm ). setInputFlag( InputFlags::FALSE ). // will be deduced from tables @@ -165,7 +186,6 @@ void TableRelativePermeabilityHysteresis::postInputInitialization() getFullName() ), InputError, getDataContext() ); - m_phaseMinVolumeFraction.resize( numPhases ); m_phaseHasHysteresis.resize( numPhases ); //initialize STONE-II only used var to avoid discrepancies in baselines @@ -235,7 +255,7 @@ void TableRelativePermeabilityHysteresis::postInputInitialization() InputError, getDataContext() ); //Killough section - KilloughHysteresis::postProcessInput( m_jerauldParam_a, m_jerauldParam_b, m_killoughCurvatureParamRelPerm ); + KilloughHysteresis::postProcessInput(m_jerauldParam_a, m_jerauldParam_b, m_killoughCurvatureParamRelPerm, 0.0); } void TableRelativePermeabilityHysteresis::initializePreSubGroups() @@ -262,33 +282,33 @@ void TableRelativePermeabilityHysteresis::checkExistenceAndValidateWettingRelPer using IPT = TableRelativePermeabilityHysteresis::ImbibitionPhasePairPhaseType; integer const numPhases = m_phaseNames.size(); integer ipWetting = -1, ipNonWetting = -1; - std::tie( ipWetting, ipNonWetting ) = RelativePermeabilityBase::wettingAndNonWettingPhaseIndices(); + std::tie( ipWetting, ipNonWetting ) = RelativePermeabilityBase::phaseIndex( m_phaseOrder ); // Step 1.a: take care of the two-phase case - real64 drainagePhaseMinVolFraction = -1; // output - real64 drainagePhaseMaxVolFraction = -1; - real64 drainagePhaseRelPermMinEndPoint = -1; - real64 drainagePhaseRelPermMaxEndPoint = -1; - - string const tableName = ( numPhases == 2 ) ? - m_drainageWettingNonWettingRelPermTableNames[0] : m_drainageWettingIntermediateRelPermTableNames[0]; - - checkExistenceAndValidateRelPermTable( tableName, // input - drainagePhaseMinVolFraction, // output + real64 drainagePhaseMinVolFraction, // output + drainagePhaseMaxVolFraction, + drainagePhaseRelPermMinEndPoint, + drainagePhaseRelPermMaxEndPoint; + GEOS_ASSERT( m_drainageWettingNonWettingRelPermTableNames.size() == 2 ); + auto tableName = ( numPhases == 2 ) ? m_drainageWettingNonWettingRelPermTableNames[0] : m_drainageWettingIntermediateRelPermTableNames[0]; +// integer const ipWetting = ( m_phaseOrder[PhaseType::WATER] >= 0 ) ? m_phaseOrder[PhaseType::WATER] : m_phaseOrder[PhaseType::OIL]; + checkExistenceAndValidateRelPermTable( tableName, // input + drainagePhaseMinVolFraction, // output drainagePhaseMaxVolFraction, drainagePhaseRelPermMinEndPoint, drainagePhaseRelPermMaxEndPoint ); - // imbibition if provided - real64 imbibitionPhaseMinVolFraction = drainagePhaseMinVolFraction; // output - real64 imbibitionPhaseMaxVolFraction = drainagePhaseMaxVolFraction; - real64 imbibitionPhaseRelPermMinEndPoint = drainagePhaseRelPermMinEndPoint; - real64 imbibitionPhaseRelPermMaxEndPoint = drainagePhaseRelPermMaxEndPoint; + + //imbibition if provided + real64 imbibitionPhaseMinVolFraction, // output + imbibitionPhaseMaxVolFraction, + imbibitionPhaseRelPermMinEndPoint, + imbibitionPhaseRelPermMaxEndPoint; if( m_phaseHasHysteresis[IPT::WETTING] ) { - checkExistenceAndValidateRelPermTable( m_imbibitionWettingRelPermTableName, // input - imbibitionPhaseMinVolFraction, // output + checkExistenceAndValidateRelPermTable( m_imbibitionWettingRelPermTableName, // input + imbibitionPhaseMinVolFraction, // output imbibitionPhaseMaxVolFraction, imbibitionPhaseRelPermMinEndPoint, imbibitionPhaseRelPermMaxEndPoint ); @@ -318,17 +338,9 @@ void TableRelativePermeabilityHysteresis::checkExistenceAndValidateWettingRelPer InputError, getDataContext() ); } - m_wettingCurve.setPoints( drainagePhaseMinVolFraction, drainagePhaseRelPermMinEndPoint, // same as imbibition min - imbibitionPhaseMaxVolFraction, imbibitionPhaseRelPermMaxEndPoint, - drainagePhaseMaxVolFraction, drainagePhaseRelPermMaxEndPoint ); - - m_phaseMinVolumeFraction[ipWetting] = drainagePhaseMinVolFraction; - - GEOS_LOG_LEVEL_RANK_0( logInfo::Init, GEOS_FMT( "Initializing wetting relperm curve with {(smin,krmin), (simax,krimax), (sdmax,krdmax)} : {({},{}),({},{}),({},{})}", - m_wettingCurve.m_extremumPhaseVolFraction, m_wettingCurve.m_extremumValue, - m_wettingCurve.m_criticalImbibitionPhaseVolFraction, m_wettingCurve.m_criticalImbibitionValue, - m_wettingCurve.m_criticalDrainagePhaseVolFraction, m_wettingCurve.m_criticalDrainageValue - )); + m_wettingCurve.setPoints( {drainagePhaseMinVolFraction, drainagePhaseRelPermMinEndPoint}, // extremum + {imbibitionPhaseMaxVolFraction, imbibitionPhaseRelPermMaxEndPoint}, // imbibition critical + {drainagePhaseMaxVolFraction, drainagePhaseRelPermMaxEndPoint} ); // drainage critical } void TableRelativePermeabilityHysteresis::checkExistenceAndValidateNonWettingRelPermTables() @@ -337,17 +349,17 @@ void TableRelativePermeabilityHysteresis::checkExistenceAndValidateNonWettingRel integer const numPhases = m_phaseNames.size(); integer ipWetting = -1, ipNonWetting = -1; - std::tie( ipWetting, ipNonWetting ) = RelativePermeabilityBase::wettingAndNonWettingPhaseIndices(); - - // treat drainage - real64 drainagePhaseMinVolFraction = -1; // output - real64 drainagePhaseMaxVolFraction = -1; - real64 drainagePhaseRelPermMinEndPoint = -1; - real64 drainagePhaseRelPermMaxEndPoint = -1; + std::tie( ipWetting, ipNonWetting ) = RelativePermeabilityBase::phaseIndex( m_phaseOrder ); + //treat drainage + real64 drainagePhaseMinVolFraction, // output + drainagePhaseMaxVolFraction, + drainagePhaseRelPermMinEndPoint, + drainagePhaseRelPermMaxEndPoint; // Step 1: Read the drainage for the non wetting phase - string const tableName = ( numPhases == 2 ) ? m_drainageWettingNonWettingRelPermTableNames[1] : - m_drainageNonWettingIntermediateRelPermTableNames[0]; + GEOS_ASSERT( m_drainageWettingNonWettingRelPermTableNames.size() == 2 ); + auto tableName = ( numPhases == 2 ) ? m_drainageWettingNonWettingRelPermTableNames[1] : + m_drainageNonWettingIntermediateRelPermTableNames[0]; checkExistenceAndValidateRelPermTable( tableName, // input drainagePhaseMinVolFraction, // output drainagePhaseMaxVolFraction, @@ -355,10 +367,10 @@ void TableRelativePermeabilityHysteresis::checkExistenceAndValidateNonWettingRel drainagePhaseRelPermMaxEndPoint ); // Step 2: validate non-wetting-phase imbibition relative permeability table - real64 imbibitionPhaseMinVolFraction = drainagePhaseMinVolFraction; // output - real64 imbibitionPhaseMaxVolFraction = drainagePhaseMaxVolFraction; - real64 imbibitionPhaseRelPermMinEndPoint = drainagePhaseRelPermMinEndPoint; - real64 imbibitionPhaseRelPermMaxEndPoint = drainagePhaseRelPermMaxEndPoint; + real64 imbibitionPhaseMinVolFraction, // output + imbibitionPhaseMaxVolFraction, + imbibitionPhaseRelPermMinEndPoint, + imbibitionPhaseRelPermMaxEndPoint; if( m_phaseHasHysteresis[IPT::NONWETTING] ) { @@ -395,17 +407,10 @@ void TableRelativePermeabilityHysteresis::checkExistenceAndValidateNonWettingRel } - m_nonWettingCurve.setPoints( drainagePhaseMaxVolFraction, drainagePhaseRelPermMaxEndPoint, // same as imbibition max - imbibitionPhaseMinVolFraction, imbibitionPhaseRelPermMinEndPoint, - drainagePhaseMinVolFraction, drainagePhaseRelPermMinEndPoint ); - - m_phaseMinVolumeFraction[ipNonWetting] = drainagePhaseMinVolFraction; - GEOS_LOG_LEVEL_RANK_0( logInfo::Init, GEOS_FMT( "Initializing non-wetting relperm curve with {(sdmin,krdmin), (simin,krimin), (smax,krmax)} : {({},{}),({},{}),({},{})}", - m_nonWettingCurve.m_criticalDrainagePhaseVolFraction, m_nonWettingCurve.m_criticalDrainageValue, - m_nonWettingCurve.m_criticalImbibitionPhaseVolFraction, m_nonWettingCurve.m_criticalImbibitionValue, - m_nonWettingCurve.m_extremumPhaseVolFraction, m_nonWettingCurve.m_extremumValue - )); + m_nonWettingCurve.setPoints( {drainagePhaseMaxVolFraction, drainagePhaseRelPermMaxEndPoint}, // extremum + {imbibitionPhaseMinVolFraction, imbibitionPhaseRelPermMinEndPoint}, // imbibition critical + {drainagePhaseMinVolFraction, drainagePhaseRelPermMinEndPoint} ); // drainage critical } @@ -414,19 +419,21 @@ void TableRelativePermeabilityHysteresis::checkExistenceAndValidateIntermediateR if( m_phaseNames.size() == 3 ) { - real64 drainagePhaseMinVolFraction, + + real64 drainagePhaseMinVolFraction, // drainagePhaseMaxVolFraction, drainagePhaseRelPermMinEndPoint, drainagePhaseRelPermMaxEndPoint; - // intermediate drainage from wetting + //intermediate drainage from wetting checkExistenceAndValidateRelPermTable( m_drainageWettingIntermediateRelPermTableNames[1], // input drainagePhaseMinVolFraction, // output drainagePhaseMaxVolFraction, drainagePhaseRelPermMinEndPoint, drainagePhaseRelPermMaxEndPoint ); + //?? checkExistenceAndValidateRelPermTable( m_drainageNonWettingIntermediateRelPermTableNames[1], // input drainagePhaseMinVolFraction, drainagePhaseMaxVolFraction, @@ -468,9 +475,8 @@ void TableRelativePermeabilityHysteresis::computeLandCoefficient() // For two-phase flow, we make sure that they are equal m_landParam.resize( 2 ); - // Note: for simplicity, the notations are taken classical reservoir notations (although this breaks our phaseVolFrac naming convention) + // Note: for simplicity, the notations are taken reservoir simulation literature (although this breaks our phaseVolFrac naming convention) using IPT = TableRelativePermeabilityHysteresis::ImbibitionPhasePairPhaseType; - KilloughHysteresis::computeLandCoefficient( m_wettingCurve, m_landParam[IPT::WETTING] ); KilloughHysteresis::computeLandCoefficient( m_nonWettingCurve, m_landParam[IPT::NONWETTING] ); } @@ -566,12 +572,14 @@ void TableRelativePermeabilityHysteresis::allocateConstitutiveData( Group & pare { integer const numPhases = numFluidPhases(); - m_phaseMinVolumeFraction.resize( numPhases ); - m_phaseMaxHistoricalVolFraction.resize( 0, numPhases ); - m_phaseMinHistoricalVolFraction.resize( 0, numPhases ); - RelativePermeabilityBase::allocateConstitutiveData( parent, numPts ); + m_phaseMaxHistoricalVolFraction.resize( parent.size(), numPhases ); + m_phaseMinHistoricalVolFraction.resize( parent.size(), numPhases ); + + m_phaseMaxHistoricalVolFraction.setValues< parallelDevicePolicy<> >( 0.0 ); + m_phaseMinHistoricalVolFraction.setValues< parallelDevicePolicy<> >( 1.0 ); + m_phaseMaxHistoricalVolFraction.setValues< parallelDevicePolicy<> >( 0.0 ); m_phaseMinHistoricalVolFraction.setValues< parallelDevicePolicy<> >( 1.0 ); } @@ -597,24 +605,25 @@ void TableRelativePermeabilityHysteresis::saveConvergedPhaseVolFractionState( ar } -TableRelativePermeabilityHysteresis::KernelWrapper::KernelWrapper( arrayView1d< TableFunction::KernelWrapper const > const & drainageRelPermKernelWrappers, - arrayView1d< TableFunction::KernelWrapper const > const & imbibitionRelPermKernelWrappers, - arrayView1d< integer const > const & phaseHasHysteresis, - arrayView1d< real64 const > const & landParam, +TableRelativePermeabilityHysteresis::KernelWrapper:: + KernelWrapper( arrayView1d< TableFunction::KernelWrapper const > const & drainageRelPermKernelWrappers, + arrayView1d< TableFunction::KernelWrapper const > const & imbibitionRelPermKernelWrappers, + arrayView1d< integer const > const & phaseHasHysteresis, + arrayView1d< real64 const > const & landParam, real64 const & jerauldParam_a, real64 const & jerauldParam_b, real64 const & killoughCurvatureParamRelPerm, KilloughHysteresis::HysteresisCurve const & wettingCurve, KilloughHysteresis::HysteresisCurve const & nonWettingCurve, - arrayView1d< integer const > const & phaseTypes, - arrayView1d< integer const > const & phaseOrder, - ThreePhaseInterpolator const & threePhaseInterpolator, - real64 const & waterOilRelPermMaxValue, - arrayView2d< real64 const, compflow::USD_PHASE > const & phaseMinHistoricalVolFraction, - arrayView2d< real64 const, compflow::USD_PHASE > const & phaseMaxHistoricalVolFraction, - arrayView3d< real64, relperm::USD_RELPERM > const & phaseTrappedVolFrac, - arrayView3d< real64, relperm::USD_RELPERM > const & phaseRelPerm, - arrayView4d< real64, relperm::USD_RELPERM_DS > const & dPhaseRelPerm_dPhaseVolFrac ) + arrayView1d< integer const > const & phaseTypes, + arrayView1d< integer const > const & phaseOrder, + ThreePhaseInterpolator const & threePhaseInterpolator, + real64 const & waterOilRelPermMaxValue, + arrayView2d< real64 const, compflow::USD_PHASE > const & phaseMinHistoricalVolFraction, + arrayView2d< real64 const, compflow::USD_PHASE > const & phaseMaxHistoricalVolFraction, + arrayView3d< real64, relperm::USD_RELPERM > const & phaseTrappedVolFrac, + arrayView3d< real64, relperm::USD_RELPERM > const & phaseRelPerm, + arrayView4d< real64, relperm::USD_RELPERM_DS > const & dPhaseRelPerm_dPhaseVolFrac ) : RelativePermeabilityBaseUpdate( phaseTypes, phaseOrder, diff --git a/src/coreComponents/constitutive/relativePermeability/TableRelativePermeabilityHysteresis.hpp b/src/coreComponents/constitutive/relativePermeability/TableRelativePermeabilityHysteresis.hpp index 3f0d5611f4c..5761d49c5fc 100644 --- a/src/coreComponents/constitutive/relativePermeability/TableRelativePermeabilityHysteresis.hpp +++ b/src/coreComponents/constitutive/relativePermeability/TableRelativePermeabilityHysteresis.hpp @@ -21,12 +21,11 @@ #define GEOS_CONSTITUTIVE_TABLERELATIVEPERMEABILITYHYSTERESIS_HPP -#include "constitutive/relativePermeability/KilloughHysteresis.hpp" +#include "constitutive/KilloughHysteresis.hpp" #include "constitutive/relativePermeability/RelativePermeabilityBase.hpp" #include "constitutive/relativePermeability/RelativePermeabilityInterpolators.hpp" #include "functions/TableFunction.hpp" - - +///helper model class with data struct for curves and computing recipe for trapped and Land Coeff namespace geos { @@ -79,8 +78,6 @@ class TableRelativePermeabilityHysteresis : public RelativePermeabilityBase virtual string getCatalogName() const override { return catalogName(); } - virtual void allocateConstitutiveData( dataRepository::Group & parent, localIndex const numPts ) override; - /// Type of kernel wrapper for in-kernel update class KernelWrapper final : public RelativePermeabilityBaseUpdate { @@ -140,7 +137,24 @@ class TableRelativePermeabilityHysteresis : public RelativePermeabilityBase real64 & phaseRelPerm, real64 & dPhaseRelPerm_dPhaseVolFrac ) const; - + /** + * @brief Function computing the trapped critical phase volume fraction (Sgcrt) + * @param[in] Scrd the drainage critical phase volume fraction + * @param[in] Shy the max historical phase volume fraction + * @param[in] Smx the max phase volume fraction (= end-point phase volume fraction) + * @param[in] jerauldParam_a first (modification) parameter proposed by Jerauld + * @param[in] jerauldParam_b second (exponent) parameter proposed by Jerauld + * @param[in] landParam Land trapping parameter + * @param[out] Scrt the trapped critical phase volume fraction + */ + GEOS_HOST_DEVICE + void computeTrappedCriticalPhaseVolFraction( real64 const & Scrd, + real64 const & Shy, + real64 const & Smx, + real64 const & jerauldParam_a, + real64 const & jerauldParam_b, + real64 const & landParam, + real64 & Scrt ) const; /** * @brief Function updating the relperm (and derivative) for the wetting phase in imbibition using Killough's method * @param[in] drainageRelPermKernelWrapper kernel wrapper storing the drainage relperm table for the wetting phase @@ -270,19 +284,13 @@ class TableRelativePermeabilityHysteresis : public RelativePermeabilityBase /// Trapping parameter from the Land model (typically called C) arrayView1d< real64 const > m_landParam; - /// Parameter a introduced by Jerauld in the Land model real64 const & m_jerauldParam_a; - /// Parameter b introduced by Jerauld in the Land model real64 const & m_jerauldParam_b; - /// Curvature parameter introduced for wetting phase hysteresis in Killough real64 const & m_killoughCurvatureParamRelPerm; - /// The wetting phase hysteretic curve KilloughHysteresis::HysteresisCurve const & m_wettingCurve; - - /// The non-wetting phase hysteretic curve KilloughHysteresis::HysteresisCurve const & m_nonWettingCurve; /// Minimum historical phase volume fraction for each phase @@ -307,17 +315,17 @@ class TableRelativePermeabilityHysteresis : public RelativePermeabilityBase struct viewKeyStruct : RelativePermeabilityBase::viewKeyStruct { - /// Land coefficient + ///Land Coeff static constexpr char const * landParameterString() { return "landParameter"; } - /// Hysteretic curves + ///and packed curves data struct static constexpr char const * wettingCurveString() { return "wettingCurve"; }; static constexpr char const * nonWettingCurveString() { return "nonWettingCurve"; }; - /// Flag to determine whether a phase has hysteresis or not + ///flag static constexpr char const * phaseHasHysteresisString() { return "phaseHasHysteresis"; } - /// Tables and associated wrappers + ///tables and assoc. wrappers static constexpr char const * drainageRelPermKernelWrappersString() { return "drainageRelPermWrappers"; } static constexpr char const * imbibitionRelPermKernelWrappersString() { return "imbibitionRelPermWrappers"; } @@ -334,18 +342,18 @@ class TableRelativePermeabilityHysteresis : public RelativePermeabilityBase }; - arrayView1d< real64 const > getPhaseMinVolumeFraction() const override { return m_phaseMinVolumeFraction; }; - real64 getWettingPhaseMinVolumeFraction() const override { - return m_wettingCurve.m_extremumPhaseVolFraction; + return m_wettingCurve.oppositeBoundPhaseVolFraction; } real64 getNonWettingMinVolumeFraction() const override { - return m_nonWettingCurve.m_criticalDrainagePhaseVolFraction; + return m_nonWettingCurve.oppositeBoundPhaseVolFraction; } + virtual void allocateConstitutiveData( Group & parent, localIndex const numPts ) override; + private: virtual void postInputInitialization() override; @@ -453,17 +461,10 @@ class TableRelativePermeabilityHysteresis : public RelativePermeabilityBase /// Maximum historical phase volume fraction for each phase array2d< real64, compflow::LAYOUT_PHASE > m_phaseMaxHistoricalVolFraction; - /// The wetting phase hysteretic curve KilloughHysteresis::HysteresisCurve m_wettingCurve; - - /// The non-wetting phase hysteretic curve KilloughHysteresis::HysteresisCurve m_nonWettingCurve; - /// Min phase volume fractions (deduced from the tables). With Baker, only the water phase entry is used - array1d< real64 > m_phaseMinVolumeFraction; - real64 m_waterOilMaxRelPerm; - ThreePhaseInterpolator m_threePhaseInterpolator; }; @@ -498,13 +499,13 @@ TableRelativePermeabilityHysteresis::KernelWrapper:: // if consistent, S should be equal to 1 - imbibitionPhaseMinVolNonWettingFraction for two-phase flow // (but wetting and nonwetting phase hysteresis are implemented in a decoupled fashion) real64 const S = phaseVolFraction; - real64 const Smxi = m_wettingCurve.m_criticalImbibitionPhaseVolFraction; - real64 const Smxd = m_wettingCurve.m_criticalDrainagePhaseVolFraction; + real64 const Smxi = m_wettingCurve.imbibitionExtremaPhaseVolFraction; + real64 const Smxd = m_wettingCurve.drainageExtremaPhaseVolFraction; // Swc is the common end min endpoint saturation for wetting curves - real64 const Swc = m_wettingCurve.m_extremumPhaseVolFraction; + real64 const Swc = m_wettingCurve.oppositeBoundPhaseVolFraction; - using IPT = ImbibitionPhasePairPhaseType; + using IPT = TableRelativePermeabilityHysteresis::ImbibitionPhasePairPhaseType; if( S <= Swc ) { phaseRelPerm = 0.0; @@ -512,12 +513,12 @@ TableRelativePermeabilityHysteresis::KernelWrapper:: } else if( S >= Smxd ) { - phaseRelPerm = m_wettingCurve.m_criticalDrainageValue; + phaseRelPerm = m_wettingCurve.drainageExtremaSCALValue; dPhaseRelPerm_dPhaseVolFrac = 0.0; } else { - real64 const krwei = m_wettingCurve.m_criticalImbibitionValue; + real64 const krwei = m_wettingCurve.imbibitionExtremaSCALValue; real64 const krwedAtSmxi = drainageRelPermKernelWrapper.compute( &Smxi ); // Step 1: Compute the new end point @@ -578,12 +579,12 @@ TableRelativePermeabilityHysteresis::KernelWrapper:: // Step 1: for a given value of the max historical saturation, Shy, compute the trapped critical saturation, Scrt, // using Land's method. The calculation includes the modifications from Jerauld. real64 const S = phaseVolFraction; - real64 const Scri = m_nonWettingCurve.m_criticalImbibitionPhaseVolFraction; - real64 const Smx = m_nonWettingCurve.m_extremumPhaseVolFraction; + real64 const Scri = m_nonWettingCurve.imbibitionExtremaPhaseVolFraction; + real64 const Smx = m_nonWettingCurve.oppositeBoundPhaseVolFraction; real64 const Shy = (phaseMaxHistoricalVolFraction < Smx) ? phaseMaxHistoricalVolFraction : Smx; // to make sure that Shy < Smax real64 Scrt = 0; - using IPT = ImbibitionPhasePairPhaseType; + using IPT = TableRelativePermeabilityHysteresis::ImbibitionPhasePairPhaseType; KilloughHysteresis::computeTrappedCriticalPhaseVolFraction( m_nonWettingCurve, Shy, m_landParam[IPT::NONWETTING], @@ -598,13 +599,13 @@ TableRelativePermeabilityHysteresis::KernelWrapper:: } else if( S >= Smx ) // S is above the max saturation, so we just skip the rest and set the relperm to the endpoint { - phaseRelPerm = m_nonWettingCurve.m_extremumValue; + phaseRelPerm = m_nonWettingCurve.oppositeBoundSCALValue; dPhaseRelPerm_dPhaseVolFrac = 0.0; } else { // Step 2: compute the normalized saturation, S_norm, at which the imbibition relperm curve will be evaluated. - real64 const ratio = ( Smx - Scri ) / ( Shy - Scrt ); + real64 const ratio = ( Smx - Scri ) / ( Shy - Scrt ); // non S-deps part (isolated for derivatives calculations) real64 const Snorm = Scri + ( S - Scrt ) * ratio; // normalized saturation real64 const dSnorm_dS = ratio; @@ -618,7 +619,7 @@ TableRelativePermeabilityHysteresis::KernelWrapper:: real64 const krdAtShy = drainageRelPermKernelWrapper.compute( &Shy ); // Step 5: evaluate the drainage relperm, krd(Smx), at the max drainage saturation, Smx. - real64 const krdAtSmx = m_nonWettingCurve.m_extremumValue; + real64 const krdAtSmx = m_nonWettingCurve.oppositeBoundSCALValue; // Step 6: apply the formula blending drainage and imbibition relperms from the Killough model. real64 const drainageRelPermRatio = krdAtShy / krdAtSmx; @@ -650,7 +651,7 @@ TableRelativePermeabilityHysteresis::KernelWrapper:: if( !m_phaseHasHysteresis[IPT::WETTING] || phaseVolFraction[ipWetting] <= phaseMinHistoricalVolFraction[ipWetting] + flowReversalBuffer ) { - phaseTrappedVolFrac[ipWetting] = LvArray::math::min( phaseVolFraction[ipWetting], m_wettingCurve.m_extremumPhaseVolFraction ); + phaseTrappedVolFrac[ipWetting] = LvArray::math::min( phaseVolFraction[ipWetting], m_wettingCurve.oppositeBoundPhaseVolFraction ); computeDrainageRelPerm( m_drainageRelPermKernelWrappers[TPT::WETTING], phaseVolFraction[ipWetting], phaseRelPerm[ipWetting], @@ -671,8 +672,8 @@ TableRelativePermeabilityHysteresis::KernelWrapper:: phaseVolFraction[ipNonWetting] >= phaseMaxHistoricalVolFraction[ipNonWetting] - flowReversalBuffer ) { // for reporting purposes, compute Sgcrt first - real64 const Shy = ( phaseVolFraction[ipNonWetting] < m_nonWettingCurve.m_extremumPhaseVolFraction ) - ? phaseVolFraction[ipNonWetting] : m_nonWettingCurve.m_extremumPhaseVolFraction; // to make sure that Shy < Smax + real64 const Shy = ( phaseVolFraction[ipNonWetting] < m_nonWettingCurve.oppositeBoundPhaseVolFraction ) + ? phaseVolFraction[ipNonWetting] : m_nonWettingCurve.oppositeBoundPhaseVolFraction; // to make sure that Shy < Smax real64 Scrt = 0; KilloughHysteresis::computeTrappedCriticalPhaseVolFraction( m_nonWettingCurve, Shy, @@ -727,7 +728,7 @@ TableRelativePermeabilityHysteresis::KernelWrapper:: if( !m_phaseHasHysteresis[IPT::WETTING] || phaseVolFraction[ipWetting] <= phaseMinHistoricalVolFraction[ipWetting] + flowReversalBuffer ) { - phaseTrappedVolFrac[ipWetting] = LvArray::math::min( m_wettingCurve.m_extremumPhaseVolFraction, phaseVolFraction[ipWetting] ); + phaseTrappedVolFrac[ipWetting] = LvArray::math::min( m_wettingCurve.oppositeBoundPhaseVolFraction, phaseVolFraction[ipWetting] ); computeDrainageRelPerm( m_drainageRelPermKernelWrappers[TPT::WETTING], phaseVolFraction[ipWetting], phaseRelPerm[ipWetting], @@ -756,8 +757,8 @@ TableRelativePermeabilityHysteresis::KernelWrapper:: phaseVolFraction[ipNonWetting] >= phaseMaxHistoricalVolFraction[ipNonWetting] - flowReversalBuffer ) { // 2.a) compute Sgcrt for reporting purposes - real64 const Shy = ( phaseVolFraction[ipNonWetting] < m_nonWettingCurve.m_extremumPhaseVolFraction) - ? phaseVolFraction[ipNonWetting] : m_nonWettingCurve.m_extremumPhaseVolFraction; // to make sure that Shy < Smax + real64 const Shy = ( phaseVolFraction[ipNonWetting] < m_nonWettingCurve.oppositeBoundPhaseVolFraction) + ? phaseVolFraction[ipNonWetting] : m_nonWettingCurve.oppositeBoundPhaseVolFraction; // to make sure that Shy < Smax real64 Scrt = 0; KilloughHysteresis::computeTrappedCriticalPhaseVolFraction( m_nonWettingCurve, Shy, @@ -792,7 +793,7 @@ TableRelativePermeabilityHysteresis::KernelWrapper:: // 3) Compute the "three-phase" oil relperm // use saturation-weighted interpolation - real64 const shiftedWettingVolFrac = (phaseVolFraction[ipWetting] - m_wettingCurve.m_extremumPhaseVolFraction); + real64 const shiftedWettingVolFrac = (phaseVolFraction[ipWetting] - m_wettingCurve.oppositeBoundPhaseVolFraction); if( m_threePhaseInterpolator == ThreePhaseInterpolator::BAKER ) { diff --git a/src/coreComponents/constitutive/relativePermeability/VanGenuchtenBakerRelativePermeability.hpp b/src/coreComponents/constitutive/relativePermeability/VanGenuchtenBakerRelativePermeability.hpp index 931f7d35b63..11bd206d906 100644 --- a/src/coreComponents/constitutive/relativePermeability/VanGenuchtenBakerRelativePermeability.hpp +++ b/src/coreComponents/constitutive/relativePermeability/VanGenuchtenBakerRelativePermeability.hpp @@ -140,19 +140,17 @@ class VanGenuchtenBakerRelativePermeability : public RelativePermeabilityBase }; - arrayView1d< real64 const > getPhaseMinVolumeFraction() const override { return m_phaseMinVolumeFraction; }; - real64 getWettingPhaseMinVolumeFraction() const override { integer ipWetting; - std::tie( ipWetting, std::ignore ) = wettingAndNonWettingPhaseIndices(); + std::tie( ipWetting, std::ignore ) = phaseIndex( getPhaseOrder()); return m_phaseMinVolumeFraction[ipWetting]; } real64 getNonWettingMinVolumeFraction() const override { integer ipNonWetting; - std::tie( std::ignore, ipNonWetting ) = wettingAndNonWettingPhaseIndices(); + std::tie( std::ignore, ipNonWetting ) = phaseIndex( getPhaseOrder()); return m_phaseMinVolumeFraction[ipNonWetting]; }; diff --git a/src/coreComponents/constitutive/relativePermeability/VanGenuchtenStone2RelativePermeability.hpp b/src/coreComponents/constitutive/relativePermeability/VanGenuchtenStone2RelativePermeability.hpp index 3927764f236..e91e4fb39bd 100644 --- a/src/coreComponents/constitutive/relativePermeability/VanGenuchtenStone2RelativePermeability.hpp +++ b/src/coreComponents/constitutive/relativePermeability/VanGenuchtenStone2RelativePermeability.hpp @@ -139,7 +139,7 @@ class VanGenuchtenStone2RelativePermeability : public RelativePermeabilityBase static constexpr char const * volFracScaleString() { return "volFracScale"; } }; - arrayView1d< real64 const > getPhaseMinVolumeFraction() const override { return m_phaseMinVolumeFraction; }; + arrayView1d< real64 const > getPhaseMinVolumeFraction() const { return m_phaseMinVolumeFraction; }; real64 getWettingPhaseMinVolumeFraction() const override { diff --git a/src/coreComponents/constitutive/relativePermeability/unitTests/constitutiveTestHelpers.hpp b/src/coreComponents/constitutive/relativePermeability/unitTests/constitutiveTestHelpers.hpp index e2ddfa05933..c5463cca49f 100644 --- a/src/coreComponents/constitutive/relativePermeability/unitTests/constitutiveTestHelpers.hpp +++ b/src/coreComponents/constitutive/relativePermeability/unitTests/constitutiveTestHelpers.hpp @@ -32,7 +32,7 @@ namespace geos { namespace testing { -void fillArray( array1d< real64_array > & arr, std::initializer_list< real64 > const & input_list ) +void fill_array( array1d< real64_array > & arr, std::initializer_list< real64 > const & input_list ) { arr.resize( 1 ); arr[0].resize( input_list.size()); @@ -42,7 +42,7 @@ void fillArray( array1d< real64_array > & arr, std::initializer_list< real64 > c } -void fillArray( real64_array & arr, std::initializer_list< real64 > const & input_list ) +void fill_array( real64_array & arr, std::initializer_list< real64 > const & input_list ) { arr.resize( input_list.size()); int j = 0; diff --git a/src/coreComponents/constitutiveDrivers/relativePermeability/RelpermDriver.cpp b/src/coreComponents/constitutiveDrivers/relativePermeability/RelpermDriver.cpp index 49dca10b482..6bd500b6dfa 100644 --- a/src/coreComponents/constitutiveDrivers/relativePermeability/RelpermDriver.cpp +++ b/src/coreComponents/constitutiveDrivers/relativePermeability/RelpermDriver.cpp @@ -13,7 +13,9 @@ * ------------------------------------------------------------------------------------------------------------ */ -#include "common/MpiWrapper.hpp" +#include "RelpermDriver.hpp" + +//#include "common/MpiWrapper.hpp" #include "functions/FunctionManager.hpp" #include "functions/TableFunction.hpp" #include "constitutive/ConstitutiveManager.hpp" @@ -110,7 +112,7 @@ bool RelpermDriver::execute( const geos::real64 GEOS_UNUSED_PARAM( time_n ), { // this code only makes sense in serial - GEOS_THROW_IF( MpiWrapper::commRank() > 0, "RelpermDriver should only be run in serial", std::runtime_error ); + //GEOS_THROW_IF( MpiWrapper::commRank() > 0, "RelpermDriver should only be run in serial", std::runtime_error ); ConstitutiveManager diff --git a/src/coreComponents/constitutiveDrivers/relativePermeability/RelpermDriverRunTest.hpp b/src/coreComponents/constitutiveDrivers/relativePermeability/RelpermDriverRunTest.hpp index eabe5616eee..750587bab88 100644 --- a/src/coreComponents/constitutiveDrivers/relativePermeability/RelpermDriverRunTest.hpp +++ b/src/coreComponents/constitutiveDrivers/relativePermeability/RelpermDriverRunTest.hpp @@ -19,7 +19,7 @@ #include "constitutiveDrivers/relativePermeability/RelpermDriver.hpp" #include "constitutive/relativePermeability/RelativePermeabilityFields.hpp" #include "constitutive/relativePermeability/Layouts.hpp" -#include "constitutive/relativePermeability/KilloughHysteresis.hpp" +#include "constitutive/KilloughHysteresis.hpp" namespace geos @@ -96,10 +96,6 @@ RelpermDriver::runTest( RELPERM_TYPE & relperm, arrayView2d< real64, compflow::USD_PHASE > phaseMaxHistoricalVolFraction = relperm.template getField< fields::relperm::phaseMaxHistoricalVolFraction >().reference(); arrayView2d< real64, compflow::USD_PHASE > phaseMinHistoricalVolFraction = relperm.template getField< fields::relperm::phaseMinHistoricalVolFraction >().reference(); -// arrayView1d< real64 > const drainagePhaseMinVolFraction = relperm.template getReference< array1d< real64 > >( -// constitutive::TableRelativePermeabilityHysteresis::viewKeyStruct::drainagePhaseMinVolumeFractionString()); -// arrayView1d< real64 > const drainagePhaseMaxVolFraction = relperm.template getReference< array1d< real64 > >( -// constitutive::TableRelativePermeabilityHysteresis::viewKeyStruct::drainagePhaseMaxVolumeFractionString()); constitutive::KilloughHysteresis::HysteresisCurve const wettingCurve = relperm.template getReference< constitutive::KilloughHysteresis::HysteresisCurve >( constitutive::TableRelativePermeabilityHysteresis::viewKeyStruct::wettingCurveString()); @@ -109,14 +105,15 @@ RelpermDriver::runTest( RELPERM_TYPE & relperm, { if( phaseHasHysteresis[ipNonWetting] ) { - phaseMaxHistoricalVolFraction[0][ipNonWetting] = nonWettingCurve.m_extremumPhaseVolFraction; + phaseMaxHistoricalVolFraction[0][ipNonWetting] = nonWettingCurve.oppositeBoundPhaseVolFraction; GEOS_LOG( GEOS_FMT( "New max non-wetting phase historical phase volume fraction: {}", phaseMaxHistoricalVolFraction[0][ipNonWetting] ) ); } if( phaseHasHysteresis[ipWetting] ) { - phaseMinHistoricalVolFraction[0][ipWetting] = wettingCurve.m_extremumPhaseVolFraction; + phaseMinHistoricalVolFraction[0][ipWetting] = wettingCurve.oppositeBoundPhaseVolFraction; GEOS_LOG( GEOS_FMT( "New min wetting phase historical phase volume fraction: {}", phaseMinHistoricalVolFraction[0][ipWetting] ) ); } + } @@ -140,13 +137,12 @@ RelpermDriver::runTest( RELPERM_TYPE & relperm, { if( phaseHasHysteresis[ipNonWetting] ) { - - phaseMaxHistoricalVolFraction[0][ipNonWetting] = nonWettingCurve.m_criticalDrainagePhaseVolFraction; + phaseMaxHistoricalVolFraction[0][ipNonWetting] = nonWettingCurve.drainageExtremaPhaseVolFraction; GEOS_LOG( GEOS_FMT( "New max non-wetting phase historical phase volume fraction: {}", phaseMaxHistoricalVolFraction[0][ipNonWetting] ) ); } if( phaseHasHysteresis[ipWetting] ) { - phaseMinHistoricalVolFraction[0][ipWetting] = wettingCurve.m_criticalDrainagePhaseVolFraction; + phaseMinHistoricalVolFraction[0][ipWetting] = wettingCurve.drainageExtremaPhaseVolFraction; GEOS_LOG( GEOS_FMT( "New min wetting phase historical phase volume fraction: {}", phaseMinHistoricalVolFraction[0][ipWetting] ) ); } } diff --git a/src/coreComponents/finiteVolume/SurfaceElementStencil.hpp b/src/coreComponents/finiteVolume/SurfaceElementStencil.hpp index 4c982dbef4a..22942a1a648 100644 --- a/src/coreComponents/finiteVolume/SurfaceElementStencil.hpp +++ b/src/coreComponents/finiteVolume/SurfaceElementStencil.hpp @@ -424,8 +424,8 @@ SurfaceElementStencilWrapper:: weight[connectionIndex][0] = value; weight[connectionIndex][1] = -value; - real64 const dt0 = m_weights[iconn][0] * dCoeff_dVar[er0][esr0][ei0][0][0]; - real64 const dt1 = m_weights[iconn][1] * dCoeff_dVar[er1][esr1][ei1][0][0]; + real64 const dt0 = m_weights[iconn][k[0]] * dCoeff_dVar[er0][esr0][ei0][0][0]; + real64 const dt1 = m_weights[iconn][k[1]] * dCoeff_dVar[er1][esr1][ei1][0][0]; real64 dHarmonic[2]; dHarmonic[0] = ( dt0 * t1 * sumOfTrans - dt0 * t0 * t1 ) / ( sumOfTrans * sumOfTrans ); diff --git a/src/coreComponents/integrationTests/constitutiveTests/CMakeLists.txt b/src/coreComponents/integrationTests/constitutiveTests/CMakeLists.txt index bbb94f47a59..7d2b4fc2fc8 100644 --- a/src/coreComponents/integrationTests/constitutiveTests/CMakeLists.txt +++ b/src/coreComponents/integrationTests/constitutiveTests/CMakeLists.txt @@ -1,6 +1,16 @@ # Specify list of tests set( gtest_geosx_tests - testRelPermHysteresis.cpp ) + # testCapillaryPressure.cpp + # testCO2BrinePVTModels.cpp + # testCO2SpycherPruessModels.cpp + # testDamage.cpp + # testMultiFluidCO2Brine.cpp + # testMultiFluidCompositionalMultiphase.cpp + # testMultiFluidDeadOil.cpp + # testMultiFluidLiveOil.cpp + # testRelPerm.cpp + testRelPermHysteresis.cpp + ) set( gtest_triaxial_xmls testTriaxial_druckerPragerExtended.xml diff --git a/src/coreComponents/integrationTests/constitutiveTests/testRelPermHysteresis.cpp b/src/coreComponents/integrationTests/constitutiveTests/testRelPermHysteresis.cpp index aec4f323c85..8c5686c3fc3 100644 --- a/src/coreComponents/integrationTests/constitutiveTests/testRelPermHysteresis.cpp +++ b/src/coreComponents/integrationTests/constitutiveTests/testRelPermHysteresis.cpp @@ -44,49 +44,46 @@ TableRelativePermeabilityHysteresis & makeTableRelPermHysteresisTwoPhase( string array1d< real64_array > coordinates_dw; // Swc = 0.22 // consistent with Swmaxd = 1-Sgcrd = 1-0 = 1 - geos::testing::fillArray( coordinates_dw, - {.22, .25, .3, .35, .4, .45, .5, .55, .6, .65, .66, .68, .72, .82, .91, 1.} ); + geosx::testing::fill_array( coordinates_dw, {.22, .25, .3, .35, .4, .45, .5, .55, .6, .65, .66, .68, .72, .82, .91, 1.} ); array1d< real64_array > coordinates_iw; // Swc = 0.22 // consistent with Swmaxi = 1-Sgcri = 1-0.3 = 0.7 - geos::testing::fillArray( coordinates_iw, {.22, .25, .3, .35, .4, .45, .5, .55, .6, .65, .66, .7} ); + geosx::testing::fill_array( coordinates_iw, {.22, .25, .3, .35, .4, .45, .5, .55, .6, .65, .66, .7} ); // Gas phase saturation, fifth column of Table 2 array1d< real64_array > coordinates_dg; // Sgcrd = 0.0 // consistent with Swc = 0.22 - geos::testing::fillArray( coordinates_dg, - {0.000, 0.010, 0.030, 0.050, 0.100, 0.150, 0.200, 0.250, 0.300, 0.350, 0.400, 0.450, - 0.500, - 0.550, 0.600, 0.650, 0.700, 0.750, 0.780} ); + geosx::testing::fill_array( coordinates_dg, + {0.000, 0.010, 0.030, 0.050, 0.100, 0.150, 0.200, 0.250, 0.300, 0.350, 0.400, 0.450, 0.500, + 0.550, 0.600, 0.650, 0.700, 0.750, 0.780} ); array1d< real64_array > coordinates_ig; // Sgcri = 0.30; // consistent with Swc = 0.22 - geos::testing::fillArray( coordinates_ig, - {0.300, 0.350, 0.400, 0.450, 0.500, 0.550, 0.600, 0.650, 0.700, 0.750, 0.78} ); + geosx::testing::fill_array( coordinates_ig, {0.300, 0.350, 0.400, 0.450, 0.500, 0.550, 0.600, 0.650, 0.700, 0.750, 0.78} ); // then define the bounding drainage and imbibibition relative permeability // Water phase drainage relperm real64_array drainageValues_w; - geos::testing::fillArray( drainageValues_w, {0.00000, 0.00100, 0.00300, 0.01000, 0.01800, 0.03500, 0.04000, 0.05700, - 0.08800, 0.14500, 0.16000, 0.19000, 0.26300, 0.45500, 0.69200, 1.} ); + geosx::testing::fill_array( drainageValues_w, {0.00000, 0.00100, 0.00300, 0.01000, 0.01800, 0.03500, 0.04000, 0.05700, + 0.08800, 0.14500, 0.16000, 0.19000, 0.26300, 0.45500, 0.69200, 1.} ); // Gas phase drainage relperm, seventh column of Table 2 real64_array drainageValues_g; - geos::testing::fillArray( drainageValues_g, {0.00000, 0.00200, 0.00700, 0.01000, 0.02000, 0.04000, 0.07500, - 0.12700, 0.18000, 0.24000, 0.31000, 0.37300, 0.46000, 0.55000, - 0.64000, 0.73000, 0.82500, 0.92000, 1.00000} ); + geosx::testing::fill_array( drainageValues_g, {0.00000, 0.00200, 0.00700, 0.01000, 0.02000, 0.04000, 0.07500, + 0.12700, 0.18000, 0.24000, 0.31000, 0.37300, 0.46000, 0.55000, + 0.64000, 0.73000, 0.82500, 0.92000, 1.00000} ); real64_array imbibitionValues_w; - geos::testing::fillArray( imbibitionValues_w, {0, 0.0156, 0.0680, 0.1409, 0.2296, 0.3317, 0.4455, 0.5700, - 0.7044, 0.8479, 0.8776, 0.9382} ); + geosx::testing::fill_array( imbibitionValues_w, {0, 0.0156, 0.0680, 0.1409, 0.2296, 0.3317, 0.4455, 0.5700, + 0.7044, 0.8479, 0.8776, 0.9382} ); real64_array imbibitionValues_g; - geos::testing::fillArray( imbibitionValues_g, {0.0000, 0.03361965, 0.09509072, 0.17469281, 0.26895718, - 0.37587908, 0.49410588, 0.62264458, 0.76072577, 0.90773047, 1.} ); + geosx::testing::fill_array( imbibitionValues_g, {0.0000, 0.03361965, 0.09509072, 0.17469281, 0.26895718, + 0.37587908, 0.49410588, 0.62264458, 0.76072577, 0.90773047, 1.} ); initializeTable( "drainageWater_swg", coordinates_dw, diff --git a/src/coreComponents/integrationTests/fluidFlowTests/CMakeLists.txt b/src/coreComponents/integrationTests/fluidFlowTests/CMakeLists.txt index 951cac7c502..9a89d938e2e 100644 --- a/src/coreComponents/integrationTests/fluidFlowTests/CMakeLists.txt +++ b/src/coreComponents/integrationTests/fluidFlowTests/CMakeLists.txt @@ -4,6 +4,7 @@ set( gtest_geosx_tests testThermalSinglePhaseFlow.cpp testTransmissibility.cpp testImmiscibleMultiphaseFlow.cpp + testImmiscibleInterfaceConditions.cpp testSinglePhaseMFDPolyhedral.cpp testSinglePhaseReactiveTransport.cpp ) diff --git a/src/coreComponents/integrationTests/fluidFlowTests/testImmiscibleInterfaceConditions.cpp b/src/coreComponents/integrationTests/fluidFlowTests/testImmiscibleInterfaceConditions.cpp index 95431c366a4..b1816d04204 100644 --- a/src/coreComponents/integrationTests/fluidFlowTests/testImmiscibleInterfaceConditions.cpp +++ b/src/coreComponents/integrationTests/fluidFlowTests/testImmiscibleInterfaceConditions.cpp @@ -26,11 +26,11 @@ #include "constitutive/fluid/twophaseimmisciblefluid/TwoPhaseImmiscibleFluid.hpp" #include "physicsSolvers/PhysicsSolverManager.hpp" #include "physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.hpp" -#include "unitTests/fluidFlowTests/testCompFlowUtils.hpp" +#include "integrationTests/fluidFlowTests/testCompFlowUtils.hpp" #include "constitutive/unitTests/FluidModelTest.hpp" #include "constitutive/unitTests/FluidModelTest_impl.hpp" #include "common/initializeEnvironment.hpp" -#include "unitTests/constitutiveTests/constitutiveTestHelpers.hpp" +#include "constitutive/relativePermeability/unitTests/constitutiveTestHelpers.hpp" #include "functions/FunctionManager.hpp" #include "constitutive/capillaryPressure/CapillaryPressureFields.hpp" @@ -417,7 +417,7 @@ CapillaryPressureBase & makeBrooksCoreyCapPressureTwoPhase1( string const & name array1d< real64 > & phaseEntryPressure = capPressure.getReference< array1d< real64 > >( BrooksCoreyCapillaryPressure::viewKeyStruct::phaseEntryPressureString() ); phaseEntryPressure.resize( 2 ); - phaseEntryPressure[0] = 0.75e5; phaseEntryPressure[1] = 0; + phaseEntryPressure[0] = 4.0e3; phaseEntryPressure[1] = 0; real64 & capPressureEpsilon = capPressure.getReference< real64 >( BrooksCoreyCapillaryPressure::viewKeyStruct::capPressureEpsilonString() ); capPressureEpsilon = 1.0e-8; @@ -445,7 +445,7 @@ CapillaryPressureBase & makeBrooksCoreyCapPressureTwoPhase2( string const & name array1d< real64 > & phaseEntryPressure = capPressure.getReference< array1d< real64 > >( BrooksCoreyCapillaryPressure::viewKeyStruct::phaseEntryPressureString() ); phaseEntryPressure.resize( 2 ); - phaseEntryPressure[0] = 0.5e5; phaseEntryPressure[1] = 0; + phaseEntryPressure[0] = 2.0e3; phaseEntryPressure[1] = 0; real64 & capPressureEpsilon = capPressure.getReference< real64 >( BrooksCoreyCapillaryPressure::viewKeyStruct::capPressureEpsilonString() ); capPressureEpsilon = 1e-8; @@ -533,22 +533,30 @@ TEST_F( ImmiscibleInterfaceConditionsTest, LocalNonlinearSolverConvergence ) std::vector< TwoPhaseImmiscibleFluid * > fluids = { &fluid, &fluid }; // real64 uT = 3.2864545889999906e-05; - // real64 uT = -3.3e-5; - real64 uT = 1e-17; + real64 uT = 3.3e-2; // real64 uT = 1e-7; stdVector< real64 > saturations = {0.2, 0.4}; stdVector< real64 > trappedSats1 = {phase0MinSat1, phase1MinSat1}; stdVector< real64 > trappedSats2 = {phase0MinSat2, phase1MinSat2}; stdVector< real64 > pressures = {1e7, 1e7}; stdVector< real64 > JFMultipliers = {45016.662822296035, 30011.108548197357}; + stdVector< fields::cappres::ModeIndexType > modes = {static_cast(0), static_cast(0)}; stdVector< real64 > transHats = {1.9738466000000002e-12, 4.4411548500000007e-12}; stdVector< real64 > dTransHats_dP = {0.0, 0.0}; stdVector< real64 > gravCoefHats = {490.5, 490.5}; stdVector< real64 > gravCoefs = {465.97500000000002, 515.02499999999998}; - + stdVector< real64 > cellCenterDuT = {0.0, 0.0, 0.0, 0.0}; // duT_dP[0], duT_dP[1], duT_dS[0], duT_dS[1] + stdVector< real64 > cellCenterDens = {1000.0, 800.0}; // density for each phase + stdVector< real64 > cellCenterDens_dP = {0.0, 0.0, 0.0, 0.0}; // dDens_dP[0][0], dDens_dP[0][1], dDens_dP[1][0], dDens_dP[1][1] + stdVector< real64 > phaseMaxHistVolFrac1 = {0.0, 0.0}; + stdVector< real64 > phaseMinHistVolFrac1 = {0.0, 0.0}; + stdVector< real64 > phaseMaxHistVolFrac2 = {0.0, 0.0}; + stdVector< real64 > phaseMinHistVolFrac2 = {0.0, 0.0}; stdVector< real64 > phi = {0.0, 0.0}; - stdVector< real64 > grad_phi = {0.0, 0.0, 0.0, 0.0}; + stdVector< real64 > grad_phi_P = {0.0, 0.0, 0.0, 0.0}; + stdVector< real64 > grad_phi_S = {0.0, 0.0, 0.0, 0.0}; + bool converged = false; std::ofstream outFile( "local_solver_results.csv" ); @@ -574,52 +582,131 @@ TEST_F( ImmiscibleInterfaceConditionsTest, LocalNonlinearSolverConvergence ) real64 const start_sat = 0.0; real64 const end_sat = 1.0; real64 const dS = 1e-2; - real64 Si = 0.0; - real64 Sj = 0.9; + // real64 Si = 0.0; + // real64 Sj = 0.9; - // for( real64 Si = start_sat; Si <= end_sat + 1e-8; Si += dS ) - // { - // for( real64 Sj = start_sat; Sj <= end_sat + 1e-8; Sj += dS ) - // { + for( real64 Si = start_sat; Si <= end_sat + 1e-8; Si += dS ) + { + for( real64 Sj = start_sat; Sj <= end_sat + 1e-8; Sj += dS ) + { saturations[0] = Si; saturations[1] = Sj; auto t0 = std::chrono::high_resolution_clock::now(); // Call the GEOS local solver - geos::immiscibleMultiphaseKernels::local_solver( uT, saturations, pressures, JFMultipliers, trappedSats1, trappedSats2, transHats, dTransHats_dP, gravCoefHats, gravCoefs, - relPerms, capPressures, fluids, phi, grad_phi ); + geos::immiscibleMultiphaseKernels::local_solver( uT, saturations, pressures, JFMultipliers, trappedSats1, trappedSats2, modes, transHats, dTransHats_dP, gravCoefHats, gravCoefs, + cellCenterDuT, cellCenterDens, cellCenterDens_dP, relPerms, capPressures, fluids, phi, grad_phi_P, grad_phi_S, converged, + phaseMaxHistVolFrac1, phaseMinHistVolFrac1, phaseMaxHistVolFrac2, phaseMinHistVolFrac2 ); auto t1 = std::chrono::high_resolution_clock::now(); std::chrono::duration elapsed = t1 - t0; -std::cout << "Local solver time: " << elapsed.count() << " s" << std::endl; - +// std::cout << "Local solver time: " << elapsed.count() << " s" << std::endl; +EXPECT_TRUE( converged ) << "Local solver diverged for saturations Si=" << Si << ", Sj=" << Sj; // Write data to the file outFile << GEOS_FMT( "{:10.10e}", saturations[0] ); outFile << GEOS_FMT( ",{:10.10e}", saturations[1] ); outFile << GEOS_FMT( ",{:10.10e}", phi[0] ); outFile << GEOS_FMT( ",{:10.10e}", phi[1] ); - outFile << GEOS_FMT( ",{:10.10e}", grad_phi[0] ); - outFile << GEOS_FMT( ",{:10.10e}", grad_phi[1] ); - outFile << GEOS_FMT( ",{:10.10e}", grad_phi[2] ); - outFile << GEOS_FMT( ",{:10.10e}", grad_phi[3] ); + outFile << GEOS_FMT( ",{:10.10e}", grad_phi_P[0] ); + outFile << GEOS_FMT( ",{:10.10e}", grad_phi_P[1] ); + outFile << GEOS_FMT( ",{:10.10e}", grad_phi_P[2] ); + outFile << GEOS_FMT( ",{:10.10e}", grad_phi_P[3] ); outFile << std::endl; phi[0] = 0; phi[1] = 0; - grad_phi[0] = 0; - grad_phi[1] = 0; - grad_phi[2] = 0; - grad_phi[3] = 0; - -// } -// } + grad_phi_P[0] = 0; + grad_phi_P[1] = 0; + grad_phi_P[2] = 0; + grad_phi_P[3] = 0; + grad_phi_S[0] = 0; + grad_phi_S[1] = 0; + grad_phi_S[2] = 0; + grad_phi_S[3] = 0; + + } +} outFile.close(); } ); } +TEST_F( ImmiscibleInterfaceConditionsTest, LocalSolverResults ) +{ + + // using Base = FluidModelTest< TwoPhaseImmiscibleFluid, 2 >; + createFluid( "fluid", [this]( TwoPhaseImmiscibleFluid & fluid ){ + makeTwoPhaseImmiscibleFluid( fluid ); + + // getting constitutive models: + RelativePermeabilityBase & relPerm = makeBrooksCoreyRelPerm( "relPerm" , this->m_parent); + RelativePermeabilityBase * relPermPtr = &relPerm; + + CapillaryPressureBase & capPressure0 = makeBrooksCoreyCapPressureTwoPhase1( "capPressure0", this->m_parent ); + CapillaryPressureBase * capPressurePtr0 = &capPressure0; + + CapillaryPressureBase & capPressure1 = makeBrooksCoreyCapPressureTwoPhase2( "capPressure1", this->m_parent ); + CapillaryPressureBase * capPressurePtr1 = &capPressure1; + + std::vector< RelativePermeabilityBase * > relPerms = {relPermPtr, relPermPtr}; + std::vector< CapillaryPressureBase * > capPressures = {capPressurePtr0, capPressurePtr1}; + std::vector< TwoPhaseImmiscibleFluid * > fluids = { &fluid, &fluid }; + + real64 uT = 0.000001889581158; + + stdVector< real64 > saturations = {0.6, 0.3}; + stdVector< real64 > trappedSats1 = {phase0MinSat1, phase1MinSat1}; + stdVector< real64 > trappedSats2 = {phase0MinSat2, phase1MinSat2}; + stdVector< real64 > pressures = {1e7, 1e7}; + stdVector< real64 > JFMultipliers = {45016.662822296035, 30011.108548197357}; + stdVector< fields::cappres::ModeIndexType > modes = {static_cast(0), static_cast(0)}; + stdVector< real64 > transHats = {2.0e-12, 8.0e-12}; + stdVector< real64 > dTransHats_dP = {0.0, 0.0}; + stdVector< real64 > gravCoefHats = {49.05, 49.05}; + stdVector< real64 > gravCoefs = {46.5975, 51.5025}; + stdVector< real64 > cellCenterDuT = {8.32E-10, -8.32E-10, 0.0000063429744518, -0.0000012971521486}; // duT_dP[0], duT_dP[1], duT_dS[0], duT_dS[1] + stdVector< real64 > cellCenterDens = {1000.0, 100.0}; // density for each phase + stdVector< real64 > cellCenterDens_dP = {0.0, 0.0, 0.0, 0.0}; // dDens_dP[0][0], dDens_dP[0][1], dDens_dP[1][0], dDens_dP[1][1] + stdVector< real64 > phaseMaxHistVolFrac1 = {0.0, 0.0}; + stdVector< real64 > phaseMinHistVolFrac1 = {0.0, 0.0}; + stdVector< real64 > phaseMaxHistVolFrac2 = {0.0, 0.0}; + stdVector< real64 > phaseMinHistVolFrac2 = {0.0, 0.0}; + + stdVector< real64 > phi = {0.0, 0.0}; + stdVector< real64 > grad_phi_P = {0.0, 0.0, 0.0, 0.0}; + stdVector< real64 > grad_phi_S = {0.0, 0.0, 0.0, 0.0}; + bool converged = false; + + + +// Call the GEOS local solver + geos::immiscibleMultiphaseKernels::local_solver( uT, saturations, pressures, JFMultipliers, trappedSats1, trappedSats2, modes, transHats, dTransHats_dP, gravCoefHats, gravCoefs, + cellCenterDuT, cellCenterDens, cellCenterDens_dP, relPerms, capPressures, fluids, phi, grad_phi_P, grad_phi_S, converged, + phaseMaxHistVolFrac1, phaseMinHistVolFrac1, phaseMaxHistVolFrac2, phaseMinHistVolFrac2 ); + + real64 const tolerance_eps = std::sqrt( std::numeric_limits< real64 >::epsilon() ); + real64 const tol = 1e-4; + real64 const abs_tolerance = tolerance_eps * tol; + + EXPECT_NEAR( phi[0], 1.676451024635667e-03, abs_tolerance ); + EXPECT_NEAR( phi[1], 2.131301333609180e-05, abs_tolerance ); + EXPECT_NEAR( grad_phi_P[0], 5.760000000000000e-07, abs_tolerance ); + EXPECT_NEAR( grad_phi_P[1], -5.760000000000000e-07, abs_tolerance ); + EXPECT_NEAR( grad_phi_P[2], 2.560000000000001e-08, abs_tolerance ); + EXPECT_NEAR( grad_phi_P[3], -2.560000000000001e-08, abs_tolerance ); + EXPECT_NEAR( grad_phi_S[0], 7.268012258072125e-03, abs_tolerance ); + EXPECT_NEAR( grad_phi_S[1], -8.980284105794445e-04, abs_tolerance ); + EXPECT_NEAR( grad_phi_S[2], -9.250378062747074e-05, abs_tolerance ); + EXPECT_NEAR( grad_phi_S[3], -3.991237380353088e-05, abs_tolerance ); + + +} ); +} + + + int main( int argc, char * *argv ) { ::testing::InitGoogleTest( &argc, argv ); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseBase.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseBase.cpp index ec8268e0079..d71740eb5fe 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseBase.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseBase.cpp @@ -998,12 +998,24 @@ void CompositionalMultiphaseBase::initializeFluidState( MeshLevel & mesh, // We postpone the other constitutive models for now // Now, we initialize and update each constitutive model one by one - // initialized phase volume fraction arrayView2d< real64 const, compflow::USD_PHASE > const phaseVolFrac = - subRegion.template getField< flow::phaseVolumeFraction >(); + subRegion.template getField< fields::flow::phaseVolumeFraction >(); - // Initialize/update the relative permeability model using the initial phase volume fraction + // 4.2 Save the computed porosity into the old porosity + // + // Note: + // - This must be called after updatePorosityAndPermeability + // - This step depends on porosity + string const & solidName = subRegion.template getReference< string >( viewKeyStruct::solidNamesString() ); + CoupledSolidBase const & porousMaterial = getConstitutiveModel< CoupledSolidBase >( subRegion, solidName ); + porousMaterial.initializeState(); + + // 4.3 Initialize/update the relative permeability model using the initial phase volume fraction + // This is needed to handle relative permeability hysteresis + // Also, initialize the fluid model (to compute the initial total mass density, needed to compute the body force increment in + // coupled simulations) + // // Note: // - This must be called after updatePhaseVolumeFraction // - This step depends on phaseVolFraction @@ -2858,6 +2870,7 @@ void CompositionalMultiphaseBase::implicitStepComplete( real64 const & time, CapillaryPressureBase const & capPressureMaterial = getConstitutiveModel< CapillaryPressureBase >( subRegion, capPressName ); capPressureMaterial.saveConvergedRockState( porosity, permeability ); + capPressureMaterial.saveConvergedPhaseVolFractionState(phaseVolFrac); } // Step 6: if the thermal option is on, send the converged porosity and phase volume fraction to the thermal conductivity model diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseBase.hpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseBase.hpp index 227055bf3ed..a03fbf63a99 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseBase.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseBase.hpp @@ -20,6 +20,11 @@ #ifndef GEOS_PHYSICSSOLVERS_FLUIDFLOW_COMPOSITIONALMULTIPHASEBASE_HPP_ #define GEOS_PHYSICSSOLVERS_FLUIDFLOW_COMPOSITIONALMULTIPHASEBASE_HPP_ +#include "common/DataLayouts.hpp" +#include "constitutive/fluid/multifluid/Layouts.hpp" +#include "constitutive/relativePermeability/Layouts.hpp" +#include "constitutive/capillaryPressure/Layouts.hpp" +#include "fieldSpecification/FieldSpecificationManager.hpp" #include "physicsSolvers/fluidFlow/FlowSolverBase.hpp" #include "common/DataLayouts.hpp" #include "constitutive/fluid/multifluid/Layouts.hpp" diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp index 5b60a07045d..5fc1155a274 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ImmiscibleMultiphaseFlow.cpp @@ -237,24 +237,73 @@ } FaceElementSubRegion const & faceSubRegion = faceRegion.getUniqueSubRegion< FaceElementSubRegion >(); - FixedToManyElementRelation const & faceElementsToCells = faceSubRegion.getToCellRelation(); - - std::function< std::tuple< CellElementSubRegion *, CellElementSubRegion * >(localIndex) > getSubregions = [&]( localIndex surfaceSubRegionIndex ) -> std::tuple< CellElementSubRegion *, + FixedToManyElementRelation const & faceElementsToCells = faceSubRegion.getToCellRelation(); + + // Precompute numRegions once (it's constant for all face elements) + localIndex const numRegions = elemManager.numRegions(); + constexpr int MAX_REASONABLE_REGION_INDEX = 100000; + + std::function< std::tuple< CellElementSubRegion *, CellElementSubRegion * >(localIndex) > getSubregions = [&]( localIndex surfaceSubRegionIndex ) -> std::tuple< CellElementSubRegion *, CellElementSubRegion * > - { - - int regionIdx0 = faceElementsToCells.m_toElementRegion[surfaceSubRegionIndex][0]; - int regionIdx1 = faceElementsToCells.m_toElementRegion[surfaceSubRegionIndex][1]; - int subRegionIdx0 = faceElementsToCells.m_toElementSubRegion[surfaceSubRegionIndex][0]; - int subRegionIdx1 = faceElementsToCells.m_toElementSubRegion[surfaceSubRegionIndex][1]; - - CellElementRegion & region0 = elemManager.getRegion< CellElementRegion >( regionIdx0 ); - CellElementRegion & region1 = elemManager.getRegion< CellElementRegion >( regionIdx1 ); - - CellElementSubRegion * subRegion0 = ®ion0.getSubRegion< CellElementSubRegion >( subRegionIdx0 ); - CellElementSubRegion * subRegion1 = ®ion1.getSubRegion< CellElementSubRegion >( subRegionIdx1 ); - return std::make_tuple( subRegion0, subRegion1 ); - }; + { + + int regionIdx0 = faceElementsToCells.m_toElementRegion[surfaceSubRegionIndex][0]; + int regionIdx1 = faceElementsToCells.m_toElementRegion[surfaceSubRegionIndex][1]; + int subRegionIdx0 = faceElementsToCells.m_toElementSubRegion[surfaceSubRegionIndex][0]; + int subRegionIdx1 = faceElementsToCells.m_toElementSubRegion[surfaceSubRegionIndex][1]; + + // Fast validation checks (ordered from cheapest to most expensive) + if( regionIdx0 < 0 || regionIdx1 < 0 || + subRegionIdx0 < 0 || subRegionIdx1 < 0 ) + { + return std::make_tuple( nullptr, nullptr ); + } + + if( regionIdx0 > MAX_REASONABLE_REGION_INDEX || regionIdx1 > MAX_REASONABLE_REGION_INDEX ) + { + return std::make_tuple( nullptr, nullptr ); + } + + if( static_cast< localIndex >( regionIdx0 ) >= numRegions || + static_cast< localIndex >( regionIdx1 ) >= numRegions ) + { + return std::make_tuple( nullptr, nullptr ); + } + + // Try to get regions - they might not exist on this MPI rank even if index is in range + ElementRegionBase * region0BasePtr = nullptr; + ElementRegionBase * region1BasePtr = nullptr; + + try + { + region0BasePtr = &elemManager.getRegion< ElementRegionBase >( regionIdx0 ); + region1BasePtr = &elemManager.getRegion< ElementRegionBase >( regionIdx1 ); + } + catch( std::exception const & ) + { + return std::make_tuple( nullptr, nullptr ); + } + + // Check if they are CellElementRegion (interface conditions only apply to cell-to-cell interfaces) + CellElementRegion * cellRegion0 = dynamic_cast< CellElementRegion * >( region0BasePtr ); + CellElementRegion * cellRegion1 = dynamic_cast< CellElementRegion * >( region1BasePtr ); + + if( cellRegion0 == nullptr || cellRegion1 == nullptr ) + { + return std::make_tuple( nullptr, nullptr ); + } + + // Validate subregion indices before accessing + if( static_cast< localIndex >( subRegionIdx0 ) >= cellRegion0->numSubRegions() || + static_cast< localIndex >( subRegionIdx1 ) >= cellRegion1->numSubRegions() ) + { + return std::make_tuple( nullptr, nullptr ); + } + + CellElementSubRegion * subRegion0 = &cellRegion0->getSubRegion< CellElementSubRegion >( subRegionIdx0 ); + CellElementSubRegion * subRegion1 = &cellRegion1->getSubRegion< CellElementSubRegion >( subRegionIdx1 ); + return std::make_tuple( subRegion0, subRegion1 ); + }; // std::tuple< CellElementSubRegion *, CellElementSubRegion * > subRegionPair = getSubregions( surfaceRegionIndex ); // CellElementSubRegion * subRegion0 = std::get< 0 >( subRegionPair ); @@ -279,41 +328,40 @@ // m_interfaceConstitutivePairs[surfaceRegionIndex][0] = std::make_tuple( relPerm0, capPressure0, fluid0 ); // m_interfaceConstitutivePairs[surfaceRegionIndex][1] = std::make_tuple( relPerm1, capPressure1, fluid1 ); - // Find a representative face element in this surface region with two adjacent cells -localIndex fei = -1; + // Find a representative face element that connects two CellElementRegion objects +// (not SurfaceElementRegion, which we don't handle for interface conditions) +CellElementSubRegion * subRegion0 = nullptr; +CellElementSubRegion * subRegion1 = nullptr; +bool foundValidFei = false; -// Prefer face element 0 if valid; otherwise scan -if( faceElementsToCells.size() > 0 ) +// Single loop to find a valid face element (avoids redundant scanning) +for( localIndex i = 0; i < faceElementsToCells.size(); ++i ) { - // Check if face element 0 has two adjacent cells - if( faceElementsToCells.m_toElementRegion[0].size() >= 2 ) + // Quick check: must have two adjacent cells with non-negative region indices + if( faceElementsToCells.m_toElementRegion[i].size() >= 2 && + faceElementsToCells.m_toElementRegion[i][0] >= 0 && + faceElementsToCells.m_toElementRegion[i][1] >= 0 ) { - fei = 0; - } - else - { - // Scan to find the first interior face element with two neighbors - for( localIndex i = 1; i < faceElementsToCells.size(); ++i ) + std::tuple< CellElementSubRegion *, CellElementSubRegion * > subRegionPair = getSubregions( i ); + CellElementSubRegion * testSubRegion0 = std::get< 0 >( subRegionPair ); + CellElementSubRegion * testSubRegion1 = std::get< 1 >( subRegionPair ); + + if( testSubRegion0 != nullptr && testSubRegion1 != nullptr ) { - if( faceElementsToCells.m_toElementRegion[i].size() >= 2 ) - { - fei = i; - break; - } + subRegion0 = testSubRegion0; + subRegion1 = testSubRegion1; + foundValidFei = true; + break; } } } -// If no valid face element, skip this surface region -if( fei < 0 ) +// If no valid face element connecting two CellElementRegion objects, skip this surface region +if( !foundValidFei ) { continue; } -std::tuple< CellElementSubRegion *, CellElementSubRegion * > subRegionPair = getSubregions( fei ); -CellElementSubRegion * subRegion0 = std::get< 0 >( subRegionPair ); -CellElementSubRegion * subRegion1 = std::get< 1 >( subRegionPair ); - // get constitutives by type and name: relPerms, capPressures, Fluids (three pointers) std::string & relPermName0 = subRegion0->getReference< std::string >( viewKeyStruct::relPermNamesString()); std::string & relPermName1 = subRegion1->getReference< std::string >( viewKeyStruct::relPermNamesString()); @@ -548,19 +596,20 @@ m_interfaceConstitutivePairs[surfaceRegionIndex][1] = std::make_tuple( relPerm1, // - This step depends on porosity and permeability if( m_hasCapPressure ) { - // initialized porosity - arrayView2d< real64 const > const porosity = porousMaterial.getPorosity(); - - string const & permName = subRegion.template getReference< string >( viewKeyStruct::permeabilityNamesString() ); - PermeabilityBase const & permeabilityMaterial = getConstitutiveModel< PermeabilityBase >( subRegion, permName ); - // initialized permeability - arrayView3d< real64 const > const permeability = permeabilityMaterial.permeability(); - - string const & capPressureName = subRegion.template getReference< string >( viewKeyStruct::capPressureNamesString() ); - CapillaryPressureBase const & capPressureMaterial = - getConstitutiveModel< CapillaryPressureBase >( subRegion, capPressureName ); - capPressureMaterial.initializeRockState( porosity, permeability ); // this needs to happen before calling updateCapPressureModel - updateCapPressureModel( subRegion ); + // initialized porosity + arrayView2d< real64 const > const porosity = porousMaterial.getPorosity(); + + string const & permName = subRegion.template getReference< string >( viewKeyStruct::permeabilityNamesString() ); + PermeabilityBase const & permeabilityMaterial = getConstitutiveModel< PermeabilityBase >( subRegion, permName ); + // initialized permeability + arrayView3d< real64 const > const permeability = permeabilityMaterial.permeability(); + + string const & capPressureName = subRegion.template getReference< string >( viewKeyStruct::capPressureNamesString() ); + CapillaryPressureBase const & capPressureMaterial = + getConstitutiveModel< CapillaryPressureBase >( subRegion, capPressureName ); + capPressureMaterial.initializeRockState( porosity, permeability ); // this needs to happen before calling updateCapPressureModel + capPressureMaterial.saveConvergedPhaseVolFractionState( phaseVolFrac ); + updateCapPressureModel( subRegion ); } // 4.5 Update the phase mobility @@ -777,59 +826,42 @@ m_interfaceConstitutivePairs[surfaceRegionIndex][1] = std::make_tuple( relPerm1, MeshLevel & mesh, string_array const & regionNames ) { - if( m_hasCapPressure ) - { - mesh.getElemManager().forElementSubRegions( regionNames, + if( m_hasCapPressure ) + { + // Get the first subregion to pass to the kernel factory (only used for domainSize, not for filtering connections) + ElementSubRegionBase const * firstSubRegion = nullptr; + mesh.getElemManager().forElementSubRegions( regionNames, [&]( localIndex const, - ElementSubRegionBase & subRegion ) // Check if you need this. - { - // // Capillary pressure wrapper - // string const & cappresName = subRegion.getReference< string >( viewKeyStruct::capPressureNamesString() ); - // BrooksCoreyCapillaryPressure & capPressure = getConstitutiveModel< BrooksCoreyCapillaryPressure >( subRegion, cappresName ); - // CapillaryPressureBase * capPressure1 = &getConstitutiveModel< CapillaryPressureBase >( subRegion, cappresName ); - // BrooksCoreyCapillaryPressure::KernelWrapper capPresWrapper = capPressure.createKernelWrapper(); - - // // Relative permeability wrapper - // string const & relPermName = subRegion.getReference< string >( viewKeyStruct::relPermNamesString() ); - // BrooksCoreyRelativePermeability & relPerm = getConstitutiveModel< BrooksCoreyRelativePermeability >( subRegion, relPermName ); - // RelativePermeabilityBase * relPerm1 = &getConstitutiveModel< RelativePermeabilityBase >( subRegion, relPermName ); - // BrooksCoreyRelativePermeability::KernelWrapper relPermWrapper = relPerm.createKernelWrapper(); - - // // fluid - // string const & fluidName = subRegion.getReference< string >( viewKeyStruct::fluidNamesString() ); - // TwoPhaseImmiscibleFluid * fluid = &getConstitutiveModel< TwoPhaseImmiscibleFluid >( subRegion, fluidName ); - - // // m_interfaceConstitutivePairs[0][0] = std::make_tuple( relPerm1, capPressure1, fluid ); - // // m_interfaceConstitutivePairs[0][1] = std::make_tuple( relPerm1, capPressure1, fluid ); - - // auto interfaceConstitutivePairs_temp = std::make_tuple( relPerm1, capPressure1, fluid ); - - fluxApprox.forAllStencils( mesh, [&]( auto & stencil ) - { - typename TYPEOFREF( stencil ) ::KernelWrapper stencilWrapper = stencil.createKernelWrapper(); - immiscibleMultiphaseKernels:: - FluxComputeKernelFactory::createAndLaunch< parallelDevicePolicy<> >( m_numPhases, - dofManager.rankOffset(), - dofKey, - m_hasCapPressure, - m_useTotalMassEquation, - m_gravityDensityScheme == GravityDensityScheme::PhasePresence, - getName(), - mesh.getElemManager(), - stencilWrapper, - // capPresWrapper, - // relPermWrapper, - m_interfaceFaceSetNames, - m_interfaceConstitutivePairs, - m_interfaceRegionByConnector, - // interfaceConstitutivePairs_temp, - subRegion, - dt, - localMatrix.toViewConstSizes(), - localRhs.toView() ); - } ); - } ); - } + ElementSubRegionBase const & subRegion ) + { + if( firstSubRegion == nullptr ) + { + firstSubRegion = &subRegion; + } + } ); + + fluxApprox.forAllStencils( mesh, [&]( auto & stencil ) + { + typename TYPEOFREF( stencil ) ::KernelWrapper stencilWrapper = stencil.createKernelWrapper(); + immiscibleMultiphaseKernels:: + FluxComputeKernelFactory::createAndLaunch< parallelDevicePolicy<> >( m_numPhases, + dofManager.rankOffset(), + dofKey, + m_hasCapPressure, + m_useTotalMassEquation, + m_gravityDensityScheme == GravityDensityScheme::PhasePresence, + getName(), + mesh.getElemManager(), + stencilWrapper, + m_interfaceFaceSetNames, + m_interfaceConstitutivePairs, + m_interfaceRegionByConnector, + *firstSubRegion, + dt, + localMatrix.toViewConstSizes(), + localRhs.toView() ); + } ); + } else { fluxApprox.forAllStencils( mesh, [&]( auto & stencil ) @@ -1509,17 +1541,18 @@ m_interfaceConstitutivePairs[surfaceRegionIndex][1] = std::make_tuple( relPerm1, // note: this is needed when the capillary pressure depends on porosity and permeability (Leverett J-function for instance) if( m_hasCapPressure ) { - arrayView2d< real64 const > const porosity = porousMaterial.getPorosity(); - - string const & permName = subRegion.getReference< string >( viewKeyStruct::permeabilityNamesString() ); - PermeabilityBase const & permeabilityMaterial = - getConstitutiveModel< PermeabilityBase >( subRegion, permName ); - arrayView3d< real64 const > const permeability = permeabilityMaterial.permeability(); - - string const & capPressName = subRegion.getReference< string >( viewKeyStruct::capPressureNamesString() ); - CapillaryPressureBase const & capPressureMaterial = - getConstitutiveModel< CapillaryPressureBase >( subRegion, capPressName ); - capPressureMaterial.saveConvergedRockState( porosity, permeability ); + arrayView2d< real64 const > const porosity = porousMaterial.getPorosity(); + + string const & permName = subRegion.getReference< string >( viewKeyStruct::permeabilityNamesString() ); + PermeabilityBase const & permeabilityMaterial = + getConstitutiveModel< PermeabilityBase >( subRegion, permName ); + arrayView3d< real64 const > const permeability = permeabilityMaterial.permeability(); + + string const & capPressName = subRegion.getReference< string >( viewKeyStruct::capPressureNamesString() ); + CapillaryPressureBase const & capPressureMaterial = + getConstitutiveModel< CapillaryPressureBase >( subRegion, capPressName ); + capPressureMaterial.saveConvergedRockState( porosity, permeability ); + capPressureMaterial.saveConvergedPhaseVolFractionState( phaseVolFrac ); } } ); } ); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp index f9535bbadba..5a228a4344d 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp @@ -33,6 +33,7 @@ #include "constitutive/capillaryPressure/CapillaryPressureBase.hpp" #include "constitutive/capillaryPressure/JFunctionCapillaryPressure.hpp" #include "constitutive/capillaryPressure/TableCapillaryPressure.hpp" + #include "constitutive/capillaryPressure/TableCapillaryPressureHysteresis.hpp" #include "constitutive/permeability/PermeabilityBase.hpp" #include "constitutive/permeability/PermeabilityFields.hpp" #include "constitutive/relativePermeability/RelativePermeabilityBase.hpp" @@ -72,10 +73,12 @@ using namespace constitutive; GEOS_HOST_DEVICE inline static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< real64 > pressures, stdVector< real64 > JFMultipliers, stdVector< real64 > trappedSats1, - stdVector< real64 > trappedSats2, stdVector< real64 > transHat, stdVector< real64 > dTransHat_dP, stdVector< real64 > gravCoefHat, stdVector< real64 > gravCoef, + stdVector< real64 > trappedSats2, stdVector< fields::cappres::ModeIndexType> modes, stdVector< real64 > transHat, stdVector< real64 > dTransHat_dP, stdVector< real64 > gravCoefHat, stdVector< real64 > gravCoef, stdVector< real64 > cellCenterDuT, stdVector< real64 > cellCenterDens, stdVector< real64 > cellCenterDens_dP, std::vector< RelativePermeabilityBase * > relPerms, std::vector< CapillaryPressureBase * > capPressures, - std::vector< TwoPhaseImmiscibleFluid * > fluids, std::vector< real64 > &phi, std::vector< real64 > &grad_phi_P, std::vector< real64 > &grad_phi_S, bool &converged ) + std::vector< TwoPhaseImmiscibleFluid * > fluids, std::vector< real64 > &phi, std::vector< real64 > &grad_phi_P, std::vector< real64 > &grad_phi_S, bool &converged, + stdVector< real64 > const & phaseMaxHistVolFrac1, stdVector< real64 > const & phaseMinHistVolFrac1, + stdVector< real64 > const & phaseMaxHistVolFrac2, stdVector< real64 > const & phaseMinHistVolFrac2 ) { // getting wrappers: @@ -102,7 +105,7 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< auto fluidWrapper1 = fluids[0]->createKernelWrapper(); auto fluidWrapper2 = fluids[1]->createKernelWrapper(); - // Create an output file stream object (ofstream) for analyzing the local solver's performance + std::ofstream outFile( "iterations2.csv" ); @@ -149,15 +152,29 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< outFile << ","; outFile << "Cn_beta"; outFile << ","; - outFile << "Pc1_ip0"; + outFile << "transHats0"; + outFile << ","; + outFile << "transHats1"; + outFile << ","; + outFile << "gravCoefHats"; + outFile << ","; + outFile << "gravCoef0"; outFile << ","; - outFile << "Pc1_ip1"; + outFile << "gravCoef1"; outFile << ","; - outFile << "S_alpha"; + outFile << "uT"; outFile << ","; - outFile << "S_beta"; + outFile << "duT_dP0"; + outFile << ","; + outFile << "duT_dS0"; + outFile << ","; + outFile << "duT_dP1"; + outFile << ","; + outFile << "duT_dS1"; outFile << std::endl; + + // nonlinear solver's parameters real64 tol = 1.0e-9; int max_iter = 50; @@ -175,7 +192,9 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< StackArray< real64, 3, 2, constitutive::cappres::LAYOUT_CAPPRES > capPres1( 1, 1, 2 ); StackArray< real64, 4, 4, constitutive::cappres::LAYOUT_CAPPRES_DS > dPhaseVolFrac_dCapPres1( 1, 1, 2, 2 ); StackArray< real64, 4, 4, constitutive::cappres::LAYOUT_CAPPRES_DS > dCapPres1_dPhaseVolFrac( 1, 1, 2, 2 ); + StackArray< real64, 3, 2, constitutive::relperm::LAYOUT_RELPERM > trappedVolFrac1( 1, 1, 2 ); StackArray< real64, 2, 2, immiscibleFlow::LAYOUT_PHASE > facePhaseVolFrac1( 1, 2 ); + StackArray< real64, 3, 2, constitutive::relperm::LAYOUT_RELPERM > faceTrappedVolFrac1( 1, 1, 2 ); StackArray< real64, 3, 2, constitutive::cappres::LAYOUT_CAPPRES > faceCapPres1( 1, 1, 2 ); StackArray< real64, 4, 4, constitutive::cappres::LAYOUT_CAPPRES_DS > dfacePhaseVolFrac_dCapPres1( 1, 1, 2, 2 ); StackArray< real64, 4, 4, constitutive::cappres::LAYOUT_CAPPRES_DS > dCapPres1_dfacePhaseVolFrac( 1, 1, 2, 2 ); @@ -183,13 +202,68 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< StackArray< real64, 3, 2, constitutive::cappres::LAYOUT_CAPPRES > capPres2( 1, 1, 2 ); StackArray< real64, 4, 4, constitutive::cappres::LAYOUT_CAPPRES_DS > dPhaseVolFrac_dCapPres2( 1, 1, 2, 2 ); StackArray< real64, 4, 4, constitutive::cappres::LAYOUT_CAPPRES_DS > dCapPres2_dPhaseVolFrac( 1, 1, 2, 2 ); + StackArray< real64, 3, 2, constitutive::relperm::LAYOUT_RELPERM > trappedVolFrac2( 1, 1, 2 ); StackArray< real64, 2, 2, immiscibleFlow::LAYOUT_PHASE > facePhaseVolFrac2( 1, 2 ); + StackArray< real64, 3, 2, constitutive::relperm::LAYOUT_RELPERM > faceTrappedVolFrac2( 1, 1, 2 ); StackArray< real64, 3, 2, constitutive::cappres::LAYOUT_CAPPRES > faceCapPres2( 1, 1, 2 ); StackArray< real64, 4, 4, constitutive::cappres::LAYOUT_CAPPRES_DS > dfacePhaseVolFrac_dCapPres2( 1, 1, 2, 2 ); StackArray< real64, 4, 4, constitutive::cappres::LAYOUT_CAPPRES_DS > dCapPres2_dfacePhaseVolFrac( 1, 1, 2, 2 ); StackArray< real64, 1, 2 > JFunc1( 2 ); StackArray< real64, 1, 2 > JFunc2( 2 ); + + StackArray< real64, 2, 2, immiscibleFlow::LAYOUT_PHASE > phaseMaxHistoricalVolFraction1( 1, 2 ); + StackArray< real64, 2, 2, immiscibleFlow::LAYOUT_PHASE > phaseMinHistoricalVolFraction1( 1, 2 ); + StackArray< real64, 2, 2, immiscibleFlow::LAYOUT_PHASE > phaseMaxHistoricalVolFraction2( 1, 2 ); + StackArray< real64, 2, 2, immiscibleFlow::LAYOUT_PHASE > phaseMinHistoricalVolFraction2( 1, 2 ); + + if( phaseMaxHistVolFrac1.size() >= 2 && phaseMaxHistVolFrac1[0] >= 0.0 ) + { + + phaseMaxHistoricalVolFraction1[0][0] = phaseMaxHistVolFrac1[0]; + phaseMaxHistoricalVolFraction1[0][1] = phaseMaxHistVolFrac1[1]; + phaseMinHistoricalVolFraction1[0][0] = phaseMinHistVolFrac1[0]; + phaseMinHistoricalVolFraction1[0][1] = phaseMinHistVolFrac1[1]; + } + else + { + + phaseMaxHistoricalVolFraction1[0][0] = saturations[0]; + phaseMaxHistoricalVolFraction1[0][1] = 1.0 - saturations[0]; + phaseMinHistoricalVolFraction1[0][0] = saturations[0]; + phaseMinHistoricalVolFraction1[0][1] = 1.0 - saturations[0]; + } + + if( phaseMaxHistVolFrac2.size() >= 2 && phaseMaxHistVolFrac2[0] >= 0.0 ) + { + + phaseMaxHistoricalVolFraction2[0][0] = phaseMaxHistVolFrac2[0]; + phaseMaxHistoricalVolFraction2[0][1] = phaseMaxHistVolFrac2[1]; + phaseMinHistoricalVolFraction2[0][0] = phaseMinHistVolFrac2[0]; + phaseMinHistoricalVolFraction2[0][1] = phaseMinHistVolFrac2[1]; + } + else + + phaseMaxHistoricalVolFraction2[0][0] = saturations[1]; + phaseMaxHistoricalVolFraction2[0][1] = 1.0 - saturations[1]; + phaseMinHistoricalVolFraction2[0][0] = saturations[1]; + phaseMinHistoricalVolFraction2[0][1] = 1.0 - saturations[1]; + } + + // compute relative permeability for both cell centers: + + trappedVolFrac1[0][0][0] = trappedSats1[0]; + trappedVolFrac1[0][0][1] = trappedSats1[1]; + + trappedVolFrac2[0][0][0] = trappedSats2[0]; + trappedVolFrac2[0][0][1] = trappedSats2[1]; + + faceTrappedVolFrac1[0][0][0] = trappedSats1[0]; + faceTrappedVolFrac1[0][0][1] = trappedSats1[1]; + + faceTrappedVolFrac2[0][0][0] = trappedSats2[0]; + faceTrappedVolFrac2[0][0][1] = trappedSats2[1]; + phaseVolFrac1[0][0] = saturations[0]; phaseVolFrac1[0][1] = 1.0 - saturations[0]; @@ -238,6 +312,74 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< Pc1_max = faceCapPres1[0][0][0]; } + else if constexpr (std::is_same_v< T1, TableCapillaryPressureHysteresis >) { + capPresWrapper1.compute( phaseVolFrac1[0], + phaseMaxHistoricalVolFraction1[0], + phaseMinHistoricalVolFraction1[0], + trappedVolFrac1[0][0], + capPres1[0][0], + dCapPres1_dPhaseVolFrac[0][0], + modes[0] ); + + + facePhaseVolFrac1[0][1] = 0.0; + facePhaseVolFrac1[0][0] = 1.0; + capPresWrapper1.compute( facePhaseVolFrac1[0], + phaseMaxHistoricalVolFraction1[0], + phaseMinHistoricalVolFraction1[0], + faceTrappedVolFrac1[0][0], + faceCapPres1[0][0], + dCapPres1_dfacePhaseVolFrac[0][0], + modes[0] ); + Pc1_min = faceCapPres1[0][0][0]; + + facePhaseVolFrac1[0][1] = 1.0; + facePhaseVolFrac1[0][0] = 0.0; + capPresWrapper1.compute( facePhaseVolFrac1[0], + phaseMaxHistoricalVolFraction1[0], + phaseMinHistoricalVolFraction1[0], + faceTrappedVolFrac1[0][0], + faceCapPres1[0][0], + dCapPres1_dfacePhaseVolFrac[0][0], + modes[0] ); + Pc1_max = faceCapPres1[0][0][0]; + + // For hysteresis models, also evaluate at historical saturation range endpoints + // to ensure we capture the full range of the current curve + if (phaseMinHistoricalVolFraction1[0][0] >= 0.0 && phaseMaxHistoricalVolFraction1[0][0] >= 0.0) { + // Evaluate at min historical saturation + real64 const S_min_hist = phaseMinHistoricalVolFraction1[0][0]; + if (S_min_hist > 0.0 && S_min_hist < 1.0) { + facePhaseVolFrac1[0][0] = S_min_hist; + facePhaseVolFrac1[0][1] = 1.0 - S_min_hist; + capPresWrapper1.compute( facePhaseVolFrac1[0], + phaseMaxHistoricalVolFraction1[0], + phaseMinHistoricalVolFraction1[0], + faceTrappedVolFrac1[0][0], + faceCapPres1[0][0], + dCapPres1_dfacePhaseVolFrac[0][0], + modes[0] ); + Pc1_min = LvArray::math::min(Pc1_min, faceCapPres1[0][0][0]); + Pc1_max = LvArray::math::max(Pc1_max, faceCapPres1[0][0][0]); + } + + // Evaluate at max historical saturation + real64 const S_max_hist = phaseMaxHistoricalVolFraction1[0][0]; + if (S_max_hist > 0.0 && S_max_hist < 1.0) { + facePhaseVolFrac1[0][0] = S_max_hist; + facePhaseVolFrac1[0][1] = 1.0 - S_max_hist; + capPresWrapper1.compute( facePhaseVolFrac1[0], + phaseMaxHistoricalVolFraction1[0], + phaseMinHistoricalVolFraction1[0], + faceTrappedVolFrac1[0][0], + faceCapPres1[0][0], + dCapPres1_dfacePhaseVolFrac[0][0], + modes[0] ); + Pc1_min = LvArray::math::min(Pc1_min, faceCapPres1[0][0][0]); + Pc1_max = LvArray::math::max(Pc1_max, faceCapPres1[0][0][0]); + } + } + } else { capPresWrapper1.compute( phaseVolFrac1[0], @@ -285,6 +427,74 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< Pc2_max = faceCapPres2[0][0][0]; } + else if constexpr (std::is_same_v< T2, TableCapillaryPressureHysteresis >) { + capPresWrapper2.compute( phaseVolFrac2[0], + phaseMaxHistoricalVolFraction2[0], + phaseMinHistoricalVolFraction2[0], + trappedVolFrac2[0][0], + capPres2[0][0], + dCapPres2_dPhaseVolFrac[0][0], + modes[1] ); + + + facePhaseVolFrac2[0][1] = 0.0; + facePhaseVolFrac2[0][0] = 1.0; + capPresWrapper2.compute( facePhaseVolFrac2[0], + phaseMaxHistoricalVolFraction2[0], + phaseMinHistoricalVolFraction2[0], + faceTrappedVolFrac2[0][0], + faceCapPres2[0][0], + dCapPres2_dfacePhaseVolFrac[0][0], + modes[1] ); + Pc2_min = faceCapPres2[0][0][0]; + + facePhaseVolFrac2[0][1] = 1.0; + facePhaseVolFrac2[0][0] = 0.0; + capPresWrapper2.compute( facePhaseVolFrac2[0], + phaseMaxHistoricalVolFraction2[0], + phaseMinHistoricalVolFraction2[0], + faceTrappedVolFrac2[0][0], + faceCapPres2[0][0], + dCapPres2_dfacePhaseVolFrac[0][0], + modes[1] ); + Pc2_max = faceCapPres2[0][0][0]; + + // For hysteresis models, also evaluate at historical saturation range endpoints + // to ensure we capture the full range of the current curve + if (phaseMinHistoricalVolFraction2[0][0] >= 0.0 && phaseMaxHistoricalVolFraction2[0][0] >= 0.0) { + // Evaluate at min historical saturation + real64 const S_min_hist = phaseMinHistoricalVolFraction2[0][0]; + if (S_min_hist > 0.0 && S_min_hist < 1.0) { + facePhaseVolFrac2[0][0] = S_min_hist; + facePhaseVolFrac2[0][1] = 1.0 - S_min_hist; + capPresWrapper2.compute( facePhaseVolFrac2[0], + phaseMaxHistoricalVolFraction2[0], + phaseMinHistoricalVolFraction2[0], + faceTrappedVolFrac2[0][0], + faceCapPres2[0][0], + dCapPres2_dfacePhaseVolFrac[0][0], + modes[1] ); + Pc2_min = LvArray::math::min(Pc2_min, faceCapPres2[0][0][0]); + Pc2_max = LvArray::math::max(Pc2_max, faceCapPres2[0][0][0]); + } + + // Evaluate at max historical saturation + real64 const S_max_hist = phaseMaxHistoricalVolFraction2[0][0]; + if (S_max_hist > 0.0 && S_max_hist < 1.0) { + facePhaseVolFrac2[0][0] = S_max_hist; + facePhaseVolFrac2[0][1] = 1.0 - S_max_hist; + capPresWrapper2.compute( facePhaseVolFrac2[0], + phaseMaxHistoricalVolFraction2[0], + phaseMinHistoricalVolFraction2[0], + faceTrappedVolFrac2[0][0], + faceCapPres2[0][0], + dCapPres2_dfacePhaseVolFrac[0][0], + modes[1] ); + Pc2_min = LvArray::math::min(Pc2_min, faceCapPres2[0][0][0]); + Pc2_max = LvArray::math::max(Pc2_max, faceCapPres2[0][0][0]); + } + } + } else { // evaluating cell-center Pc: @@ -311,37 +521,16 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< // Use of the relative permeability kernel wrapper - StackArray< real64, 3, 2, constitutive::relperm::LAYOUT_RELPERM > faceTrappedVolFrac1( 1, 1, 2 ); + StackArray< real64, 3, 2, constitutive::relperm::LAYOUT_RELPERM > faceRelPerm1( 1, 1, 2 ); StackArray< real64, 4, 4, constitutive::relperm::LAYOUT_RELPERM_DS > dfacePhaseRelPerm1_dPhaseVolFrac( 1, 1, 2, 2 ); - StackArray< real64, 3, 2, constitutive::relperm::LAYOUT_RELPERM > trappedVolFrac1( 1, 1, 2 ); StackArray< real64, 3, 2, constitutive::relperm::LAYOUT_RELPERM > relPerm1( 1, 1, 2 ); StackArray< real64, 4, 4, constitutive::relperm::LAYOUT_RELPERM_DS > dPhaseRelPerm1_dPhaseVolFrac( 1, 1, 2, 2 ); - StackArray< real64, 3, 2, constitutive::relperm::LAYOUT_RELPERM > faceTrappedVolFrac2( 1, 1, 2 ); StackArray< real64, 3, 2, constitutive::relperm::LAYOUT_RELPERM > faceRelPerm2( 1, 1, 2 ); StackArray< real64, 4, 4, constitutive::relperm::LAYOUT_RELPERM_DS > dfacePhaseRelPerm2_dPhaseVolFrac( 1, 1, 2, 2 ); - StackArray< real64, 3, 2, constitutive::relperm::LAYOUT_RELPERM > trappedVolFrac2( 1, 1, 2 ); StackArray< real64, 3, 2, constitutive::relperm::LAYOUT_RELPERM > relPerm2( 1, 1, 2 ); StackArray< real64, 4, 4, constitutive::relperm::LAYOUT_RELPERM_DS > dPhaseRelPerm2_dPhaseVolFrac( 1, 1, 2, 2 ); - StackArray< real64, 2, 2, immiscibleFlow::LAYOUT_PHASE > phaseMaxHistoricalVolFraction1( 1, 2 ); - StackArray< real64, 2, 2, immiscibleFlow::LAYOUT_PHASE > phaseMinHistoricalVolFraction1( 1, 2 ); - StackArray< real64, 2, 2, immiscibleFlow::LAYOUT_PHASE > phaseMaxHistoricalVolFraction2( 1, 2 ); - StackArray< real64, 2, 2, immiscibleFlow::LAYOUT_PHASE > phaseMinHistoricalVolFraction2( 1, 2 ); - - // compute relative permeability for both cell centers: - - trappedVolFrac1[0][0][0] = trappedSats1[0]; - trappedVolFrac1[0][0][1] = trappedSats1[1]; - - trappedVolFrac2[0][0][0] = trappedSats2[0]; - trappedVolFrac2[0][0][1] = trappedSats2[1]; - - faceTrappedVolFrac1[0][0][0] = trappedSats1[0]; - faceTrappedVolFrac1[0][0][1] = trappedSats1[1]; - - faceTrappedVolFrac2[0][0][0] = trappedSats2[0]; - faceTrappedVolFrac2[0][0][1] = trappedSats2[1]; using T5 = std::decay_t< decltype(castedRelPerm1) >; if constexpr (std::is_same_v< T5, constitutive::TableRelativePermeabilityHysteresis >) { @@ -561,6 +750,25 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< faceCapPres1[0][0], dCapPres1_dfacePhaseVolFrac[0][0] ); + } + else if constexpr (std::is_same_v< T3, TableCapillaryPressureHysteresis >) { + capPresWrapper1.computeInv( facePhaseVolFrac1[0], + phaseMaxHistoricalVolFraction1[0], + phaseMinHistoricalVolFraction1[0], + faceTrappedVolFrac1[0][0], + faceCapPres1[0][0], + dCapPres1_dfacePhaseVolFrac[0][0], + modes[0] ); + facePhaseVolFrac1[0][0] = fmin( 1.0, fmax( facePhaseVolFrac1[0][0], 0.0 )); + facePhaseVolFrac1[0][1] = fmin( 1.0, fmax( facePhaseVolFrac1[0][1], 0.0 )); + capPresWrapper1.compute( facePhaseVolFrac1[0], + phaseMaxHistoricalVolFraction1[0], + phaseMinHistoricalVolFraction1[0], + faceTrappedVolFrac1[0][0], + faceCapPres1[0][0], + dCapPres1_dfacePhaseVolFrac[0][0], + modes[0] ); + } else { @@ -592,6 +800,25 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< faceCapPres2[0][0], dCapPres2_dfacePhaseVolFrac[0][0] ); + } + else if constexpr (std::is_same_v< T4, TableCapillaryPressureHysteresis >) { + capPresWrapper2.computeInv( facePhaseVolFrac2[0], + phaseMaxHistoricalVolFraction2[0], + phaseMinHistoricalVolFraction2[0], + faceTrappedVolFrac2[0][0], + faceCapPres2[0][0], + dCapPres2_dfacePhaseVolFrac[0][0], + modes[1] ); + facePhaseVolFrac2[0][0] = fmin( 1.0, fmax( facePhaseVolFrac2[0][0], 0.0 )); + facePhaseVolFrac2[0][1] = fmin( 1.0, fmax( facePhaseVolFrac2[0][1], 0.0 )); + capPresWrapper2.compute( facePhaseVolFrac2[0], + phaseMaxHistoricalVolFraction2[0], + phaseMinHistoricalVolFraction2[0], + faceTrappedVolFrac2[0][0], + faceCapPres2[0][0], + dCapPres2_dfacePhaseVolFrac[0][0], + modes[1] ); + } else { @@ -1079,7 +1306,8 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< } // while check for BJ PPU - real64 constexpr eps2 = 1.0e-18; + real64 constexpr eps2 = 4.9304e-32; + // real64 constexpr eps2 = 0.0; // newton update dhalfFlux_dpc[0][0] = dhalfFlux1_dS[0][1]*dfacePhaseVolFrac_dCapPres1[0][0][0][0]; real64 dhalfFlux_dpc00 = dV1_dpc[0][1] - dG1_dpc[0][1] - dC1_dpc[0][1]; @@ -1110,6 +1338,38 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< // std::cout << "**********************ZeroJacobian*******************" << std::endl; // } converged = 1; + outFile << GEOS_FMT( "{:10.10e}", local_jacobian ); + outFile << GEOS_FMT( ",{:10.10e}", local_residual ); + outFile << GEOS_FMT( ",{:10.10e}", halfFluxVal[0][0] ); + outFile << GEOS_FMT( ",{:10.10e}", halfFluxVal[0][1] ); + outFile << GEOS_FMT( ",{:10.10e}", Pc_int_iterate ); + outFile << GEOS_FMT( ",{:10.10e}", faceCapPres1[0][0][0] ); + outFile << GEOS_FMT( ",{:10.10e}", faceCapPres2[0][0][0] ); + outFile << GEOS_FMT( ",{:10.10e}", halfFluxVal[1][0] ); + outFile << GEOS_FMT( ",{:10.10e}", halfFluxVal[1][1] ); + outFile << GEOS_FMT( ",{:10.10e}", viscous[0][0] ); + outFile << GEOS_FMT( ",{:10.10e}", viscous[1][0] ); + outFile << GEOS_FMT( ",{:10.10e}", viscous[0][1] ); + outFile << GEOS_FMT( ",{:10.10e}", viscous[1][1] ); + outFile << GEOS_FMT( ",{:10.10e}", bouyancy[0][0] ); + outFile << GEOS_FMT( ",{:10.10e}", bouyancy[1][0] ); + outFile << GEOS_FMT( ",{:10.10e}", bouyancy[0][1] ); + outFile << GEOS_FMT( ",{:10.10e}", bouyancy[1][1] ); + outFile << GEOS_FMT( ",{:10.10e}", capillarity[0][0] ); + outFile << GEOS_FMT( ",{:10.10e}", capillarity[1][0] ); + outFile << GEOS_FMT( ",{:10.10e}", capillarity[0][1] ); + outFile << GEOS_FMT( ",{:10.10e}", capillarity[1][1] ); + outFile << GEOS_FMT( ",{:10.10e}", transHat[0] ); + outFile << GEOS_FMT( ",{:10.10e}", transHat[1] ); + outFile << GEOS_FMT( ",{:10.10e}", gravCoefHat[0] ); + outFile << GEOS_FMT( ",{:10.10e}", gravCoef[0] ); + outFile << GEOS_FMT( ",{:10.10e}", gravCoef[1] ); + outFile << GEOS_FMT( ",{:10.10e}", uT ); + outFile << GEOS_FMT( ",{:10.10e}", duT_dP[0] ); + outFile << GEOS_FMT( ",{:10.10e}", duT_dS[0] ); + outFile << GEOS_FMT( ",{:10.10e}", duT_dP[1] ); + outFile << GEOS_FMT( ",{:10.10e}", duT_dS[1] ); + outFile << std::endl; break; // Converged } // converged = 0; @@ -1130,7 +1390,7 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< else if( div > 1 ) { local_jacobian = 0.0; - std::cout << "**********************Diverged*******************" << std::endl; + iter = max_iter; } } @@ -1141,10 +1401,40 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< if( std::fabs( local_residual ) < tol ) { - // if( std::fabs( dhalfFlux_dpc[0][0] - dhalfFlux_dpc[0][1] ) < eps2 ) { - // std::cout << "**********************ZeroJacobian*******************" << std::endl; - // } + converged = 1; + outFile << GEOS_FMT( "{:10.10e}", local_jacobian ); + outFile << GEOS_FMT( ",{:10.10e}", local_residual ); + outFile << GEOS_FMT( ",{:10.10e}", halfFluxVal[0][0] ); + outFile << GEOS_FMT( ",{:10.10e}", halfFluxVal[0][1] ); + outFile << GEOS_FMT( ",{:10.10e}", Pc_int_iterate ); + outFile << GEOS_FMT( ",{:10.10e}", faceCapPres1[0][0][0] ); + outFile << GEOS_FMT( ",{:10.10e}", faceCapPres2[0][0][0] ); + outFile << GEOS_FMT( ",{:10.10e}", halfFluxVal[1][0] ); + outFile << GEOS_FMT( ",{:10.10e}", halfFluxVal[1][1] ); + outFile << GEOS_FMT( ",{:10.10e}", viscous[0][0] ); + outFile << GEOS_FMT( ",{:10.10e}", viscous[1][0] ); + outFile << GEOS_FMT( ",{:10.10e}", viscous[0][1] ); + outFile << GEOS_FMT( ",{:10.10e}", viscous[1][1] ); + outFile << GEOS_FMT( ",{:10.10e}", bouyancy[0][0] ); + outFile << GEOS_FMT( ",{:10.10e}", bouyancy[1][0] ); + outFile << GEOS_FMT( ",{:10.10e}", bouyancy[0][1] ); + outFile << GEOS_FMT( ",{:10.10e}", bouyancy[1][1] ); + outFile << GEOS_FMT( ",{:10.10e}", capillarity[0][0] ); + outFile << GEOS_FMT( ",{:10.10e}", capillarity[1][0] ); + outFile << GEOS_FMT( ",{:10.10e}", capillarity[0][1] ); + outFile << GEOS_FMT( ",{:10.10e}", capillarity[1][1] ); + outFile << GEOS_FMT( ",{:10.10e}", transHat[0] ); + outFile << GEOS_FMT( ",{:10.10e}", transHat[1] ); + outFile << GEOS_FMT( ",{:10.10e}", gravCoefHat[0] ); + outFile << GEOS_FMT( ",{:10.10e}", gravCoef[0] ); + outFile << GEOS_FMT( ",{:10.10e}", gravCoef[1] ); + outFile << GEOS_FMT( ",{:10.10e}", uT ); + outFile << GEOS_FMT( ",{:10.10e}", duT_dP[0] ); + outFile << GEOS_FMT( ",{:10.10e}", duT_dS[0] ); + outFile << GEOS_FMT( ",{:10.10e}", duT_dP[1] ); + outFile << GEOS_FMT( ",{:10.10e}", duT_dS[1] ); + outFile << std::endl; break; // Converged } @@ -1154,7 +1444,7 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< real64 sign = std::copysign(1.0, deltaPc); - deltaPc = fmin( fabs(deltaPc), max_dpc * 0.2 ); + deltaPc = fmin( fabs(deltaPc), max_dpc * 0.1 ); deltaPc *= sign; } @@ -1228,24 +1518,33 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< outFile << GEOS_FMT( ",{:10.10e}", capillarity[1][0] ); outFile << GEOS_FMT( ",{:10.10e}", capillarity[0][1] ); outFile << GEOS_FMT( ",{:10.10e}", capillarity[1][1] ); - outFile << GEOS_FMT( ",{:10.10e}", capPres1[0][0][0] ); - outFile << GEOS_FMT( ",{:10.10e}", capPres1[0][0][1] ); - outFile << GEOS_FMT( ",{:10.10e}", facePhaseVolFrac1[0][0] ); - outFile << GEOS_FMT( ",{:10.10e}", facePhaseVolFrac2[0][0] ); + outFile << GEOS_FMT( ",{:10.10e}", transHat[0] ); + outFile << GEOS_FMT( ",{:10.10e}", transHat[1] ); + outFile << GEOS_FMT( ",{:10.10e}", gravCoefHat[0] ); + outFile << GEOS_FMT( ",{:10.10e}", gravCoef[0] ); + outFile << GEOS_FMT( ",{:10.10e}", gravCoef[1] ); + outFile << GEOS_FMT( ",{:10.10e}", uT ); + outFile << GEOS_FMT( ",{:10.10e}", duT_dP[0] ); + outFile << GEOS_FMT( ",{:10.10e}", duT_dS[0] ); + outFile << GEOS_FMT( ",{:10.10e}", duT_dP[1] ); + outFile << GEOS_FMT( ",{:10.10e}", duT_dS[1] ); outFile << std::endl; iter++; } - + } // while loop + + if( converged ) { // Global derivatives: - real64 constexpr eps3 = 1.0e-18; + real64 constexpr eps3 = 4.9304e-32; + // real64 constexpr eps3 = 0.0; real64 const dPc_int_dS1 =(-1.0) * (dhalfFlux1_dS[0][0] + dhalfFlux_duT[0][0] * duT_dS[0] - dhalfFlux_duT[0][1] * duT_dS[0]) / (dhalfFlux_dpc[0][0] - dhalfFlux_dpc[0][1] + eps3); real64 const dPc_int_dS2 =(-1.0) * (dhalfFlux_duT[0][0] * duT_dS[1] - dhalfFlux2_dS[0][0] - dhalfFlux_duT[0][1] * duT_dS[1]) / (dhalfFlux_dpc[0][0] - dhalfFlux_dpc[0][1] + eps3); @@ -1267,7 +1566,8 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< fluxVal[1] = halfFluxVal[1][0] * density2[1]; } else { - std::cout << "**********************Diverged*******************" << std::endl; + + std::cout << "**********************Diverged*******************" << std::endl; } @@ -1284,8 +1584,7 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< grad_phi_S[2] = dFlux_dS[1][0]; grad_phi_S[3] = dFlux_dS[1][1]; - converged = 1; - GEOS_UNUSED_VAR( converged ); + // Close the file after writing outFile.close(); @@ -1338,7 +1637,7 @@ class FluxComputeKernelBase fields::twophaseimmisciblefluid::dPhaseViscosity >; using CapPressureAccessors = - StencilMaterialAccessors< BrooksCoreyCapillaryPressure, + StencilMaterialAccessors< CapillaryPressureBase, fields::cappres::phaseCapPressure, fields::cappres::dPhaseCapPressure_dPhaseVolFraction >; @@ -1867,6 +2166,16 @@ class FluxComputeKernel : public FluxComputeKernelBase // compute the flux and derivatives using upstream cell mobility fluxVal[ip] = mobility[ip] * potGrad; // F = M * DPhi + // DEBUG: Print flux computation for regular kernel + printf( "REGULAR_KERNEL_FLUX: iconn=%d, ip=%d, mobility[%d]=%.10e, potGrad=%.10e, fluxVal[%d]=%.10e\n", + static_cast(iconn), + static_cast(ip), + static_cast(ip), + mobility[ip], + potGrad, + static_cast(ip), + fluxVal[ip] ); + for( integer ke = 0; ke < 2; ++ke ) { dFlux_dP[ip][ke] *= mobility[ip]; // dF/dP = { M [ T + dT/dP1 * (P1 - P2) - drho/dP1 * T g (z1 - z2) - dT/dP1 * rho g (z1 - @@ -1890,6 +2199,15 @@ class FluxComputeKernel : public FluxComputeKernelBase } // populate local flux vector and derivatives + printf( "REGULAR_KERNEL_ACCUM: iconn=%d, ip=%d, k[0]=%d, k[1]=%d, fluxVal[%d]=%.10e, dt=%.10e, adding=%.10e\n", + static_cast(iconn), + static_cast(ip), + static_cast(k[0]), + static_cast(k[1]), + static_cast(ip), + fluxVal[ip], + m_dt, + m_dt * fluxVal[ip] ); stack.localFlux[k[0]*numEqn + ip] += m_dt * fluxVal[ip]; stack.localFlux[k[1]*numEqn + ip] -= m_dt * fluxVal[ip]; @@ -2517,8 +2835,10 @@ class FluxComputeInterfaceConditionKernel : public FluxComputeKernel< NUM_EQN, N // stdVector< real64 > JFMultipliers = {jFMultiplier[0][0], jFMultiplier[0][1]}; stdVector< real64 > JFMultipliers = {0.0, 0.0}; + // trappedSats will be extracted from models below and passed to local_solver stdVector< real64 > trappedSats1 = {0.0, 0.0}; stdVector< real64 > trappedSats2 = {0.0, 0.0}; + stdVector< fields::cappres::ModeIndexType> modes = {static_cast(0), static_cast(0)}; stdVector< real64 > transHats = {transHat[0], transHat[1]}; stdVector< real64 > dTransHats_dP = {dTransHat_dP[0], dTransHat_dP[1]}; stdVector< real64 > gravCoefHats = {gravCoefHat[0], gravCoefHat[1]}; @@ -2549,12 +2869,119 @@ std::vector< constitutive::TwoPhaseImmiscibleFluid * > fluids = { std::get<2>( pairArray[1] ) }; + // Extract historical volume fractions, trapped saturations, and mode from TableCapillaryPressureHysteresis models + // Initialize with sentinel values to indicate they haven't been set + // Use -1.0 as a sentinel value (invalid for saturations which are 0-1) + stdVector< real64 > phaseMaxHistoricalVolFraction1 = {-1.0, -1.0}; + stdVector< real64 > phaseMinHistoricalVolFraction1 = {-1.0, -1.0}; + stdVector< real64 > phaseMaxHistoricalVolFraction2 = {-1.0, -1.0}; + stdVector< real64 > phaseMinHistoricalVolFraction2 = {-1.0, -1.0}; + + // Trapped saturations are available in all capillary pressure models (via base class), + // but we only extract them when using hysteresis models since they're most meaningful there + // Initialize with sentinel values to indicate they haven't been set + stdVector< real64 > trappedSats1_extracted = {-1.0, -1.0}; + stdVector< real64 > trappedSats2_extracted = {-1.0, -1.0}; + + for( integer ke = 0; ke < 2; ++ke ) + { + constitutive::TableCapillaryPressureHysteresis * capPresHyst = + dynamic_cast(capPressures[ke]); + + if( capPresHyst != nullptr ) + { + // Get the mode for this cell + auto const & modeArray = capPresHyst->getField< fields::cappres::mode >().reference(); + if( sei[ke] < static_cast(modeArray.size()) ) + { + modes[ke] = static_cast(modeArray[sei[ke]]); + } + + // Get historical volume fractions for this cell + auto const & maxHistArray = capPresHyst->getField< fields::cappres::phaseMaxHistoricalVolFraction >().reference(); + auto const & minHistArray = capPresHyst->getField< fields::cappres::phaseMinHistoricalVolFraction >().reference(); + + if( sei[ke] < static_cast(maxHistArray.size(0)) && m_numPhases > 0 ) + { + for( integer ip = 0; ip < m_numPhases; ++ip ) + { + if( ke == 0 ) + { + phaseMaxHistoricalVolFraction1[ip] = maxHistArray[sei[ke]][ip]; + phaseMinHistoricalVolFraction1[ip] = minHistArray[sei[ke]][ip]; + } + else + { + phaseMaxHistoricalVolFraction2[ip] = maxHistArray[sei[ke]][ip]; + phaseMinHistoricalVolFraction2[ip] = minHistArray[sei[ke]][ip]; + } + } + } + + // Get trapped volume fractions for this cell + // Note: phaseTrappedVolFraction is available in all capillary pressure models (via base class) + auto const & trappedArray = capPresHyst->getField< fields::cappres::phaseTrappedVolFraction >().reference(); + + if( sei[ke] < static_cast(trappedArray.size(0)) && m_numPhases > 0 ) + { + for( integer ip = 0; ip < m_numPhases; ++ip ) + { + if( ke == 0 ) + { + trappedSats1_extracted[ip] = trappedArray[sei[ke]][0][ip]; // [element][subregion][phase] + } + else + { + trappedSats2_extracted[ip] = trappedArray[sei[ke]][0][ip]; + } + } + } + } + else + { + // For non-hysteresis models, we can still try to get trapped saturations if available + // but they're typically not meaningful for non-hysteresis models + // We'll extract them anyway in case they were set (e.g., for consistency) + auto const & trappedArray = capPressures[ke]->getField< fields::cappres::phaseTrappedVolFraction >().reference(); + + if( sei[ke] < static_cast(trappedArray.size(0)) && m_numPhases > 0 ) + { + for( integer ip = 0; ip < m_numPhases; ++ip ) + { + if( ke == 0 ) + { + trappedSats1_extracted[ip] = trappedArray[sei[ke]][0][ip]; + } + else + { + trappedSats2_extracted[ip] = trappedArray[sei[ke]][0][ip]; + } + } + } + } + } + stdVector< real64 > phi = {halfFluxVal[0][0], halfFluxVal[0][1]}; stdVector< real64 > grad_phi_P = {0.0, 0.0, 0.0, 0.0}; stdVector< real64 > grad_phi_S = {0.0, 0.0, 0.0, 0.0}; - local_solver( uT, saturations, pressures, JFMultipliers, trappedSats1, trappedSats2, transHats, dTransHats_dP, gravCoefHats, gravCoefs, - cellCenterDuTdS, cellCenterDens, cellCenterDens_dP, relPerms, capPressures, fluids, phi, grad_phi_P, grad_phi_S, converged ); + // // Debug: print if local_solver is being called + // printf( "DEBUG: local_solver called for iconn=%d, connectorHasInterfaceConditionQ=%d\n", + // static_cast(iconn), static_cast(connectorHasInterfaceConditionQ) ); + + // Use extracted trapped saturations if available, otherwise use defaults + if( trappedSats1_extracted[0] >= 0.0 ) + { + trappedSats1 = trappedSats1_extracted; + } + if( trappedSats2_extracted[0] >= 0.0 ) + { + trappedSats2 = trappedSats2_extracted; + } + + local_solver( uT, saturations, pressures, JFMultipliers, trappedSats1, trappedSats2, modes, transHats, dTransHats_dP, gravCoefHats, gravCoefs, + cellCenterDuTdS, cellCenterDens, cellCenterDens_dP, relPerms, capPressures, fluids, phi, grad_phi_P, grad_phi_S, converged, + phaseMaxHistoricalVolFraction1, phaseMinHistoricalVolFraction1, phaseMaxHistoricalVolFraction2, phaseMinHistoricalVolFraction2 ); fluxVal[0] = phi[0]; diff --git a/src/coreComponents/schema/schema.xsd.other b/src/coreComponents/schema/schema.xsd.other index e77cc9d197a..a3def28f6b5 100644 --- a/src/coreComponents/schema/schema.xsd.other +++ b/src/coreComponents/schema/schema.xsd.other @@ -3267,6 +3267,10 @@ A field can represent a physical variable. (pressure, temperature, global compos + + + + @@ -3276,7 +3280,11 @@ A field can represent a physical variable. (pressure, temperature, global compos +<<<<<<< HEAD +======= + +>>>>>>> Killough-PC_copy diff --git a/src/docs/doxygen/GeosxConfig.hpp b/src/docs/doxygen/GeosxConfig.hpp index 21b976a0d4c..a28bf2ae4ce 100644 --- a/src/docs/doxygen/GeosxConfig.hpp +++ b/src/docs/doxygen/GeosxConfig.hpp @@ -144,7 +144,7 @@ #define adiak_VERSION .. /// Version information for caliper -#define caliper_VERSION 2.8.0 +#define caliper_VERSION 2.4.0 /// Version information for Metis #define metis_VERSION 5.1.0 From 965dc6d42326e103c3f4822eebf07e519e2b01a2 Mon Sep 17 00:00:00 2001 From: Ammara-14 Date: Mon, 9 Feb 2026 13:40:19 -0800 Subject: [PATCH 104/104] Update ImmiscibleMultiphaseKernels.hpp --- .../immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp b/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp index 5a228a4344d..378048270f3 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/kernels/immiscibleMultiphase/ImmiscibleMultiphaseKernels.hpp @@ -243,7 +243,7 @@ static void local_solver( real64 uT, stdVector< real64 > saturations, stdVector< phaseMinHistoricalVolFraction2[0][1] = phaseMinHistVolFrac2[1]; } else - + { phaseMaxHistoricalVolFraction2[0][0] = saturations[1]; phaseMaxHistoricalVolFraction2[0][1] = 1.0 - saturations[1]; phaseMinHistoricalVolFraction2[0][0] = saturations[1];