inline void CreateOpenLineList(IntCoord *cpx, IntCoord *cpy, int cpcount) { int cpi; llcount = 0; CalcBSpline( cpx[0], cpy[0], cpx[0], cpy[0], cpx[0], cpy[0], cpx[1], cpy[1] ); CalcBSpline( cpx[0], cpy[0], cpx[0], cpy[0], cpx[1], cpy[1], cpx[2], cpy[2] ); for (cpi = 1; cpi < cpcount - 2; ++cpi) { CalcBSpline( cpx[cpi - 1], cpy[cpi - 1], cpx[cpi], cpy[cpi], cpx[cpi + 1], cpy[cpi + 1], cpx[cpi + 2], cpy[cpi + 2] ); } CalcBSpline( cpx[cpi - 1], cpy[cpi - 1], cpx[cpi], cpy[cpi], cpx[cpi + 1], cpy[cpi + 1], cpx[cpi + 1], cpy[cpi + 1] ); CalcBSpline( cpx[cpi], cpy[cpi], cpx[cpi + 1], cpy[cpi + 1], cpx[cpi + 1], cpy[cpi + 1], cpx[cpi + 1], cpy[cpi + 1] ); }
PetscErrorCode BSSPsi(BSS self, Vec c, Vec xs, Vec ys) { // yj = sum(i) ci ui(xj) // PetscErrorCode ierr; // ierr = BSSChcek(self); CHKERRQ(ierr); PetscErrorCode ierr; int nc; VecGetSize(c, &nc); int nb; BSSGetSize(self, &nb); int nx; VecGetSize(xs, &nx); int ny; VecGetSize(ys, &ny); if(nc != nb) { SETERRQ(self->comm, 1, "size of c must be same as basis size"); } if(nx != ny) { SETERRQ(self->comm, 1, "xs and ys must be same size"); } Mat f_jx_ib; ierr = MatCreate(self->comm, &f_jx_ib); CHKERRQ(ierr); ierr = MatSetSizes(f_jx_ib, PETSC_DECIDE, PETSC_DECIDE, nx, nb); CHKERRQ(ierr); ierr = MatSetUp(f_jx_ib); CHKERRQ(ierr); PetscScalar *x_ptr; VecGetArray(xs, &x_ptr); PetscReal *x_r_ptr; PetscMalloc1(nx, &x_r_ptr); for(int ix = 0; ix < nx; ix++) x_r_ptr[ix] = creal(x_ptr[ix]); PetscScalar *x_c_ptr; PetscMalloc1(nx, &x_c_ptr); ierr = CScalingCalc(self->c_scaling, x_r_ptr, nx, NULL, x_c_ptr); CHKERRQ(ierr); for(int jx = 0; jx < nx; jx++) { for(int ib = 0; ib < nb; ib++) { PetscScalar y; PetscBool zeroq; ierr = CalcBSpline(self->order, self->ts_r, self->ts_s, self->b_idx_list[ib], x_r_ptr[jx], x_c_ptr[jx], &y, &zeroq); CHKERRQ(ierr); if(!zeroq) { ierr = MatSetValue(f_jx_ib, jx, ib, y, INSERT_VALUES); CHKERRQ(ierr); } } } MatAssemblyBegin(f_jx_ib, MAT_FINAL_ASSEMBLY); MatAssemblyEnd(f_jx_ib, MAT_FINAL_ASSEMBLY); ierr = MatMult(f_jx_ib, c, ys); CHKERRQ(ierr); MatDestroy(&f_jx_ib); VecRestoreArray(xs, &x_ptr); PetscFree(x_r_ptr); PetscFree(x_c_ptr); return 0; }
PetscErrorCode CalcDerivBSpline(int order, PetscReal* ts_r, PetscScalar *ts, int i, double x_r, PetscScalar x, PetscScalar* y, PetscBool *zeroq) { if(order < 1) { SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "order must be positive integer\n"); } PetscBool _zeroq; if(order == 1) { *y = 0.0; _zeroq = PETSC_TRUE; } else { int k = order; PetscScalar bs0; PetscBool zeroq0; CalcBSpline(k-1, ts_r, ts, i, x_r, x, &bs0, &zeroq0); PetscScalar bs1; PetscBool zeroq1; CalcBSpline(k-1, ts_r, ts, i+1, x_r, x, &bs1, &zeroq1); double eps = 0.000000001; PetscScalar acc = 0.0; if(ScalarAbs(bs0) > eps && !zeroq0) acc += (k-1)/(ts[i+k-1]-ts[i]) * bs0; if(ScalarAbs(bs1) > eps && !zeroq1) acc -= (k-1)/(ts[i+k]-ts[i+1]) * bs1; *y = acc; _zeroq = (zeroq0 && zeroq1); } if(zeroq != NULL) *zeroq = _zeroq; return 0; }
PetscErrorCode BSSBasisPsi(BSS self, int i, PetscReal x, PetscScalar *y) { PetscErrorCode ierr; ierr = BSSCheck(self); CHKERRQ(ierr); PetscScalar z; PetscReal xs[1] = {x}; PetscScalar Rxs[1]; CScalingCalc(self->c_scaling, xs, 1, NULL, Rxs); CalcBSpline(self->order, self->ts_r, self->ts_s, self->b_idx_list[i], xs[0], Rxs[0], &z, NULL); *y = z; return 0; }
int testCalcBSpline() { PrintTimeStamp(PETSC_COMM_SELF, "calc", NULL); // see paper int order = 3; // overlaped knot points list double ts_r[10] = {0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 5.0, 5.0}; PetscScalar ts_s[10]; for(int i = 0; i < 10; i++) ts_s[i] = ts_r[i]; // non overlaped points list //double zs[6] = {0.0, 1.0, 2.0, 3.0, 4.0, 5.0}; PetscBool zeroq; PetscScalar y = 777.0; CalcBSpline(order, ts_r, ts_s, 0, 0.0, 0.0, &y, &zeroq); ASSERT_DOUBLE_EQ(1.0, y); ASSERT_FALSE(zeroq); CalcBSpline(order, ts_r, ts_s, 0, 1.0, 1.0, &y, &zeroq); ASSERT_DOUBLE_EQ(0.0, y); ASSERT_TRUE(zeroq); CalcBSpline(order, ts_r, ts_s, 6, 4.0, 4.0, &y, &zeroq); ASSERT_DOUBLE_EQ(0.0, y); ASSERT_TRUE(zeroq); PetscScalar x = 0.34; CalcBSpline( order, ts_r, ts_s, 2, x, x, &y, &zeroq); ASSERT_DOUBLE_EQ(0.5*x*x, y); ASSERT_FALSE(zeroq); CalcDerivBSpline(order, ts_r, ts_s, 2, x, x, &y, &zeroq); ASSERT_DOUBLE_EQ(x, y); ASSERT_FALSE(zeroq); x = 2.44; CalcBSpline( order, ts_r, ts_s, 2, x, x, &y, &zeroq); ASSERT_DOUBLE_EQ(0.5*x*x-3*x+4.5, y); ASSERT_FALSE(zeroq); CalcDerivBSpline(order, ts_r, ts_s, 2, x, x, &y, &zeroq); ASSERT_DOUBLE_EQ(x-3.0, y); ASSERT_FALSE(zeroq); x = 3.44; CalcBSpline( order, ts_r, ts_s, 2, x, x, &y, &zeroq); ASSERT_DOUBLE_EQ(0.0, y); ASSERT_TRUE(zeroq); CalcDerivBSpline(order, ts_r, ts_s, 2, x, x, &y, &zeroq); ASSERT_DOUBLE_EQ(0.0, y); ASSERT_TRUE(zeroq); return 0; }
PetscErrorCode CalcBSpline(int k, double* ts_r, PetscScalar* ts, int i, double x_r, PetscScalar x, PetscScalar* y, PetscBool *zeroq) { if(k < 1) { SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "order must be positive integer\n"); } PetscBool _zeroq; if(x_r < ts_r[i] || ts_r[i+k] < x_r) { *y = 0.0; if(zeroq != NULL) *zeroq = PETSC_TRUE; return 0; } if(k == 1) { if(ts_r[i] <= x_r && x_r < ts_r[i+1]) { *y = 1.0; _zeroq = PETSC_FALSE; } else { *y = 0.0; _zeroq = PETSC_TRUE; } } else { PetscScalar ti = ts[i]; PetscScalar ti1 = ts[i+1]; PetscScalar tidm1 = ts[i+k-1]; PetscScalar tid = ts[i+k]; PetscBool zeroq0, zeroq1; PetscScalar bs0; CalcBSpline(k-1, ts_r, ts, i, x_r, x, &bs0, &zeroq0); PetscScalar bs1; CalcBSpline(k-1, ts_r, ts, i+1, x_r, x, &bs1, &zeroq1); _zeroq = PETSC_TRUE; PetscScalar acc = 0.0; //if(ScalarAbs(bs0) > 0.000000001 && !zeroq0) { if(!zeroq0) { PetscScalar x_minus_ti = x - ti; if(ScalarAbs(x_minus_ti) > 0.00000000001) { acc += x_minus_ti / (tidm1 - ti) * bs0; } else { zeroq0 = PETSC_TRUE; } } // if(ScalarAbs(bs1) > 0.000000001 && !zeroq1) { if( !zeroq1) { if(ScalarAbs(tid-x) > 0.00000000001) { acc += (tid - x) / (tid - ti1) * bs1; } else { zeroq1 = PETSC_TRUE; } } *y = acc; _zeroq = zeroq1 && zeroq0; } if(zeroq != NULL) *zeroq = _zeroq; return 0; }
PetscErrorCode BSSSetUp(BSS self) { PetscErrorCode ierr; // check knots are setted if(!self->set_knots) SETERRQ(self->comm, 1, "Knots information is not setted. Call BSSSetKnots first."); // set default scaler if(self->c_scaling == NULL) BSSSetCScaling(self, NULL); // copy ts_r and ts_s PetscReal *zs; PetscInt num_zs; BPSGetZs(self->bps, &zs, &num_zs); for(int i = 0; i < self->order-1; i++) { self->ts_r[i] = zs[0]; self->ts_r[self->order-1+num_zs+i] = zs[num_zs-1]; } for(int i = 0; i < num_zs; i++) self->ts_r[i+self->order-1] = zs[i]; PetscFree(zs); CScalingCalc(self->c_scaling, self->ts_r, self->num_ts, NULL, self->ts_s); // for(int i = 0; i < self->num_ts; i++) // self->ts_s[i] = self->ts_r[i]; // index of basis for(int ib = 0; ib < self->num_basis; ib++) self->b_idx_list[ib] = ib + 1; // each element for(int ie = 0; ie < self->num_ele; ie++) { PetscScalar a, b; a = self->bps->zs[ie]; b = self->bps->zs[ie+1]; for(int iq = 0; iq < self->order; iq++) { PetscReal x_r[1], w_r[1]; PetscScalar x_c[1]; int ix = ie*self->order+iq; PetscScalar quad_x, quad_w; LegGauss(self->order, iq, &quad_x, &quad_w); x_r[0] = creal(quad_x); w_r[0] = creal(quad_w); x_r[0] = (b+a)/2.0 + (b-a)/2.0 * x_r[0]; w_r[0] = (b-a)/2.0*w_r[0]; CScalingCalc(self->c_scaling, x_r, 1, NULL, x_c); self->xs[ix] = x_r[0]; self->ws[ix] = w_r[0]; self->xs_s[ix] = x_c[0]; for(int ib = 0; ib < self->num_basis; ib++) { PetscScalar y; PetscScalar dy; PetscReal *ts_r = self->ts_r; PetscScalar *ts_s = self->ts_s; int idx = self->b_idx_list[ib]; CalcBSpline( self->order, ts_r, ts_s, idx, x_r[0], x_c[0], &y, NULL); CalcDerivBSpline(self->order, ts_r, ts_s, idx, x_r[0], x_c[0], &dy, NULL); int iy = ib*(self->num_ele*self->order) + ie*self->order + iq; self->vals[iy] = y; self->derivs[iy] = dy; } } } int n_xs = self->num_ele * self->order; ierr = CScalingCalc(self->c_scaling, self->xs, n_xs, self->qrs, self->Rrs); CHKERRQ(ierr); self->setup = PETSC_TRUE; return 0; }