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_type
isNodeCellType.MassSource
,mass_source_properties
will be taken in account.When
node_type
isNodeCellType.Pressure
,pressure_properties
will 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
convert_description_to_alfacase 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 convert_description_to_alfacase
.
from pathlib import Path
from alfasim_sdk import convert_description_to_alfacase
case_description = CaseDescription( [...] )
alfacase_content = convert_description_to_alfacase(case_description)
# Dump the content to a file
alfacase_file = Path("c:\\user\\") / 'my_project.alfacase'
alfacase_file.write_text(data=alfacase_content, encoding='UTF-8')