def run_laplacian_debug(self, x): """Compute the trained derivative (debug version).""" n = len(x) m = len(self.eq.bc) H = len(self.v) w = self.w u = self.u v = self.v z = np.zeros((n, H)) for i in range(n): for k in range(H): z[i, k] = u[k] for j in range(m): z[i, k] += w[j, k] * x[i, j] s = np.zeros((n, H)) for i in range(n): for k in range(H): s[i, k] = sigma.s(z[i, k]) s1 = np.zeros((n, H)) for i in range(n): for k in range(H): s1[i, k] = sigma.s1(s[i, k]) s2 = np.zeros((n, H)) for i in range(n): for k in range(H): s2[i, k] = sigma.s2(s[i, k]) N = np.zeros(n) for i in range(n): for k in range(H): N[i] += s[i, k] * v[k] delN = np.zeros((n, m)) for i in range(n): for j in range(m): for k in range(H): delN[i, j] += v[k] * s1[i, k] * w[j, k] del2N = np.zeros((n, m)) for i in range(n): for j in range(m): for k in range(H): del2N[i, j] += v[k] * s2[i, k] * w[j, k]**2 del2Yt = np.zeros((n, m)) for i in range(n): del2Yt[i] = self.tf.del2Yt(x[i], N[i], delN[i], del2N[i]) return del2Yt
def _train_delta_debug(self, x, opts=DEFAULT_OPTS): """Train using the delta method (debug version). """ my_opts = dict(DEFAULT_OPTS) my_opts.update(opts) # Sanity-check arguments. assert len(x) > 0 assert opts['maxepochs'] > 0 assert opts['eta'] > 0 assert opts['vmin'] < opts['vmax'] assert opts['wmin'] < opts['wmax'] assert opts['umin'] < opts['umax'] # Determine the number of training points, independent variables, and # hidden nodes. n = len(x) # Number of training points m = len(self.eq.bc) H = len(self.v) # Number of hidden nodes # Change notation for convenience. debug = my_opts['debug'] verbose = my_opts['verbose'] eta = my_opts['eta'] # Learning rate maxepochs = my_opts['maxepochs'] # Number of training epochs wmin = my_opts['wmin'] # Network parameter limits wmax = my_opts['wmax'] umin = my_opts['umin'] umax = my_opts['umax'] vmin = my_opts['vmin'] vmax = my_opts['vmax'] # Create the hidden node weights, biases, and output node weights. w = np.random.uniform(wmin, wmax, (m, H)) u = np.random.uniform(umin, umax, H) v = np.random.uniform(vmin, vmax, H) # Initial parameter deltas are 0. dE_dw = np.zeros((m, H)) dE_du = np.zeros(H) dE_dv = np.zeros(H) # Train the network. for epoch in range(maxepochs): if debug: print('Starting epoch %d.' % epoch) # Compute the new values of the network parameters. for j in range(m): for k in range(H): w[j, k] -= eta*dE_dw[j, k] for k in range(H): u[k] -= eta*dE_du[k] for k in range(H): v[k] -= eta*dE_dv[k] # Compute the input, the sigmoid function, and its derivatives, # for each hidden node and each training point. z = np.zeros((n, H)) for i in range(n): for k in range(H): z[i, k] = u[k] for j in range(m): z[i, k] += w[j, k]*x[i, j] s = np.zeros((n, H)) for i in range(n): for k in range(H): s[i, k] = sigma.s(z[i, k]) s1 = np.zeros((n, H)) for i in range(n): for k in range(H): s1[i, k] = sigma.s1(s[i, k]) s2 = np.zeros((n, H)) for i in range(n): for k in range(H): s2[i, k] = sigma.s2(s[i, k]) # Compute the network output and its derivatives, for each # training point. N = np.zeros(n) for i in range(n): for k in range(H): N[i] += v[k]*s[i, k] P = np.zeros(n) for i in range(n): P[i] = self._P(x[i]) delP = np.zeros((n, m)) for i in range(n): for j in range(m): delP[i, j] = self._delP[j](self, x[i]) delN = np.zeros((n, m)) for i in range(n): for j in range(m): for k in range(H): delN[i, j] += v[k]*s1[i, k]*w[j, k] dN_dw = np.zeros((n, m, H)) for i in range(n): for j in range(m): for k in range(H): dN_dw[i, j, k] = v[k]*s1[i, k]*x[i, j] dN_du = np.zeros((n, H)) for i in range(n): for k in range(H): dN_du[i, k] = v[k]*s1[i, k] dN_dv = np.zeros((n, H)) for i in range(n): for k in range(H): dN_dv[i, k] = s[i, k] d2N_dwdx = np.zeros((n, m, m, H)) for i in range(n): for j in range(m): for jj in range(m): for k in range(H): d2N_dwdx[i, j, jj, k] = ( v[k]*(s1[i, k]*kdelta(j, jj) + s2[i, k]*w[jj, k]*x[i, j]) ) d2N_dudx = np.zeros((n, m, H)) for i in range(n): for j in range(m): for k in range(H): d2N_dudx[i, j, k] = v[k]*s2[i, k]*w[j, k] d2N_dvdx = np.zeros((n, m, H)) for i in range(n): for j in range(m): for k in range(H): d2N_dvdx[i, j, k] = s1[i, k]*w[j, k] # Compute the value of the trial solution and its derivatives, # for each training point. Yt = np.zeros(n) for i in range(n): Yt[i] = self._Yt(x[i], N[i]) delYt = np.zeros((n, m)) for i in range(n): for j in range(m): delYt[i, j] = self._delYt[j](self, x[i], N[i], delN[i]) dYt_dw = np.zeros((n, m, H)) for i in range(n): for j in range(m): for k in range(H): dYt_dw[i, j, k] = P[i]*dN_dw[i, j, k] dYt_du = np.zeros((n, H)) for i in range(n): for k in range(H): dYt_du[i, k] = P[i]*dN_du[i, k] dYt_dv = np.zeros((n, H)) for i in range(n): for k in range(H): dYt_dv[i, k] = P[i]*dN_dv[i, k] d2Yt_dwdx = np.zeros((n, m, m, H)) for i in range(n): for j in range(m): for jj in range(m): for k in range(H): d2Yt_dwdx[i, j, jj, k] = ( P[i]*d2N_dwdx[i, j, jj, k] + delP[i, jj]*dN_dw[i, j, k] ) d2Yt_dudx = np.zeros((n, m, H)) for i in range(n): for j in range(m): for k in range(H): d2Yt_dudx[i, j, k] = ( P[i]*d2N_dudx[i, j, k] + delP[i, j]*dN_du[i, k] ) d2Yt_dvdx = np.zeros((n, m, H)) for i in range(n): for j in range(m): for k in range(H): d2Yt_dvdx[i, j, k] = ( P[i]*d2N_dvdx[i, j, k] + delP[i, j]*dN_dv[i, k] ) # Compute the value of the original differential equation for # each training point, and its derivatives. G = np.zeros(n) for i in range(n): G[i] = self.eq.G(x[i], Yt[i], delYt[i]) dG_dYt = np.zeros(n) for i in range(n): dG_dYt[i] = self.eq.dG_dY(x[i], Yt[i], delYt[i]) dG_ddelYt = np.zeros((n, m)) for i in range(n): for j in range(m): dG_ddelYt[i, j] = ( self.eq.dG_ddelY[j](x[i], Yt[i], delYt[i]) ) dG_dw = np.zeros((n, m, H)) for i in range(n): for j in range(m): for k in range(H): dG_dw[i, j, k] = dG_dYt[i]*dYt_dw[i, j, k] for jj in range(m): dG_dw[i, j, k] += ( dG_ddelYt[i, jj]*d2Yt_dwdx[i, j, jj, k] ) dG_du = np.zeros((n, H)) for i in range(n): for k in range(H): dG_du[i, k] = dG_dYt[i]*dYt_du[i, k] for j in range(m): dG_du[i, k] += dG_ddelYt[i, j]*d2Yt_dudx[i, j, k] dG_dv = np.zeros((n, H)) for i in range(n): for k in range(H): dG_dv[i, k] = dG_dYt[i]*dYt_dv[i, k] for j in range(m): dG_dv[i, k] += dG_ddelYt[i, j]*d2Yt_dvdx[i, j, k] # Compute the error function for this epoch. E = 0 for i in range(n): E += G[i]**2 # Compute the partial derivatives of the error with respect to # the network parameters. dE_dw = np.zeros((m, H)) for j in range(m): for k in range(H): for i in range(n): dE_dw[j, k] += 2*G[i]*dG_dw[i, j, k] dE_du = np.zeros(H) for k in range(H): for i in range(n): dE_du[k] += 2*G[i]*dG_du[i, k] dE_dv = np.zeros(H) for k in range(H): for i in range(n): dE_dv[k] += 2*G[i]*dG_dv[i, k] # Compute the RMS error for this epoch. rmse = sqrt(E/n) if verbose: print(epoch, rmse) # Save the optimized parameters. self.w = w self.u = u self.v = v
def _compute_error_debug(self, p, x): """Compute the error function using the current parameter values (debug version).""" # Determine the number of training points, independent variables, and # hidden nodes. n = len(x) m = len(self.eq.bc) H = len(self.v) # Unpack the network parameters. w = np.zeros((m, H)) for j in range(m): w[j] = p[j * H:(j + 1) * H] u = p[m * H:(m + 1) * H] v = p[(m + 1) * H:(m + 2) * H] # Compute the forward pass through the network. z = np.zeros((n, H)) for i in range(n): for k in range(H): z[i, k] = u[k] for j in range(m): z[i, k] += w[j, k] * x[i, j] s = np.zeros((n, H)) for i in range(n): for k in range(H): s[i, k] = sigma.s(z[i, k]) s1 = np.zeros((n, H)) for i in range(n): for k in range(H): s1[i, k] = sigma.s1(s[i, k]) s2 = np.zeros((n, H)) for i in range(n): for k in range(H): s2[i, k] = sigma.s2(s[i, k]) N = np.zeros(n) for i in range(n): for k in range(H): N[i] += v[k] * s[i, k] delN = np.zeros((n, m)) for i in range(n): for j in range(m): for k in range(H): delN[i, j] += v[k] * s1[i, k] * w[j, k] del2N = np.zeros((n, m)) for i in range(n): for j in range(m): for k in range(H): del2N[i, j] += v[k] * s2[i, k] * w[j, k]**2 Yt = np.zeros(n) for i in range(n): Yt[i] = self.tf.Yt(x[i], N[i]) delYt = np.zeros((n, m)) for i in range(n): delYt[i] = self.tf.delYt(x[i], N[i], delN[i]) del2Yt = np.zeros((n, m)) for i in range(n): del2Yt[i] = self.tf.del2Yt(x[i], N[i], delN[i], del2N[i]) G = np.zeros(n) for i in range(n): G[i] = self.eq.G(x[i], Yt[i], delYt[i], del2Yt[i]) E2 = 0 for i in range(n): E2 += G[i]**2 return E2
def _train_delta_debug(self, x, opts=DEFAULT_OPTS): """Train using the delta method (debug version).""" my_opts = dict(DEFAULT_OPTS) my_opts.update(opts) # Determine the number of training points, independent variables, and # hidden nodes. n = len(x) m = len(self.eq.bc) H = len(self.v) # Change notation for convenience. debug = my_opts["debug"] verbose = my_opts["verbose"] eta = my_opts["eta"] # Learning rate maxepochs = my_opts["maxepochs"] # Number of training epochs wmin = my_opts["wmin"] # Network parameter limits wmax = my_opts["wmax"] umin = my_opts["umin"] umax = my_opts["umax"] vmin = my_opts["vmin"] vmax = my_opts["vmax"] # Create the hidden node weights, biases, and output node weights. w = np.random.uniform(wmin, wmax, (m, H)) u = np.random.uniform(umin, umax, H) v = np.random.uniform(vmin, vmax, H) # w = np.zeros((m, H)) # u = np.zeros(H) # v = np.zeros(H) # Initial parameter deltas are 0. dE_dw = np.zeros((m, H)) dE_du = np.zeros(H) dE_dv = np.zeros(H) # Train the network. for epoch in range(maxepochs): if debug: print("Starting epoch %d." % epoch) # Compute the new values of the network parameters. for j in range(m): for k in range(H): w[j, k] -= eta * dE_dw[j, k] for k in range(H): u[k] -= eta * dE_du[k] for k in range(H): v[k] -= eta * dE_dv[k] # Compute the input, the sigmoid function, and its derivatives, # for each hidden node and each training point. z = np.zeros((n, H)) for i in range(n): for k in range(H): z[i, k] = u[k] for j in range(m): z[i, k] += w[j, k] * x[i, j] s = np.zeros((n, H)) for i in range(n): for k in range(H): s[i, k] = sigma.s(z[i, k]) s1 = np.zeros((n, H)) for i in range(n): for k in range(H): s1[i, k] = sigma.s1(s[i, k]) s2 = np.zeros((n, H)) for i in range(n): for k in range(H): s2[i, k] = sigma.s2(s[i, k]) s3 = np.zeros((n, H)) for i in range(n): for k in range(H): s3[i, k] = sigma.s3(s[i, k]) # Compute the network output and its derivatives, for each # training point. N = np.zeros(n) for i in range(n): for k in range(H): N[i] += v[k] * s[i, k] delN = np.zeros((n, m)) for i in range(n): for j in range(m): for k in range(H): delN[i, j] += v[k] * s1[i, k] * w[j, k] del2N = np.zeros((n, m)) for i in range(n): for j in range(m): for k in range(H): del2N[i, j] += v[k] * s2[i, k] * w[j, k]**2 dN_dw = np.zeros((n, m, H)) for i in range(n): for j in range(m): for k in range(H): dN_dw[i, j, k] = v[k] * s1[i, k] * x[i, j] dN_du = np.zeros((n, H)) for i in range(n): for k in range(H): dN_du[i, k] = v[k] * s1[i, k] dN_dv = np.zeros((n, H)) for i in range(n): for k in range(H): dN_dv[i, k] = s[i, k] d2N_dwdx = np.zeros((n, m, m, H)) for i in range(n): for j in range(m): for jj in range(m): for k in range(H): d2N_dwdx[i, j, jj, k] = (v[k] * (s1[i, k] * kdelta(j, jj) + s2[i, k] * w[jj, k] * x[i, j])) d2N_dudx = np.zeros((n, m, H)) for i in range(n): for j in range(m): for k in range(H): d2N_dudx[i, j, k] = v[k] * s2[i, k] * w[j, k] d2N_dvdx = np.zeros((n, m, H)) for i in range(n): for j in range(m): for k in range(H): d2N_dvdx[i, j, k] = s1[i, k] * w[j, k] d3N_dwdx2 = np.zeros((n, m, m, H)) for i in range(n): for j in range(m): for jj in range(m): for k in range(H): d3N_dwdx2[i, j, jj, k] = ( v[k] * (2 * s2[i, k] * w[jj, k] * kdelta(j, jj) + s3[i, k] * w[j, k]**2 * x[i, j])) d3N_dudx2 = np.zeros((n, m, H)) for i in range(n): for j in range(m): for k in range(H): d3N_dudx2[i, j, k] = v[k] * s3[i, k] * w[j, k]**2 d3N_dvdx2 = np.zeros((n, m, H)) for i in range(n): for j in range(m): for k in range(H): d3N_dvdx2[i, j, k] = s2[i, k] * w[j, k]**2 # Compute the value of the trial solution and its derivatives, # for each training point. P = np.zeros(n) for i in range(n): P[i] = self.tf.P(x[i]) delP = np.zeros((n, m)) for i in range(n): delP[i] = self.tf.delP(x[i]) del2P = np.zeros((n, m)) for i in range(n): del2P[i] = self.tf.del2P(x[i]) Yt = np.zeros(n) for i in range(n): Yt[i] = self.tf.Yt(x[i], N[i]) delYt = np.zeros((n, m)) for i in range(n): delYt[i] = self.tf.delYt(x[i], N[i], delN[i]) del2Yt = np.zeros((n, m)) for i in range(n): del2Yt[i] = self.tf.del2Yt(x[i], N[i], delN[i], del2N[i]) dYt_dw = np.zeros((n, m, H)) for i in range(n): for j in range(m): for k in range(H): dYt_dw[i, j, k] = P[i] * dN_dw[i, j, k] dYt_du = np.zeros((n, H)) for i in range(n): for k in range(H): dYt_du[i, k] = P[i] * dN_du[i, k] dYt_dv = np.zeros((n, H)) for i in range(n): for k in range(H): dYt_dv[i, k] = P[i] * dN_dv[i, k] d2Yt_dwdx = np.zeros((n, m, m, H)) for i in range(n): for j in range(m): for jj in range(m): for k in range(H): d2Yt_dwdx[i, j, jj, k] = (P[i] * d2N_dwdx[i, j, jj, k] + delP[i, jj] * dN_dw[i, j, k]) d2Yt_dudx = np.zeros((n, m, H)) for i in range(n): for j in range(m): for k in range(H): d2Yt_dudx[i, j, k] = (P[i] * d2N_dudx[i, j, k] + delP[i, j] * dN_du[i, k]) d2Yt_dvdx = np.zeros((n, m, H)) for i in range(n): for j in range(m): for k in range(H): d2Yt_dvdx[i, j, k] = (P[i] * d2N_dvdx[i, j, k] + delP[i, j] * dN_dv[i, k]) d3Yt_dwdx2 = np.zeros((n, m, m, H)) for i in range(n): for j in range(m): for jj in range(m): for k in range(H): d3Yt_dwdx2[i, j, jj, k] = ( P[i] * d3N_dwdx2[i, j, jj, k] + 2 * delP[i, jj] * d2N_dwdx[i, j, jj, k] + del2P[i, jj] * dN_dw[i, j, k]) d3Yt_dudx2 = np.zeros((n, m, H)) for i in range(n): for j in range(m): for k in range(H): d3Yt_dudx2[i, j, k] = (P[i] * d3N_dudx2[i, j, k] + 2 * delP[i, j] * d2N_dudx[i, j, k] + del2P[i, j] * dN_du[i, k]) d3Yt_dvdx2 = np.zeros((n, m, H)) for i in range(n): for j in range(m): for k in range(H): d3Yt_dvdx2[i, j, k] = (P[i] * d3N_dvdx2[i, j, k] + 2 * delP[i, j] * d2N_dvdx[i, j, k] + del2P[i, j] * dN_dv[i, k]) # Compute the value of the original differential equation # for each training point, and its derivatives. G = np.zeros(n) for i in range(n): G[i] = self.eq.G(x[i], Yt[i], delYt[i], del2Yt[i]) dG_dYt = np.zeros(n) for i in range(n): dG_dYt[i] = self.eq.dG_dY(x[i], Yt[i], delYt[i], del2Yt[i]) dG_ddelYt = np.zeros((n, m)) for i in range(n): for j in range(m): dG_ddelYt[i, j] = (self.eq.dG_ddelY[j](x[i], Yt[i], delYt[i], del2Yt[i])) dG_ddel2Yt = np.zeros((n, m)) for i in range(n): for j in range(m): dG_ddel2Yt[i, j] = (self.eq.dG_ddel2Y[j](x[i], Yt[i], delYt[i], del2Yt[i])) dG_dw = np.zeros((n, m, H)) for i in range(n): for j in range(m): for k in range(H): dG_dw[i, j, k] = dG_dYt[i] * dYt_dw[i, j, k] for jj in range(m): dG_dw[i, j, k] += ( dG_ddelYt[i, jj] * d2Yt_dwdx[i, j, jj, k] + dG_ddel2Yt[i, jj] * d3Yt_dwdx2[i, j, jj, k]) dG_du = np.zeros((n, H)) for i in range(n): for k in range(H): dG_du[i, k] = dG_dYt[i] * dYt_du[i, k] for j in range(m): dG_du[i, k] += (dG_ddelYt[i, j] * d2Yt_dudx[i, j, k] + dG_ddel2Yt[i, j] * d3Yt_dudx2[i, j, k]) dG_dv = np.zeros((n, H)) for i in range(n): for k in range(H): dG_dv[i, k] = dG_dYt[i] * dYt_dv[i, k] for j in range(m): dG_dv[i, k] += (dG_ddelYt[i, j] * d2Yt_dvdx[i, j, k] + dG_ddel2Yt[i, j] * d3Yt_dvdx2[i, j, k]) # Compute the error function for this epoch. E2 = 0 for i in range(n): E2 += G[i]**2 if verbose: rmse = sqrt(E2 / n) print(epoch, rmse) # Compute the partial derivatives of the error with respect to the # network parameters. dE_dw = np.zeros((m, H)) for j in range(m): for k in range(H): for i in range(n): dE_dw[j, k] += 2 * G[i] * dG_dw[i, j, k] dE_du = np.zeros(H) for k in range(H): for i in range(n): dE_du[k] += 2 * G[i] * dG_du[i, k] dE_dv = np.zeros(H) for k in range(H): for i in range(n): dE_dv[k] += 2 * G[i] * dG_dv[i, k] # Save the optimized parameters. self.w = w self.u = u self.v = v
def _compute_error_jacobian_debug(self, p, x): """Compute the Jacobian of the error function (debug version).""" # Determine the number of training points, independent variables, and # hidden nodes. n = len(x) m = len(self.eq.bc) H = len(self.v) # Unpack the network parameters. w = np.zeros((m, H)) for j in range(m): w[j] = p[j * H:(j + 1) * H] u = p[m * H:(m + 1) * H] v = p[(m + 1) * H:(m + 2) * H] # Compute the forward pass through the network. z = np.zeros((n, H)) for i in range(n): for k in range(H): z[i, k] = u[k] for j in range(m): z[i, k] += w[j, k] * x[i, j] s = np.zeros((n, H)) for i in range(n): for k in range(H): s[i, k] = sigma.s(z[i, k]) s1 = np.zeros((n, H)) for i in range(n): for k in range(H): s1[i, k] = sigma.s1(s[i, k]) s2 = np.zeros((n, H)) for i in range(n): for k in range(H): s2[i, k] = sigma.s2(s[i, k]) s3 = np.zeros((n, H)) for i in range(n): for k in range(H): s3[i, k] = sigma.s3(s[i, k]) N = np.zeros(n) for i in range(n): for k in range(H): N[i] += v[k] * s[i, k] delN = np.zeros((n, m)) for i in range(n): for j in range(m): for k in range(H): delN[i, j] += v[k] * s1[i, k] * w[j, k] del2N = np.zeros((n, m)) for i in range(n): for j in range(m): for k in range(H): del2N[i, j] += v[k] * s2[i, k] * w[j, k]**2 dN_dw = np.zeros((n, m, H)) for i in range(n): for j in range(m): for k in range(H): dN_dw[i, j, k] = v[k] * s1[i, k] * x[i, j] dN_du = np.zeros((n, H)) for i in range(n): for k in range(H): dN_du[i, k] = v[k] * s1[i, k] dN_dv = np.zeros((n, H)) for i in range(n): for k in range(H): dN_dv[i, k] = s[i, k] d2N_dwdx = np.zeros((n, m, m, H)) for i in range(n): for j in range(m): for jj in range(m): for k in range(H): d2N_dwdx[i, j, jj, k] = (v[k] * (s1[i, k] * kdelta(j, jj) + s2[i, k] * w[jj, k] * x[i, j])) d2N_dudx = np.zeros((n, m, H)) for i in range(n): for j in range(m): for k in range(H): d2N_dudx[i, j, k] = v[k] * s2[i, k] * w[j, k] d2N_dvdx = np.zeros((n, m, H)) for i in range(n): for j in range(m): for k in range(H): d2N_dvdx[i, j, k] = s1[i, k] * w[j, k] d3N_dwdx2 = np.zeros((n, m, m, H)) for i in range(n): for j in range(m): for jj in range(m): for k in range(H): d3N_dwdx2[i, j, jj, k] = ( v[k] * (2 * s2[i, k] * w[jj, k] * kdelta(j, jj) + s3[i, k] * w[j, k]**2 * x[i, j])) d3N_dudx2 = np.zeros((n, m, H)) for i in range(n): for j in range(m): for k in range(H): d3N_dudx2[i, j, k] = v[k] * s3[i, k] * w[j, k]**2 d3N_dvdx2 = np.zeros((n, m, H)) for i in range(n): for j in range(m): for k in range(H): d3N_dvdx2[i, j, k] = s2[i, k] * w[j, k]**2 P = np.zeros(n) for i in range(n): P[i] = self.tf.P(x[i]) delP = np.zeros((n, m)) for i in range(n): delP[i] = self.tf.delP(x[i]) del2P = np.zeros((n, m)) for i in range(n): del2P[i] = self.tf.del2P(x[i]) Yt = np.zeros(n) for i in range(n): Yt[i] = self.tf.Yt(x[i], N[i]) delYt = np.zeros((n, m)) for i in range(n): delYt[i] = self.tf.delYt(x[i], N[i], delN[i]) del2Yt = np.zeros((n, m)) for i in range(n): del2Yt[i] = self.tf.del2Yt(x[i], N[i], delN[i], del2N[i]) dYt_dw = np.zeros((n, m, H)) for i in range(n): for j in range(m): for k in range(H): dYt_dw[i, j, k] = P[i] * dN_dw[i, j, k] dYt_du = np.zeros((n, H)) for i in range(n): for k in range(H): dYt_du[i, k] = P[i] * dN_du[i, k] dYt_dv = np.zeros((n, H)) for i in range(n): for k in range(H): dYt_dv[i, k] = P[i] * dN_dv[i, k] d2Yt_dwdx = np.zeros((n, m, m, H)) for i in range(n): for j in range(m): for jj in range(m): for k in range(H): d2Yt_dwdx[i, j, jj, k] = (P[i] * d2N_dwdx[i, j, jj, k] + delP[i, jj] * dN_dw[i, j, k]) d2Yt_dudx = np.zeros((n, m, H)) for i in range(n): for j in range(m): for k in range(H): d2Yt_dudx[i, j, k] = (P[i] * d2N_dudx[i, j, k] + delP[i, j] * dN_du[i, k]) d2Yt_dvdx = np.zeros((n, m, H)) for i in range(n): for j in range(m): for k in range(H): d2Yt_dvdx[i, j, k] = (P[i] * d2N_dvdx[i, j, k] + delP[i, j] * dN_dv[i, k]) d3Yt_dwdx2 = np.zeros((n, m, m, H)) for i in range(n): for j in range(m): for jj in range(m): for k in range(H): d3Yt_dwdx2[i, j, jj, k] = ( P[i] * d3N_dwdx2[i, j, jj, k] + 2 * delP[i, jj] * d2N_dwdx[i, j, jj, k] + del2P[i, jj] * dN_dw[i, j, k]) d3Yt_dudx2 = np.zeros((n, m, H)) for i in range(n): for j in range(m): for k in range(H): d3Yt_dudx2[i, j, k] = (P[i] * d3N_dudx2[i, j, k] + 2 * delP[i, j] * d2N_dudx[i, j, k] + del2P[i, j] * dN_du[i, k]) d3Yt_dvdx2 = np.zeros((n, m, H)) for i in range(n): for j in range(m): for k in range(H): d3Yt_dvdx2[i, j, k] = (P[i] * d3N_dvdx2[i, j, k] + 2 * delP[i, j] * d2N_dvdx[i, j, k] + del2P[i, j] * dN_dv[i, k]) G = np.zeros(n) for i in range(n): G[i] = self.eq.G(x[i], Yt[i], delYt[i], del2Yt[i]) dG_dYt = np.zeros(n) for i in range(n): dG_dYt[i] = self.eq.dG_dY(x[i], Yt[i], delYt[i], del2Yt[i]) dG_ddelYt = np.zeros((n, m)) for i in range(n): for j in range(m): dG_ddelYt[i, j] = (self.eq.dG_ddelY[j](x[i], Yt[i], delYt[i], del2Yt[i])) dG_ddel2Yt = np.zeros((n, m)) for i in range(n): for j in range(m): dG_ddel2Yt[i, j] = (self.eq.dG_ddel2Y[j](x[i], Yt[i], delYt[i], del2Yt[i])) dG_dw = np.zeros((n, m, H)) for i in range(n): for j in range(m): for k in range(H): dG_dw[i, j, k] = dG_dYt[i] * dYt_dw[i, j, k] for jj in range(m): dG_dw[i, j, k] += ( dG_ddelYt[i, jj] * d2Yt_dwdx[i, j, jj, k] + dG_ddel2Yt[i, jj] * d3Yt_dwdx2[i, j, jj, k]) dG_du = np.zeros((n, H)) for i in range(n): for k in range(H): dG_du[i, k] = dG_dYt[i] * dYt_du[i, k] for j in range(m): dG_du[i, k] += (dG_ddelYt[i, j] * d2Yt_dudx[i, j, k] + dG_ddel2Yt[i, j] * d3Yt_dudx2[i, j, k]) dG_dv = np.zeros((n, H)) for i in range(n): for k in range(H): dG_dv[i, k] = dG_dYt[i] * dYt_dv[i, k] for j in range(m): dG_dv[i, k] += (dG_ddelYt[i, j] * d2Yt_dvdx[i, j, k] + dG_ddel2Yt[i, j] * d3Yt_dvdx2[i, j, k]) dE_dw = np.zeros((m, H)) for j in range(m): for k in range(H): for i in range(n): dE_dw[j, k] += 2 * G[i] * dG_dw[i, j, k] dE_du = np.zeros(H) for k in range(H): for i in range(n): dE_du[k] += 2 * G[i] * dG_du[i, k] dE_dv = np.zeros(H) for k in range(H): for i in range(n): dE_dv[k] += 2 * G[i] * dG_dv[i, k] jac = np.hstack((dE_dw.flatten(), dE_du, dE_dv)) return jac