def build_system(self, q, q0, R_load=None): """Build the matrix system of equations for the next Newton step.""" DT = self._sess.run(self._vars['Dt']) R0_vol_arr = self._sess.run([self.rhs], feed_dict={self.i_q: q0.reshape(-1, 2)}) # The mass component at t vol_R0, = cf.Assemble(husk_identity.kernel_idty_R, self.H_vol, { 'iR': (R0_vol_arr, self.dm_q), }, { 'R': (self.dm_q, ), }, ndof=self.X.shape[0] * 2) # Assemble the mass component at t+Dt: K_vol_arr, R_vol_arr = self._sess.run( [self.K_lhs, self.lhs], feed_dict={self.i_q: q.reshape(-1, 2)}) vol_R, vol_K = cf.Assemble(husk_identity.kernel_idty_RK, self.H_vol, { 'iR': (R_vol_arr, self.dm_q), 'iK': (K_vol_arr, self.dm_4) }, { 'R': (self.dm_q, ), 'K': (self.dm_q, ) }, ndof=self.X.shape[0] * 2) # Assemble the fluxes: q_face = np.array([q[self.dm_q.Get_List(e[0:2])] for e in self.H_face]) X_face = np.array( [self.X.ravel()[self.dm_q.Get_List(e[0:2])] for e in self.H_face]) qA = q_face[:, 0:2] qB = q_face[:, 2:4] XA = X_face[:, 0:2] XB = X_face[:, 2:4] oF, oKF = self._sess.run([self.o_F, self.o_KF], feed_dict={ self.i_q: qA, self.i_q2: qB, self.i_XA: XA, self.i_XB: XB }) flux_R, flux_K = cf.Assemble(husk_identity.kernel_idty_2_RK, self.H_face, { 'iR': (oF.flatten(), self.dm_face), 'iK': (oKF.flatten(), self.dm_face16) }, { 'R': (self.dm_q, ), 'K': (self.dm_q, ) }, ndof=self.X.shape[0] * 2) # Make the runge kutta system RR = vol_R0 - vol_R + DT * flux_R if not R_load is None: RR += R_load KK = vol_K - DT * flux_K return RR, KK
def solve(self, method, weight, P=1.0, smoothing="", stab=2.0, fictmet="trivial"): """ Solves the deformation of the block matrix given the method name and influence function. The influence support is decided at initialization of the PeriBlock object. The method and weight strings key directly into the peridynamics kernels in the husk. There is an additional smoothing argument, which, if not false-valued, will call the smoothing kernel after assembling and solving the system. If there are cut bonds present, self.HCut, the P argument will be used to apply the fluid-filled pressure force on the bonds. """ # Assemble the matrix and load for the given peridynamics law K, R = self._assemble_KR(method, weight, stab) # Assemble the fluid pressure on bonds if present try: Rp, = cf.Assemble( hb.kernel_bond_pressure, self.HCut, [self.data, { 'p': (np.array([P]), self.dm_GlobalSca) }], { 'R': (self.dm_PtVec, ), }, gdim * self.NPart) R += Rp except AttributeError: pass # Add the ficticious domain component if self.ficticious: K, R = self._assemble_KR_fict(K, R, fictmet, method, weight, stab) else: R -= self.data['load'][0].ravel( ) * self.data['p_Vol'][0]**0.5 / self.data['p_Vol'][0] # Apply boundary conditions and then solve the matrix system cf.Apply_BC(self.diridofs, self.ubc, K, R) u = splin.spsolve(K, R) # If we specified a smoothing function, post process the solution if smoothing: us, = cf.Assemble(hp.__dict__['kernel_smooth_{0}'.format(weight)], self.HAdj, [self.data, { 'y': (u, self.dm_PtVec) }], {'ys': (self.dm_PtVec, )}, gdim * self.NPart) u = us # The PeriBlock object is stateless w.r.t. solution, so return u
def _assemble_KR(self, method, weight, stab=0.0): K, R = cf.Assemble( hp.__dict__['kernel_{0}_{1}'.format(method, weight)], self.HAdj, [self.data, { 'p_stab': (np.array([stab]), self.dm_GlobalSca) }], { 'R': (self.dm_PtVec, ), 'K': (self.dm_PtVec, ) }, gdim * self.NPart) return K, R
def _assemble_KR_fict(self, K, R, fictmet, method, weight, stab=0.0): if fictmet == "trivial": Kf, Rf = cf.Assemble( hp.__dict__['kernel_{0}_{1}'.format(method, weight)], self.HFict, [self.data, { 'p_stab': (np.array([stab]), self.dm_GlobalSca) }], { 'R': (self.dm_PtVec, ), 'K': (self.dm_PtVec, ) }, gdim * self.NPart) Rf -= self.data['load'][0].ravel( ) * self.data['p_Vol'][0]**0.5 / self.data['p_Vol'][0] return K + Kf, R + Rf elif fictmet == "bobaru": K3, R3 = cf.Assemble(hf.kernel_bobaru_n3, self.HFictStencil3, self.data, { 'R': (self.dm_PtVec, ), 'K': (self.dm_PtVec, ) }, gdim * self.NPart) K4, R4 = cf.Assemble(hf.kernel_bobaru_n, self.HFictStencil4, self.data, { 'R': (self.dm_PtVec, ), 'K': (self.dm_PtVec, ) }, gdim * self.NPart) Kb = K3 + K4 Rb = R3 + R4 Kt = K.copy() Rt = R.copy() for e in self.FictNodes: Kt[self.dm_PtVec.Get_List([e]), :] = Kb[ self.dm_PtVec.Get_List([e]), :] Rt[self.dm_PtVec.Get_List([e ])] = Rb[self.dm_PtVec.Get_List([e ])] return Kt, Rt elif fictmet == "bobaru_F": K3, R3 = cf.Assemble(hf.kernel_bobaru_F3, self.HFictStencil3, self.data, { 'R': (self.dm_PtVec, ), 'K': (self.dm_PtVec, ) }, gdim * self.NPart) K4, R4 = cf.Assemble(hf.kernel_bobaru_F, self.HFictStencil4, self.data, { 'R': (self.dm_PtVec, ), 'K': (self.dm_PtVec, ) }, gdim * self.NPart) Kb = K3 + K4 Rb = R3 + R4 Kt = K.copy() Rt = R.copy() for e in self.FictNodes: Kt[self.dm_PtVec.Get_List([e]), :] = Kb[ self.dm_PtVec.Get_List([e]), :] Rt[self.dm_PtVec.Get_List([e ])] = Rb[self.dm_PtVec.Get_List([e ])] return Kt, Rt elif fictmet == "both": Kp, Rp = cf.Assemble( hp.__dict__['kernel_{0}_{1}'.format(method, weight)], self.HFict, [self.data, { 'p_stab': (np.array([stab]), self.dm_GlobalSca) }], { 'R': (self.dm_PtVec, ), 'K': (self.dm_PtVec, ) }, gdim * self.NPart) K3, R3 = cf.Assemble(hf.kernel_bobaru_n3, self.HFictStencil3, self.data, { 'R': (self.dm_PtVec, ), 'K': (self.dm_PtVec, ) }, gdim * self.NPart) K4, R4 = cf.Assemble(hf.kernel_bobaru_n, self.HFictStencil4, self.data, { 'R': (self.dm_PtVec, ), 'K': (self.dm_PtVec, ) }, gdim * self.NPart) Kb = K3 + K4 Rb = R3 + R4 Kt = K + Kp Rt = R + Rp for e in self.FictNodes: Kt[self.dm_PtVec.Get_List([e]), :] = Kb[ self.dm_PtVec.Get_List([e]), :] Rt[self.dm_PtVec.Get_List([e ])] = Rb[self.dm_PtVec.Get_List([e ])] return Kt, Rt return K, R
'p_vol': (np.array([particle_Vol]), dm_GlobalSca), } # Mark boundaries eps = 1.0e-10 right = cf.select_nodes(x, lambda a: a[0] < -L + eps) left = cf.select_nodes(x, lambda a: a[0] > L - eps) bottom = cf.select_nodes(x, lambda a: a[1] < -L + eps) top = cf.select_nodes(x, lambda a: a[1] > L - eps) loaddofs = dm_PtVec.Get_List(top)[1::2] dirrdofs = np.array([ dm_PtVec.Get_List(right)[0::2], dm_PtVec.Get_List(left)[0::2], dm_PtVec.Get_List(bottom)[1::2] ]).flatten() Nbc = len(dirrdofs) ubc = np.zeros(Nbc) # Make the linear system K, R = cf.Assemble(hp.kernel_Silling_cubic, HAdj, data, { 'R': (cf.Dofmap_Strided(gdim), ), 'K': (cf.Dofmap_Strided(gdim), ) }, gdim * NPart) cf.Apply_BC(dirrdofs, ubc, K, R) R[loaddofs] -= 1.0 u = splin.spsolve(K, R) cf.GraphIO.write_graph("./out.vtk", HPair, x, [('x', x), ('u', u.reshape((-1, 2)))])