Create a sparse periodic design matrix and corresponding derivative matrices.
(u: Array, order: int, dorder: int, knots: Array)
| 1130 | |
| 1131 | @njit |
| 1132 | def periodicDerMatrix(u: Array, order: int, dorder: int, knots: Array) -> list[COO]: |
| 1133 | """ |
| 1134 | Create a sparse periodic design matrix and corresponding derivative matrices. |
| 1135 | """ |
| 1136 | |
| 1137 | # extend the knots |
| 1138 | knots_ext = np.concat( |
| 1139 | (knots[-order:-1] - knots[-1], knots, knots[-1] + knots[1:order]) |
| 1140 | ) |
| 1141 | |
| 1142 | # number of parameter values |
| 1143 | nu = len(u) |
| 1144 | |
| 1145 | # number of basis functions |
| 1146 | nb = len(knots) - 1 |
| 1147 | |
| 1148 | # chunk size |
| 1149 | n = order + 1 |
| 1150 | |
| 1151 | # temp chunk storage |
| 1152 | temp = np.zeros((dorder + 1, n)) |
| 1153 | |
| 1154 | # initialize the empty matrix |
| 1155 | rv = [] |
| 1156 | |
| 1157 | for _ in range(dorder + 1): |
| 1158 | rv.append( |
| 1159 | COO( |
| 1160 | i=np.empty(n * nu, dtype=np.int64), |
| 1161 | j=np.empty(n * nu, dtype=np.int64), |
| 1162 | v=np.empty(n * nu), |
| 1163 | shape=(nu, len(knots) - 1), |
| 1164 | ) |
| 1165 | ) |
| 1166 | |
| 1167 | # loop over parameter values |
| 1168 | for i in range(nu): |
| 1169 | ui = u[i] |
| 1170 | |
| 1171 | # find the supporting span |
| 1172 | span = nbFindSpan(ui, order, knots, 0, nb) + order - 1 |
| 1173 | |
| 1174 | # evaluate non-zero functions |
| 1175 | nbBasisDer(span, ui, order, dorder, knots_ext, temp) |
| 1176 | |
| 1177 | # update the matrices |
| 1178 | for di in range(dorder + 1): |
| 1179 | rv[di].i[i * n : (i + 1) * n] = i |
| 1180 | rv[di].j[i * n : (i + 1) * n] = ( |
| 1181 | span - order + 1 + np.arange(n) |
| 1182 | ) % nb # NB: this is due to periodicity |
| 1183 | rv[di].v[i * n : (i + 1) * n] = temp[di, :] |
| 1184 | |
| 1185 | return rv |
| 1186 | |
| 1187 | |
| 1188 | @njit |
no test coverage detected