Skip to content

Computational Grid

The computational grid (CGRID) defines the spatial and spectral discretization for SWAN calculations. It specifies where wave action densities are computed.

Grid Types

SWAN supports three grid types:

  • Regular — Rectangular grid with uniform spacing
  • Curvilinear — Grid with curved coordinate lines (e.g., following coastlines)
  • Unstructured — Triangular mesh for complex geometries

The CGRID command also defines the spectral resolution (number of directions and frequency range).

Regular Grid

REGULAR

Bases: CGRID

SWAN regular computational grid.

.. code-block:: text

CGRID REGULAR [xpc] [ypc] [alpc] [xlenc] [ylenc] [mxc] [myc] &
    ->CIRCLE|SECTOR [mdc] [flow] [fhigh] [msc]

This is a group component that includes a CGRID and a READGRID component.

Note

In 1D-mode, alpc should be equal to the direction alpinp.

Examples

.. ipython:: python :okwarning:

from rompy_swan.components.cgrid import REGULAR
cgrid = REGULAR(
    grid=dict(xp=0, yp=0, alp=0, xlen=2000, ylen=1300, mx=100, my=100),
    spectrum=dict(mdc=36, flow=0.04, fhigh=1.0),
)
print(cgrid.render())
Source code in src/rompy_swan/components/cgrid.py
class REGULAR(CGRID):
    """SWAN regular computational grid.

    .. code-block:: text

        CGRID REGULAR [xpc] [ypc] [alpc] [xlenc] [ylenc] [mxc] [myc] &
            ->CIRCLE|SECTOR [mdc] [flow] [fhigh] [msc]

    This is a group component that includes a `CGRID` and a `READGRID` component.

    Note
    ----
    In 1D-mode, `alpc` should be equal to the direction `alpinp`.


    Examples
    --------

    .. ipython:: python
        :okwarning:

        from rompy_swan.components.cgrid import REGULAR
        cgrid = REGULAR(
            grid=dict(xp=0, yp=0, alp=0, xlen=2000, ylen=1300, mx=100, my=100),
            spectrum=dict(mdc=36, flow=0.04, fhigh=1.0),
        )
        print(cgrid.render())

    """

    model_type: Literal["regular", "REGULAR"] = Field(
        default="regular", description="Model type discriminator"
    )
    grid: GRIDREGULAR = Field(description="Computational grid definition")

    @model_validator(mode="after")
    def grid_suffix(self) -> "REGULAR":
        """Set expected grid suffix."""
        if self.grid.suffix != "c":
            logger.debug(f"Set grid suffix 'c' instead of {self.grid.suffix}")
            self.grid.suffix = "c"
        return self

    def cmd(self) -> str:
        repr = f"CGRID REGULAR {self.grid.render()} {self.spectrum.render()}"
        return repr

Attributes

model_type class-attribute instance-attribute

model_type: Literal['regular', 'REGULAR'] = Field(default='regular', description='Model type discriminator')

grid class-attribute instance-attribute

grid: GRIDREGULAR = Field(description='Computational grid definition')

Functions

grid_suffix

grid_suffix() -> REGULAR

Set expected grid suffix.

Source code in src/rompy_swan/components/cgrid.py
@model_validator(mode="after")
def grid_suffix(self) -> "REGULAR":
    """Set expected grid suffix."""
    if self.grid.suffix != "c":
        logger.debug(f"Set grid suffix 'c' instead of {self.grid.suffix}")
        self.grid.suffix = "c"
    return self

cmd

cmd() -> str
Source code in src/rompy_swan/components/cgrid.py
def cmd(self) -> str:
    repr = f"CGRID REGULAR {self.grid.render()} {self.spectrum.render()}"
    return repr

Curvilinear Grid

CURVILINEAR

Bases: CGRID

SWAN curvilinear computational grid.

.. code-block:: text

CGRID CURVILINEAR [mxc] [myc] (EXCEPTION [xexc] [yexc])
    ->CIRCLE|SECTOR [mdc] [flow] [fhigh] [msc]
READGRID COORDINATES [fac] 'fname' [idla] [nhedf] [nhedvec] &
    FREE|FORMAT ('form'|[idfm])

This is a group component that includes a CGRID and a READGRID component.

Examples

.. ipython:: python :okwarning:

from rompy_swan.components.cgrid import CURVILINEAR
cgrid = CURVILINEAR(
    mxc=199,
    myc=199,
    readcoord=dict(fname="./coords.txt"),
    spectrum=dict(mdc=36, flow=0.04, fhigh=1.0),
)
print(cgrid.render())
Source code in src/rompy_swan/components/cgrid.py
class CURVILINEAR(CGRID):
    """SWAN curvilinear computational grid.

    .. code-block:: text

        CGRID CURVILINEAR [mxc] [myc] (EXCEPTION [xexc] [yexc])
            ->CIRCLE|SECTOR [mdc] [flow] [fhigh] [msc]
        READGRID COORDINATES [fac] 'fname' [idla] [nhedf] [nhedvec] &
            FREE|FORMAT ('form'|[idfm])

    This is a group component that includes a `CGRID` and a `READGRID` component.

    Examples
    --------

    .. ipython:: python
        :okwarning:

        from rompy_swan.components.cgrid import CURVILINEAR
        cgrid = CURVILINEAR(
            mxc=199,
            myc=199,
            readcoord=dict(fname="./coords.txt"),
            spectrum=dict(mdc=36, flow=0.04, fhigh=1.0),
        )
        print(cgrid.render())

    """

    model_type: Literal["curvilinear", "CURVILINEAR"] = Field(
        default="curvilinear", description="Model type discriminator"
    )
    mxc: int = Field(
        description=(
            "Number of meshes in computational grid in ξ-direction (this number is "
            "one less than the number of grid points in this domain)."
        ),
    )
    myc: int = Field(
        description=(
            "Number of meshes in computational grid in η-direction (this number is "
            "one less than the number of grid points in this domain)."
        ),
    )
    xexc: Optional[float] = Field(
        default=None,
        description=(
            "the value which the user uses to indicate that a grid point is to be "
            "ignored in the computations (this value is provided by the user at the "
            "location of the x-coordinate considered in the file of the "
            "x-coordinates, see command READGRID COOR)."
        ),
    )
    yexc: Optional[float] = Field(
        default=None,
        description=(
            "the value which the user uses to indicate that a grid point is to be "
            "ignored in the computations (this value is provided by the user at the "
            "location of the y-coordinate considered in the file of the "
            "y-coordinates, see command READGRID COOR)."
        ),
    )
    readcoord: READCOORD = Field(
        description="Grid coordinates reader.",
    )

    @model_validator(mode="after")
    def xexc_and_yexc_or_neither(self) -> "CURVILINEAR":
        if [self.xexc, self.yexc].count(None) == 1:
            raise ValueError("xexc and yexc must be specified together")
        return self

    @property
    def exception(self):
        if self.xexc is not None:
            return f"EXCEPTION xexc={self.xexc} xexc={self.yexc}"
        else:
            return ""

    @property
    def format_repr(self):
        if self.format == "free":
            repr = "FREE"
        elif self.format == "fixed" and self.form:
            repr = f"FORMAT form='{self.form}'"
        elif self.format == "fixed" and self.idfm:
            repr = f"FORMAT idfm={self.idfm}"
        elif self.format == "unformatted":
            repr = "UNFORMATTED"
        return repr

    def cmd(self) -> str:
        repr = f"CGRID CURVILINEAR mxc={self.mxc} myc={self.myc}"
        if self.exception:
            repr += f" {self.exception}"
        repr += f" {self.spectrum.render()}"
        repr = [repr] + [self.readcoord.render()]
        return repr

Attributes

model_type class-attribute instance-attribute

model_type: Literal['curvilinear', 'CURVILINEAR'] = Field(default='curvilinear', description='Model type discriminator')

mxc class-attribute instance-attribute

mxc: int = Field(description='Number of meshes in computational grid in ξ-direction (this number is one less than the number of grid points in this domain).')

myc class-attribute instance-attribute

myc: int = Field(description='Number of meshes in computational grid in η-direction (this number is one less than the number of grid points in this domain).')

xexc class-attribute instance-attribute

xexc: Optional[float] = Field(default=None, description='the value which the user uses to indicate that a grid point is to be ignored in the computations (this value is provided by the user at the location of the x-coordinate considered in the file of the x-coordinates, see command READGRID COOR).')

yexc class-attribute instance-attribute

yexc: Optional[float] = Field(default=None, description='the value which the user uses to indicate that a grid point is to be ignored in the computations (this value is provided by the user at the location of the y-coordinate considered in the file of the y-coordinates, see command READGRID COOR).')

readcoord class-attribute instance-attribute

readcoord: READCOORD = Field(description='Grid coordinates reader.')

exception property

exception

format_repr property

format_repr

Functions

xexc_and_yexc_or_neither

xexc_and_yexc_or_neither() -> CURVILINEAR
Source code in src/rompy_swan/components/cgrid.py
@model_validator(mode="after")
def xexc_and_yexc_or_neither(self) -> "CURVILINEAR":
    if [self.xexc, self.yexc].count(None) == 1:
        raise ValueError("xexc and yexc must be specified together")
    return self

cmd

cmd() -> str
Source code in src/rompy_swan/components/cgrid.py
def cmd(self) -> str:
    repr = f"CGRID CURVILINEAR mxc={self.mxc} myc={self.myc}"
    if self.exception:
        repr += f" {self.exception}"
    repr += f" {self.spectrum.render()}"
    repr = [repr] + [self.readcoord.render()]
    return repr

Unstructured Grid

UNSTRUCTURED

Bases: CGRID

SWAN unstructured computational grid.

.. code-block:: text

CGRID UNSTRUCTURED CIRCLE|SECTOR [mdc] [flow] [fhigh] [msc]
READGRID UNSTRUCTURED [grid_type] ('fname')

This is a group component that includes a CGRID and a READGRID component.

Examples

.. ipython:: python :okwarning:

from rompy_swan.components.cgrid import UNSTRUCTURED
cgrid = UNSTRUCTURED(
    grid_type="adcirc",
    spectrum=dict(mdc=36, flow=0.04, fhigh=1.0),
)
print(cgrid.render())
Source code in src/rompy_swan/components/cgrid.py
class UNSTRUCTURED(CGRID):
    """SWAN unstructured computational grid.

    .. code-block:: text

        CGRID UNSTRUCTURED CIRCLE|SECTOR [mdc] [flow] [fhigh] [msc]
        READGRID UNSTRUCTURED [grid_type] ('fname')

    This is a group component that includes a `CGRID` and a `READGRID` component.

    Examples
    --------

    .. ipython:: python
        :okwarning:

        from rompy_swan.components.cgrid import UNSTRUCTURED
        cgrid = UNSTRUCTURED(
            grid_type="adcirc",
            spectrum=dict(mdc=36, flow=0.04, fhigh=1.0),
        )
        print(cgrid.render())

    """

    model_type: Literal["unstructured"] = Field(
        default="unstructured", description="Model type discriminator"
    )
    grid_type: Literal["adcirc", "triangle", "easymesh"] = Field(
        default="adcirc",
        description="Unstructured grid type",
    )
    fname: Optional[str] = Field(
        default=None,
        description="Name of the file containing the unstructured grid",
        max_length=36,
    )

    @model_validator(mode="after")
    def check_fname_required(self) -> "UNSTRUCTURED":
        """Check that fname needs to be provided."""
        if self.grid_type == "adcirc" and self.fname is not None:
            raise ValueError("fname must not be specified for ADCIRC grid")
        elif self.grid_type != "adcirc" and self.fname is None:
            raise ValueError(f"fname must be specified for {self.grid_type} grid")
        return self

    def cmd(self) -> str:
        repr = [f"CGRID UNSTRUCTURED {self.spectrum.cmd()}"]
        repr += [f"READGRID UNSTRUCTURED {self.grid_type.upper()}"]
        if self.grid_type in ["triangle", "easymesh"]:
            repr[-1] += f" fname='{self.fname}'"
        return repr

Attributes

model_type class-attribute instance-attribute

model_type: Literal['unstructured'] = Field(default='unstructured', description='Model type discriminator')

grid_type class-attribute instance-attribute

grid_type: Literal['adcirc', 'triangle', 'easymesh'] = Field(default='adcirc', description='Unstructured grid type')

fname class-attribute instance-attribute

fname: Optional[str] = Field(default=None, description='Name of the file containing the unstructured grid', max_length=36)

Functions

check_fname_required

check_fname_required() -> UNSTRUCTURED

Check that fname needs to be provided.

Source code in src/rompy_swan/components/cgrid.py
@model_validator(mode="after")
def check_fname_required(self) -> "UNSTRUCTURED":
    """Check that fname needs to be provided."""
    if self.grid_type == "adcirc" and self.fname is not None:
        raise ValueError("fname must not be specified for ADCIRC grid")
    elif self.grid_type != "adcirc" and self.fname is None:
        raise ValueError(f"fname must be specified for {self.grid_type} grid")
    return self

cmd

cmd() -> str
Source code in src/rompy_swan/components/cgrid.py
def cmd(self) -> str:
    repr = [f"CGRID UNSTRUCTURED {self.spectrum.cmd()}"]
    repr += [f"READGRID UNSTRUCTURED {self.grid_type.upper()}"]
    if self.grid_type in ["triangle", "easymesh"]:
        repr[-1] += f" fname='{self.fname}'"
    return repr