116 sunbooleantype jok, sunbooleantype* jcurPtr,
117 sunrealtype gamma,
void* user_data) {
120 const int N = P.N_eq;
121 const int bw = P.prec_bw;
122 const int r = P.prec_rank;
128 if (jok && !P.prec_band.empty()) {
130 P.prec_gamma = gamma;
135 P.prec_gamma = gamma;
137 double* ydata = N_VGetArrayPointer_Serial(y);
140 const int ldab = 3 * bw + 1;
141 if (
static_cast<int>(P.prec_band.size()) != ldab * N) {
142 P.prec_band.resize(ldab * N, 0.0);
143 P.prec_Tinv_U.resize(N * r, 0.0);
144 P.prec_schur.resize(r * r, 0.0);
145 P.prec_ipiv_band.resize(N, 0);
146 P.prec_ipiv_schur.resize(r, 0);
147 P.prec_f0.resize(N, 0.0);
148 P.prec_work.resize(N, 0.0);
149 P.prec_y_save.resize(N, 0.0);
150 P.prec_deltas.resize(N, 0.0);
151 P.prec_f_pert.resize(N, 0.0);
156 const double* f0_ptr = N_VGetArrayPointer_Serial(fy);
157 for (
int k = 0; k < N; ++k) P.prec_f0[k] = f0_ptr[k];
160 for (
int k = 0; k < N; ++k) P.prec_y_save[k] = ydata[k];
165 const int n_colors = 2 * bw + 1;
168 std::fill(P.prec_band.begin(), P.prec_band.end(), 0.0);
169 std::fill(P.prec_deltas.begin(), P.prec_deltas.end(), 0.0);
171 for (
int c = 0; c < n_colors; ++c) {
173 for (
int j = c; j < N; j += n_colors) {
174 double dy =
fd_delta(ydata[j], P.atol);
175 P.prec_deltas[j] = dy;
180 ud->
rhs_fn(t, y, fy, user_data);
181 const double* f_tmp = N_VGetArrayPointer_Serial(fy);
182 for (
int k = 0; k < N; ++k) P.prec_f_pert[k] = f_tmp[k];
185 for (
int j = c; j < N; j += n_colors) {
186 double inv_dy = 1.0 / P.prec_deltas[j];
187 int klo = std::max(0, j - bw);
188 int khi = std::min(N - 1, j + bw);
189 for (
int k = klo; k <= khi; ++k) {
190 double Jkj = (P.prec_f_pert[k] - P.prec_f0[k]) * inv_dy;
194 int band_row = 2 * bw + (k - j);
195 P.prec_band[band_row + j * ldab] = (k == j)
196 ? (1.0 - gamma * Jkj)
202 for (
int j = c; j < N; j += n_colors) {
203 ydata[j] = P.prec_y_save[j];
204 P.prec_deltas[j] = 0.0;
211 int kl = bw, ku = bw;
212 dgbtrf_(&N, &N, &kl, &ku, P.prec_band.data(), &ldab,
213 P.prec_ipiv_band.data(), &info);
215 std::cerr <<
"[prec_setup_woodbury] dgbtrf failed, info=" << info <<
"\n";
217 double* fy_data = N_VGetArrayPointer_Serial(fy);
218 for (
int k = 0; k < N; ++k) fy_data[k] = P.prec_f0[k];
227 for (
int jj = 0; jj < r; ++jj) {
228 int j = P.prec_mobile_idx[jj];
229 double dy =
fd_delta(ydata[j], P.atol);
232 ud->
rhs_fn(t, y, fy, user_data);
233 const double* f_tmp = N_VGetArrayPointer_Serial(fy);
235 double inv_dy = 1.0 / dy;
236 double* col = &P.prec_Tinv_U[jj * N];
238 for (
int k = 0; k < N; ++k) {
239 double Jkj = (f_tmp[k] - P.prec_f0[k]) * inv_dy;
242 int dist = std::abs(k - j);
246 col[k] = -gamma * Jkj;
250 ydata[j] = P.prec_y_save[j];
255 int kl = bw, ku = bw;
258 dgbtrs_(&trans, &N, &kl, &ku, &nrhs, P.prec_band.data(), &ldab,
259 P.prec_ipiv_band.data(), col, &N, &info);
261 std::cerr <<
"[prec_setup_woodbury] dgbtrs for col " << jj
262 <<
" failed, info=" << info <<
"\n";
263 double* fy_data = N_VGetArrayPointer_Serial(fy);
264 for (
int k = 0; k < N; ++k) fy_data[k] = P.prec_f0[k];
273 for (
int ii = 0; ii < r; ++ii) {
274 int row_idx = P.prec_mobile_idx[ii];
275 for (
int jj = 0; jj < r; ++jj) {
276 P.prec_schur[ii + jj * r] = (ii == jj ? 1.0 : 0.0)
277 + P.prec_Tinv_U[jj * N + row_idx];
284 dgetrf_(&r, &r, P.prec_schur.data(), &r,
285 P.prec_ipiv_schur.data(), &info);
287 std::cerr <<
"[prec_setup_woodbury] dgetrf (Schur) failed, info="
289 double* fy_data = N_VGetArrayPointer_Serial(fy);
290 for (
int k = 0; k < N; ++k) fy_data[k] = P.prec_f0[k];
297 double* fy_data = N_VGetArrayPointer_Serial(fy);
298 for (
int k = 0; k < N; ++k) fy_data[k] = P.prec_f0[k];
304 N_Vector rv, N_Vector zv,
305 sunrealtype gamma, sunrealtype ,
306 int ,
void* user_data) {
309 const int N = P.N_eq;
310 const int bw = P.prec_bw;
311 const int r = P.prec_rank;
312 const int ldab = 3 * bw + 1;
314 double* rdata = N_VGetArrayPointer_Serial(rv);
315 double* zdata = N_VGetArrayPointer_Serial(zv);
317 (void)t; (void)y; (void)fy; (void)gamma;
320 for (
int k = 0; k < N; ++k) zdata[k] = rdata[k];
323 int kl = bw, ku = bw;
326 dgbtrs_(&trans, &N, &kl, &ku, &nrhs, P.prec_band.data(), &ldab,
327 P.prec_ipiv_band.data(), zdata, &N, &info);
329 std::cerr <<
"[prec_solve_woodbury] dgbtrs failed, info=" << info <<
"\n";
334 if (r == 0)
return 0;
337 std::vector<double> w2(r);
338 for (
int jj = 0; jj < r; ++jj)
339 w2[jj] = zdata[P.prec_mobile_idx[jj]];
346 dgetrs_(&trans, &r, &nrhs, P.prec_schur.data(), &r,
347 P.prec_ipiv_schur.data(), w2.data(), &r, &info);
349 std::cerr <<
"[prec_solve_woodbury] dgetrs (Schur) failed, info="
356 for (
int k = 0; k < N; ++k) {
358 for (
int jj = 0; jj < r; ++jj)
359 corr += P.prec_Tinv_U[jj * N + k] * w2[jj];