Example#
In this section, we will walk trough the creation of a simple network, with two nodes and one pipe, to illustrate how to create a project and how to interpret the definitions available on Full API Reference.
The root level of a Description is always the class CaseDescription
which has the following attributes:
Note
This guide assumes the reader is familiar with Python 3.
class CaseDescription:
name: Optional[str] = None
physics: PhysicsDescription = PhysicsDescription()
time_options: TimeOptionsDescription = TimeOptionsDescription()
numerical_options: NumericalOptionsDescription = NumericalOptionsDescription()
ipr_models: IPRModelsDescription = IPRModelsDescription()
pvt_models: PvtModelsDescription = PvtModelsDescription()
tracers: TracersDescription = TracersDescription()
outputs: CaseOutputDescription = CaseOutputDescription()
pipes: List[PipeDescription] = []
nodes: List[NodeDescription] = []
wells: List[WellDescription] = []
materials: List[MaterialDescription] = []
walls: List[WallDescription] = []
In the following section, these steps will be covered:
How to configure the project options.
How to add a PVtModel.
How to add Nodes.
How to add Pipes.
How to add output curves.
Note
For the full reference check the Full API Reference
Project Options#
We will start the example by configuring the project options, as discussed in the previous section,
the root level of an ALFacase file is the CaseDescription and it has the following options:
class CaseDescription:
physics: PhysicsDescription = PhysicsDescription()
time_options: TimeOptionsDescription = TimeOptionsDescription()
numerical_options: NumericalOptionsDescription = NumericalOptionsDescription()
For this example, the application will be configured with the ALFAsim correlation package using a hydrodynamic model with two-phase and four fields, the time steps will be changed as well and the tolerance will be set to 1e-4
Example
from alfasim_sdk import (
CaseDescription,
PhysicsDescription,
NumericalOptionsDescription,
TimeOptionsDescription,
)
from barril.units import Scalar
CaseDescription(
name="basic_case",
physics=PhysicsDescription(
correlations_package=CorrelationPackageType.Alfasim,
hydrodynamic_model=HydrodynamicModelType.FourFields,
),
numerical_options=NumericalOptionsDescription(tolerance=1e-4),
time_options=TimeOptionsDescription(
minimum_timestep=Scalar(1e-4, "s"),
maximum_timestep=Scalar(0.5, "s"),
final_time=Scalar(1.0, "s"),
),
)
PVT Model#
The second step will add a PVT model to the project and configure it as the default PVT for the entire project.
The PvtModelsDescription class configures PVT models used in the project.
Each element in the project can have a PVT model assigned, however it is possible to configure a default model that will be used when an element doesn’t have an assigned PVT model. That default model is the model assigned to the default_model attribute.
For this example, a PVT model will be created from a .tab file. Path definitions inside the .alfacase
file are always relative for portability.
And for this, we need to populate the tables field with the PVT name and a file.
Note
Each PVT model name must be unique.
Check the PVTs section for a detailed description of each PVT type option.
Example
from alfasim_sdk import (
CaseDescription,
PvtModelsDescription,
)
CaseDescription(
# Omitting fields that configure option
pvt_models=PvtModelsDescription(
default_model="Pvt1",
tables={"Pvt1": "my_pvt_file.tab"},
),
)
Nodes#
The third step will add two different types of nodes: a mass source node and a pressure node.
Nodes are added over the nodes section of the CaseDescription.
The NodeDescription class configures several types of nodes
through the node_type field and their respective property fields.
For example:
When
node_typeisNodeCellType.MassSource,mass_source_propertieswill be taken in account.When
node_typeisNodeCellType.Pressure,pressure_propertieswill be taken in account.
The other properties not related to the node_type are read by the application, but are not considered for the solution.
Note
Check the Node section for a detailed description of each Node type.
Example
from alfasim_sdk import (
CaseDescription,
NodeDescription,
MassSourceNodePropertiesDescription,
PressureNodePropertiesDescription,
)
CaseDescription(
# Omitting fields that configure Options and Pvt
nodes=[
NodeDescription(
name="Inlet",
node_type=NodeCellType.MassSource,
mass_source_properties=MassSourceNodePropertiesDescription(
mass_flow_rates={
"gas": Scalar(0.0, "kg/s"),
"oil": Scalar(0.0, "kg/s"),
},
),
),
NodeDescription(
name="Outlet",
node_type=NodeCellType.Pressure,
pressure_properties=PressureNodePropertiesDescription(
pressure=Scalar(50.0, "bar"),
volume_fractions={
"gas": Scalar(1.0, "-"),
"oil": Scalar(1.0, "-"),
},
),
),
],
)
Pipes#
Let’s add a Pipe to the application through the pipes fields.
The pipes attribute accepts a list of PipeDescription definitions that connects two nodes.
The connection is defined by the source and target fields, and to configure them it is only necessary
to inform the name of the NodeDescription that will be used.
Note
Check the Pipe section for a detailed description of the attributes available.
Example
from alfasim_sdk import (
CaseDescription,
PipeDescription,
ProfileDescription,
LengthAndElevationDescription,
PipeSegmentsDescription,
)
CaseDescription(
# Omitting fields that configure Options, Pvt and Node
pipes=[
PipeDescription(
name="pipe",
source="Inlet",
target="Outlet",
profile=ProfileDescription(
length_and_elevation=LengthAndElevationDescription(
length=Array([0.0, 15.0, 30.0, 30.0, 15.0], "m"),
elevation=Array([0.0, 15.0, 30.0, 30.0, 15.0], "m"),
),
),
segments=PipeSegmentsDescription(
start_positions=Array([0.0], "m"),
diameters=Array([0.1], "m"),
roughnesses=Array([5e-05], "m"),
),
),
],
)
Output#
The final step for our example will configure a trend and a profile for our project.
As indicated on CaseDescription, the outputs field must be filled with
a CaseOutputDescription instance which configures trends
and profiles.
Note
Check the Outputs section for a detailed description of each output type, that shows all the available curves that can be used.
Example
from alfasim_sdk import (
CaseDescription,
CaseOutputDescription,
TrendsOutputDescription,
PositionalPipeTrendDescription,
OutputAttachmentLocation,
ProfileOutputDescription,
)
CaseDescription(
# Omitting fields that configure Options, Pvt, Node and Pipes
outputs=CaseOutputDescription(
trends=TrendsOutputDescription(
positional_pipe_trends=[
PositionalPipeTrendDescription(
element_name="pipe",
curve_names=["oil mass flow rate"],
position=Scalar(100.0, "m"),
location=OutputAttachmentLocation.Main,
)
]
),
automatic_trend_frequency=True,
trend_frequency=Scalar(0.1, "s"),
profiles=[
ProfileOutputDescription(
curve_names=["pressure"],
element_name="pipe",
location=OutputAttachmentLocation.Main,
)
],
automatic_profile_frequency=True,
profile_frequency=Scalar(0.1, "s"),
),
)
Full Case#
This section brings together all the previous sections, showing the full example of a
Description with a project configuration and being converted to a .alfacase file, using
generate_alfacase_file making this project ready to be imported by the application.
from alfasim_sdk import (
CaseDescription,
PhysicsDescription,
NumericalOptionsDescription,
TimeOptionsDescription,
PvtModelsDescription,
NodeDescription,
MassSourceNodePropertiesDescription,
PressureNodePropertiesDescription,
PipeDescription,
ProfileDescription,
LengthAndElevationDescription,
PipeSegmentsDescription,
CaseOutputDescription,
TrendsOutputDescription,
PositionalPipeTrendDescription,
OutputAttachmentLocation,
ProfileOutputDescription,
CaseOutputDescription,
)
case_description = CaseDescription(
name="basic_case",
physics=PhysicsDescription(
correlations_package=CorrelationPackageType.Alfasim,
hydrodynamic_model=HydrodynamicModelType.FourFields,
),
numerical_options=NumericalOptionsDescription(tolerance=1e-4),
time_options=TimeOptionsDescription(
minimum_timestep=Scalar(1e-4, "s"),
maximum_timestep=Scalar(0.5, "s"),
final_time=Scalar(1.0, "s"),
),
pvt_models=PvtModelsDescription(
default_model="Pvt1",
tables={"Pvt1": "my_pvt_file.tab"},
),
nodes=[
NodeDescription(
name="Inlet",
node_type=NodeCellType.MassSource,
mass_source_properties=MassSourceNodePropertiesDescription(
mass_flow_rates={
"gas": Scalar(0.0, "kg/s"),
"oil": Scalar(0.0, "kg/s"),
},
),
),
NodeDescription(
name="Outlet",
node_type=NodeCellType.Pressure,
pressure_properties=PressureNodePropertiesDescription(
pressure=Scalar(50.0, "bar"),
volume_fractions={
"gas": Scalar(1.0, "-"),
"oil": Scalar(1.0, "-"),
},
),
),
],
pipes=[
PipeDescription(
name="pipe",
source="Inlet",
target="Outlet",
profile=ProfileDescription(
length_and_elevation=LengthAndElevationDescription(
length=Array([0.0, 15.0, 30.0, 30.0, 15.0], "m"),
elevation=Array([0.0, 15.0, 30.0, 30.0, 15.0], "m"),
),
),
segments=PipeSegmentsDescription(
start_positions=Array([0.0], "m"),
diameters=Array([0.1], "m"),
roughnesses=Array([5e-05], "m"),
),
),
],
outputs=CaseOutputDescription(
trends=TrendsOutputDescription(
positional_pipe_trends=[
PositionalPipeTrendDescription(
element_name="pipe",
curve_names=["oil mass flow rate"],
position=Scalar(100.0, "m"),
location=OutputAttachmentLocation.Main,
)
]
),
automatic_trend_frequency=True,
trend_frequency=Scalar(0.1, "s"),
profiles=[
ProfileOutputDescription(
curve_names=["pressure"],
element_name="pipe",
location=OutputAttachmentLocation.Main,
)
],
automatic_profile_frequency=True,
profile_frequency=Scalar(0.1, "s"),
),
)
And the case_description above can be converted to a .alfacase file using generate_alfacase_file.
from pathlib import Path
from alfasim_sdk import generate_alfacase_file
case_description = CaseDescription( [...] )
alfacase_file = Path("c:\\user\\") / 'my_project.alfacase'
generate_alfacase_file(case_description, alfacase_file)