Skip to content

Commit aa95778

Browse files
committed
CPEX-0045 doc updates: IsoParametric SolutionInterpolation_t, variable-order patterns
- highorder.rst: expand IsoParametric section for SolutionInterpolation_t: clarify no LagrangeControlPoints child, mandatory ElementInterpolation_t prerequisite, and add read/write code examples - highorder.rst: add 'Variable-Order Configurations' section documenting Pattern A (variable order per cell via disjoint PointRange) and Pattern B (variable order per field variable with same PointRange, different arrays) with code examples for both; includes note on combining patterns - c_api.rst: fix example code to use cg_sol_ptset_write (not the removed cg_sol_write + cg_ptset_write pair); add Pattern B example showing Density at order 2 and VelocityX at order 3 over the same cell range
1 parent 2ca868f commit aa95778

2 files changed

Lines changed: 136 additions & 24 deletions

File tree

source/standard/MLL/api/c_api.rst

Lines changed: 42 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -535,36 +535,59 @@ ____________________________________________
535535
**without** a ``PointRange`` or ``PointList`` will return ``CG_ERROR``. This is enforced by the MLL to
536536
prevent ambiguous p-adaptive configurations.
537537

538-
**Example: P-Adaptation with Variable Orders**
538+
**Example A: Variable Order Per Cell (P-Adaptation)**
539+
540+
Different cells use different polynomial orders. Use ``cg_sol_ptset_write``
541+
to create a ``FlowSolution_t`` that includes a ``PointRange`` or ``PointList``
542+
in a single call:
539543

540544
.. code-block:: c
541545
542-
/* Example: Zone with 100 elements using two different polynomial orders */
546+
/* Zone with 100 elements using two different polynomial orders */
543547
int fn, B, Z, S_order3, S_order4;
544-
cgsize_t range_1_to_50[2] = {1, 50};
545-
cgsize_t range_51_to_100[2] = {51, 100};
548+
cgsize_t range_1_to_50[2] = {1, 50};
549+
cgsize_t range_51_to_100[2] = {51, 100};
546550
547-
/* 1. Create solution node for Order 3 elements (elements 1-50) */
548-
cg_sol_write(fn, B, Z, "Solution_Order3", CellCenter, &S_order3);
551+
/* Order-3 elements (cells 1-50): create solution with PointRange in one call */
552+
cg_sol_ptset_write(fn, B, Z, "Solution_Order3",
553+
CGNS_ENUMV(CellCenter),
554+
CGNS_ENUMV(PointRange), 2, range_1_to_50, &S_order3);
555+
cg_sol_interpolation_order_write(fn, B, Z, S_order3, 3, 0);
549556
550-
/* CRITICAL: Specify which elements use Order 3 */
551-
cg_ptset_write(fn, B, Z, S_order3, PointRange, 2, range_1_to_50);
557+
/* Order-4 elements (cells 51-100) */
558+
cg_sol_ptset_write(fn, B, Z, "Solution_Order4",
559+
CGNS_ENUMV(CellCenter),
560+
CGNS_ENUMV(PointRange), 2, range_51_to_100, &S_order4);
561+
cg_sol_interpolation_order_write(fn, B, Z, S_order4, 4, 0);
552562
553-
/* Write interpolation order for this subset */
554-
cg_sol_interpolation_order_write(fn, B, Z, S_order3, 3, 0);
563+
/* Write field data to each node using cg_field_write() */
555564
556-
/* 2. Create solution node for Order 4 elements (elements 51-100) */
557-
cg_sol_write(fn, B, Z, "Solution_Order4", CellCenter, &S_order4);
565+
**Example B: Variable Order Per Field Variable**
558566

559-
/* CRITICAL: Specify which elements use Order 4 */
560-
cg_ptset_write(fn, B, Z, S_order4, PointRange, 2, range_51_to_100);
567+
The *same* cells are present in both ``FlowSolution_t`` nodes, but each
568+
node carries a different field array stored at a different polynomial order.
561569

562-
/* Write interpolation order for this subset */
563-
cg_sol_interpolation_order_write(fn, B, Z, S_order4, 4, 0);
570+
.. code-block:: c
564571
565-
/* Write actual solution data to each node */
566-
/* Solution_Order3 will have N_DOFs = (3+1)^d per element (element-type dependent) */
567-
/* Solution_Order4 will have N_DOFs = (4+1)^d per element (element-type dependent) */
572+
/* Zone with 100 elements; Density stored at order 2, VelocityX at order 3 */
573+
int fn, B, Z, S_density, S_vel;
574+
cgsize_t range_all[2] = {1, 100};
575+
576+
/* Density at spatial order 2 */
577+
cg_sol_ptset_write(fn, B, Z, "FS_Density",
578+
CGNS_ENUMV(CellCenter),
579+
CGNS_ENUMV(PointRange), 2, range_all, &S_density);
580+
cg_sol_interpolation_order_write(fn, B, Z, S_density, 2, 0);
581+
cg_field_write(fn, B, Z, S_density, CGNS_ENUMV(RealDouble),
582+
"Density", density_data, &fld);
583+
584+
/* VelocityX at spatial order 3 */
585+
cg_sol_ptset_write(fn, B, Z, "FS_VelocityX",
586+
CGNS_ENUMV(CellCenter),
587+
CGNS_ENUMV(PointRange), 2, range_all, &S_vel);
588+
cg_sol_interpolation_order_write(fn, B, Z, S_vel, 3, 0);
589+
cg_field_write(fn, B, Z, S_vel, CGNS_ENUMV(RealDouble),
590+
"VelocityX", velx_data, &fld);
568591
569592
See :ref:`High-Order Interpolation <HighOrderInterpolation>` in the SIDS for complete details on
570593
interpolation metadata and data layout.

source/standard/SIDS/highorder.rst

Lines changed: 94 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1137,13 +1137,40 @@ The interpolation space for Cartesian modal interpolations uses ordered sets of
11371137
IsoParametric Interpolation
11381138
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
11391139

1140-
:sidskey:`IsoParametric` interpolation indicates that the solution uses the same interpolation functions as the mesh geometry. In this case:
1140+
:sidskey:`IsoParametric` interpolation indicates that the solution uses the same interpolation
1141+
functions as the mesh geometry. This applies to :sidsref:`SolutionInterpolation_t` nodes only.
11411142

1142-
* The element's own node coordinates from :sidsref:`GridCoordinates_t` serve as control points
1143-
* No :sidskey:`LagrangeControlPoints` need to be specified in :sidsref:`SolutionInterpolation_t`
1144-
* The interpolation type is simply marked as :sidskey:`IsoParametric`
1143+
* The element's own node coordinates from :sidsref:`GridCoordinates_t` serve as the control points.
1144+
* No :sidskey:`LagrangeControlPoints` child shall be present in the :sidsref:`SolutionInterpolation_t` node.
1145+
* An :sidsref:`ElementInterpolation_t` node for the same element type **must** already exist in
1146+
:sidsref:`Family_t`, defining the geometric interpolation whose basis is inherited.
1147+
* The :sidskey:`InterpolationType_t` child of :sidsref:`SolutionInterpolation_t` is set to
1148+
:sidskey:`IsoParametric`.
11451149

1146-
This approach is commonly used in finite element methods where the solution is interpolated using the same basis functions as the geometric mapping.
1150+
This approach is commonly used in finite element methods where the solution is expressed in the same
1151+
basis as the geometric mapping (pure isoparametric elements).
1152+
1153+
**Example**
1154+
1155+
.. code-block:: c
1156+
1157+
int fam, sn;
1158+
/* Mesh family already has an ElementInterpolation_t for QUAD_4 */
1159+
cg_solution_interpolation_write(fn, B, fam, "QUAD4_IsoParam",
1160+
CGNS_ENUMV(QUAD_4), /*spatialOrder=*/1, /*temporalOrder=*/0,
1161+
CGNS_ENUMV(IsoParametric), &sn);
1162+
/* No cg_solution_interpolation_points_write() call required */
1163+
1164+
Reading back:
1165+
1166+
.. code-block:: c
1167+
1168+
char name[33];
1169+
CGNS_ENUMT(ElementType_t) et;
1170+
CGNS_ENUMT(InterpolationType_t) it;
1171+
int os, ot;
1172+
cg_solution_interpolation_read(fn, B, fam, 1, name, &et, &os, &ot, &it);
1173+
/* it == IsoParametric, no LagrangeControlPoints child exists */
11471174
11481175
Usage in CGNS Files
11491176
^^^^^^^^^^^^^^^^^^^
@@ -1807,6 +1834,68 @@ This maps :math:`\theta \in [-1, 1]`, matching the parametric time convention an
18071834
.. important::
18081835
**Storage**: When using normalized coordinates :math:`(\xi, \eta, \zeta, \theta)`, the normalization parameters (characteristic length :math:`h^e` and time slab bounds :math:`T_n, T_{n+1}`) must be stored to enable reconstruction of physical values. This ensures data portability and prevents ambiguity in interpreting modal coefficients.
18091836

1837+
.. _variable_order_configurations:
1838+
1839+
Variable-Order Configurations
1840+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1841+
1842+
CGNS supports two distinct variable-order patterns using :sidsref:`FlowSolution_t` with
1843+
``GridLocation = CellCenter`` and a ``PointRange`` or ``PointList``.
1844+
1845+
**Pattern A: Variable order per cell (p-adaptation)**
1846+
1847+
Different cells within the same zone use different polynomial orders. Create one
1848+
:sidsref:`FlowSolution_t` per distinct order, each with a disjoint
1849+
``PointRange``/``PointList`` identifying its cell subset. Each node carries an
1850+
``InterpolationOrders`` child (written via ``cg_sol_interpolation_order_write``)
1851+
specifying ``[SpatialOrder, TemporalOrder]`` for that subset.
1852+
1853+
Example — 8 TETRA_4 elements split at order 2 and order 3:
1854+
1855+
.. code-block:: c
1856+
1857+
cgsize_t lo_range[2] = {1, 4}; /* cells 1-4 at order 2 */
1858+
cgsize_t hi_range[2] = {5, 8}; /* cells 5-8 at order 3 */
1859+
1860+
cg_sol_ptset_write(fn, B, Z, "FS_P2", CGNS_ENUMV(CellCenter),
1861+
CGNS_ENUMV(PointRange), 2, lo_range, &S1);
1862+
cg_sol_interpolation_order_write(fn, B, Z, S1, 2, 0);
1863+
1864+
cg_sol_ptset_write(fn, B, Z, "FS_P3", CGNS_ENUMV(CellCenter),
1865+
CGNS_ENUMV(PointRange), 2, hi_range, &S2);
1866+
cg_sol_interpolation_order_write(fn, B, Z, S2, 3, 0);
1867+
1868+
**Pattern B: Variable order per field variable**
1869+
1870+
All cells share the same ``PointRange`` (typically the full zone), but individual
1871+
field arrays (``DataArray_t`` children) are stored at different polynomial orders.
1872+
Use a separate :sidsref:`FlowSolution_t` per distinct order, each carrying only the
1873+
field arrays that belong to that order.
1874+
1875+
Example — ``Density`` at order 2 and ``VelocityX`` at order 3, over all 8 cells:
1876+
1877+
.. code-block:: c
1878+
1879+
cgsize_t all[2] = {1, 8};
1880+
1881+
cg_sol_ptset_write(fn, B, Z, "FS_Density", CGNS_ENUMV(CellCenter),
1882+
CGNS_ENUMV(PointRange), 2, all, &S1);
1883+
cg_sol_interpolation_order_write(fn, B, Z, S1, 2, 0);
1884+
cg_field_write(fn, B, Z, S1, CGNS_ENUMV(RealDouble), "Density", rho, &fld);
1885+
1886+
cg_sol_ptset_write(fn, B, Z, "FS_VelocityX", CGNS_ENUMV(CellCenter),
1887+
CGNS_ENUMV(PointRange), 2, all, &S2);
1888+
cg_sol_interpolation_order_write(fn, B, Z, S2, 3, 0);
1889+
cg_field_write(fn, B, Z, S2, CGNS_ENUMV(RealDouble), "VelocityX", velx, &fld);
1890+
1891+
.. note::
1892+
Pattern A and Pattern B can be combined: a file may have some
1893+
``FlowSolution_t`` nodes that differ in both cell subset *and* polynomial
1894+
order, while others share the same cell subset but carry different field
1895+
variables. The :sidsref:`Family_t` must contain a
1896+
:sidsref:`SolutionInterpolation_t` entry for every (ElementType, SpatialOrder,
1897+
TemporalOrder) triplet that appears in the file.
1898+
18101899
References
18111900
^^^^^^^^^^
18121901

0 commit comments

Comments
 (0)