1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
|
.. _ch_network:
Networks
--------
The ``DMNETWORK`` class provides
abstractions for representing general unstructured networks such as
communication networks, power grid, computer networks, transportation
networks, electrical circuits, graphs, and others.
Application flow
~~~~~~~~~~~~~~~~
The general flow of an application code using ``DMNETWORK`` is as
follows:
#. Create a network object.
.. code-block::
DMNetworkCreate(MPI_Comm comm, DM *dm);
#. Create components and register them with the network. A “component”
is specific application data at a vertex/edge of the network required
for its residual evaluation. For example, components could be
resistor/inductor data for circuit applications, edge weights for
graph problems, or generator/transmission line data for power grids.
Components are registered by calling
.. code-block::
DMNetworkRegisterComponent(DM dm, const char *name, size_t size, PetscInt *compkey);
Here, ``name`` is the component name, ``size`` is the size of
component data, and ``compkey`` is an integer key that can be
used for setting/getting the component at a vertex or an edge.
#. A ``DMNETWORK`` can consist of one or more physical subnetworks. Each subnetwork has its own mathematical model. When
multiple subnetworks are used one can (optionally) provide
coupling information between subnetworks. That is vertices that are *shared* between multiple subnetworks; edges can only belong to a single subnetwork. The
number of subnetwork is set by calling
.. code-block::
DMNetworkSetNumSubNetworks(DM dm, PetscInt nsubnet, PetscInt Nsubnet);
Here, ``nsubnet`` and ``Nsubnet`` are the local and global number of subnetworks.
#. A subnetwork is added to the network by calling
.. code-block::
DMNetworkAddSubnetwork(DM dm, const char* name, PetscInt ne, PetscInt edgelist[], PetscInt *netnum);
Here ``name`` is the subnetwork name, ``ne`` is the number of local edges on the subnetwork, and ``edgelist`` is the connectivity for the subnetwork.
The output ``netnum`` is the global numbering of the subnetwork in the network.
Each element of ``edgelist`` is an integer array of size ``2*ne``
containing the edge connectivity for the subnetwork.
| As an example, consider a network comprised of 2 subnetworks that
are coupled. The topological information for the network is as
follows:
| subnetwork 0: v0 — v1 — v2 — v3
| subnetwork 1: v1 — v2 — v0
| The two subnetworks are coupled by merging vertex 0 from subnetwork 0 with vertex 2 from subnetwork 1.
| The ``edgelist`` of this network is
| edgelist[0] = {0,1,1,2,2,3}
| edgelist[1] = {1,2,2,0}
The coupling is done by calling
.. code-block::
DMNetworkAddSharedVertices(DM dm, PetscInt anet, PetscInt bnet, PetscInt nsv, PetscInt asv[], PetscInt bsv[]);
Here ``anet`` and ``bnet`` are the first and second subnetwork global numberings returned by ``DMNetworkAddSubnetwork()``,
``nsv`` is the number of vertices shared by the two subnetworks, ``asv`` and ``bsv`` are the vertex indices in the subnetwork ``anet`` and ``bnet`` .
#. The next step is to have ``DMNETWORK`` create a bare layout (graph) of
the network by calling
.. code-block::
DMNetworkLayoutSetUp(DM dm);
#. After completing the previous steps, the network graph is set up, but
no physics is associated yet. This is done by adding the components
and setting the number of variables to the vertices and edges.
A component and number of variables are added to a vertex/edge by calling
.. code-block::
DMNetworkAddComponent(DM dm, PetscInt p, PetscInt compkey, void* compdata, PetscInt nvar)
where ``p`` is the network vertex/edge point in the range obtained by
either ``DMNetworkGetVertexRange()``/``DMNetworkGetEdgeRange()``, ``DMNetworkGetSubnetwork()``, or ``DMNetworkGetSharedVertices()``;
``compkey`` is the component key returned when registering the component
(``DMNetworkRegisterComponent()``); ``compdata`` holds the data for the
component; and ``nvar`` is the number of variables associated to the added component at this network point. ``DMNETWORK`` supports setting multiple components
at a vertex/edge. At a shared vertex, ``DMNETWORK`` currently requires the owner process of the vertex adds all the components and number of variables.
``DMNETWORK`` currently assumes the component data to be stored in a
contiguous chunk of memory. As such, it does not do any
packing/unpacking before/after the component data gets distributed.
Any such serialization (packing/unpacking) should be done by the
application.
#. Set up network internal data structures.
.. code-block::
DMSetUp(DM dm);
#. Distribute the network (also moves components attached with
vertices/edges) to multiple processors.
.. code-block::
DMNetworkDistribute(DM dm, const char partitioner[], PetscInt overlap, DM *distDM);
#. Associate the ``DM`` with a PETSc solver:
.. code-block::
KSPSetDM(KSP ksp, DM dm) or SNESSetDM(SNES snes, DM dm) or TSSetDM(TS ts, DM dm).
Utility functions
~~~~~~~~~~~~~~~~~
``DMNETWORK`` provides several utility functions for operations on the
network. The most commonly used functions are: obtaining iterators for
vertices/edges,
.. code-block::
DMNetworkGetEdgeRange(DM dm, PetscInt *eStart, PetscInt *eEnd);
.. code-block::
DMNetworkGetVertexRange(DM dm, PetscInt *vStart, PetscInt *vEnd);
.. code-block::
DMNetworkGetSubnetwork(DM dm, PetscInt netnum, PetscInt *nv, PetscInt *ne, const PetscInt **vtx, const PetscInt **edge);
checking the status of a vertex,
.. code-block::
DMNetworkIsGhostVertex(DM dm, PetscInt p, PetscBool *isghost);
.. code-block::
DMNetworkIsSharedVertex(DM dm, PetscInt p, PetscBool *isshared);
and retrieving local/global indices of vertex/edge component variables for
inserting elements in vectors/matrices,
.. code-block::
DMNetworkGetLocalVecOffset(DM dm, PetscInt p, PetscInt compnum, PetscInt *offset);
.. code-block::
DMNetworkGetGlobalVecOffset(DM dm, PetscInt p, PetscInt compnum, PetscInt *offsetg).
In network applications, one frequently needs to find the supporting
edges for a vertex or the connecting vertices covering an edge. These
can be obtained by the following two routines.
.. code-block::
DMNetworkGetConnectedVertices(DM dm, PetscInt edge, const PetscInt *vertices[]);
.. code-block::
DMNetworkGetSupportingEdges(DM dm, PetscInt vertex, PetscInt *nedges, const PetscInt *edges[]).
Retrieving components and number of variables
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The components and the corresponding number of variables set at a vertex/edge can be accessed by
.. code-block::
DMNetworkGetComponent(DM dm, PetscInt p, PetscInt compnum, PetscInt *compkey, void **component, PetscInt *nvar)
input ``compnum`` is the component number, output ``compkey`` is the key set by ``DMNetworkRegisterComponent()``. An example
of accessing and retrieving the components and number of variables at vertices is:
.. code-block::
PetscInt Start,End,numcomps,key,v,compnum;
void *component;
DMNetworkGetVertexRange(dm, &Start, &End);
for (v = Start; v < End; v++) {
DMNetworkGetNumComponents(dm, v, &numcomps);
for (compnum=0; compnum < numcomps; compnum++) {
DMNetworkGetComponent(dm, v, compnum, &key, &component, &nvar);
compdata = (UserCompDataType)(component);
}
}
The above example does not explicitly use the component key. It is
used when different component types are set at different vertices. In
this case, ``compkey`` is used to differentiate the component type.
.. bibliography:: /petsc.bib
:filter: docname in docnames
|