//  [python]
eigvalues = []
nepoch_u2 = int(nepoch_u2)
nepoch_u1 = int(nepoch_u1)
start = time.time()
for epoch_inter in range(nepoch_inter): # 两个神经网络交错优化
    print('the process : %i' % epoch_inter) # 交错优化的步骤数
    for epoch in range(nepoch_u2): # 两个一起优化
        if epoch ==1000:
            end = time.time()
            consume_time = end-start
            print('time is %f' % consume_time)
        if epoch%100 == 0:
            dom_koch_n = koch_points.get_koch_points(10000) # 获得n_test个koch的随机分布点
            dom_koch_n1 = dom_koch_n[(dom_koch_n[:,0]**2+dom_koch_n[:,1]**2)<r0**2]#定义内部的dom点，即是r<r0的点
            dom_koch_n2 = dom_koch_n[(dom_koch_n[:,0]**2+dom_koch_n[:,1]**2)>=r0**2]#定义内部的dom点，即是r<r0的点
            dom_koch_t1= torch.tensor(dom_koch_n1,  requires_grad=True, device = 'cuda') # 将numpy数据转化为tensor
            dom_koch_t2= torch.tensor(dom_koch_n2,  requires_grad=True, device = 'cuda') # 将numpy数据转化为tensor
            f1 = -16 * torch.linalg.norm(dom_koch_t1, dim = 1, keepdim=True).data**2 # 定义体力 
            f2 = -16 * torch.linalg.norm(dom_koch_t2, dim = 1, keepdim=True).data**2 # 定义体力
            Xi = interface(1000)
        def closure():   # 先优化外面的J2
    
            # 构造可能位移场
            u_pred1 = pred(dom_koch_t1)
            u_pred2 = pred(dom_koch_t2)
            
            du1dxy = grad(u_pred1, dom_koch_t1, torch.ones(dom_koch_t1.size()[0], 1).cuda(), create_graph=True)[0]
            du1dx = du1dxy[:, 0].unsqueeze(1)
            du1dy = du1dxy[:, 1].unsqueeze(1)
    
            du2dxy = grad(u_pred2, dom_koch_t2, torch.ones(dom_koch_t2.size()[0], 1).cuda(), create_graph=True)[0]
            du2dx = du2dxy[:, 0].unsqueeze(1)
            du2dy = du2dxy[:, 1].unsqueeze(1)
    
            J1 = ((0.5 * a1 * torch.sum(du1dx**2 + du1dy**2)) - torch.sum(f1*u_pred1)) * (r0**2*np.pi)/len(dom_koch_t1) 
            
            J2 = ((0.5 * a2 * torch.sum(du2dx**2 + du2dy**2)) - torch.sum(f2*u_pred2)) * (10*np.sqrt(3)/3-r0**2*np.pi)/len(dom_koch_t2) 
    
            J = J1 + J2
            # 添加交界面的损失函数
            u_i1 = model_h1(Xi)  # 内部网络的交界面预测
            u_i2 = model_p(Xi)  + RBF(Xi)*model_h2(Xi)  # 外部网络的交界面预测
            Ji = criterion(u_i1, u_i2)
            
            loss = J + penalty * Ji
            error_t = evaluate()
            optim_h.zero_grad()
            loss.backward()
            loss2_array.append(J2.data.cpu())
            loss_array.append(loss.data.cpu())
            error_array.append(error_t.data.cpu())
    
            if epoch%10==0:
                print(' epoch : %i, the loss : %f , loss1 : %f, loss2 : %f, inter : %f, error : %f' % (epoch, loss.data, J1.data, J2.data, Ji.data, error_t.data))
            return loss
        optim_h.step(closure)
        scheduler.step()
        # 网络1损失函数下不去，所以我们用交界面来作为本质边界条件训练网络1
    for epoch in range(nepoch_u1): #固定网络2，优化网络2
        if epoch ==1000:
            end = time.time()
            consume_time = end-start
            print('time is %f' % consume_time)
        if epoch%100 == 0:
            dom_koch_n = koch_points.get_koch_points(10000) # 获得n_test个koch的随机分布点
            dom_koch_n1 = dom_koch_n[(dom_koch_n[:,0]**2+dom_koch_n[:,1]**2)<r0**2]#定义内部的dom点，即是r<r0的点
            dom_koch_n2 = dom_koch_n[(dom_koch_n[:,0]**2+dom_koch_n[:,1]**2)>=r0**2]#定义内部的dom点，即是r<r0的点
            dom_koch_t1= torch.tensor(dom_koch_n1,  requires_grad=True, device = 'cuda') # 将numpy数据转化为tensor
            dom_koch_t2= torch.tensor(dom_koch_n2,  requires_grad=True, device = 'cuda') # 将numpy数据转化为tensor
            f1 = -16 * torch.linalg.norm(dom_koch_t1, dim = 1, keepdim=True).data**2 # 定义体力 
            f2 = -16 * torch.linalg.norm(dom_koch_t2, dim = 1, keepdim=True).data**2 # 定义体力
            Xi = interface(1000)
        def closure():  
    
            # 构造可能位移场
            u_pred1 = pred(dom_koch_t1)
       
            du1dxy = grad(u_pred1, dom_koch_t1, torch.ones(dom_koch_t1.size()[0], 1).cuda(), create_graph=True)[0]
            du1dx = du1dxy[:, 0].unsqueeze(1)
            du1dy = du1dxy[:, 1].unsqueeze(1)
    
    
            J1 = ((0.5 * a1 * torch.sum(du1dx**2 + du1dy**2)) - torch.sum(f1*u_pred1)) * (r0**2*np.pi)/len(dom_koch_t1) 
            
            J = J1 
            # 添加交界面的损失函数
            u_i1 = model_h1(Xi)  # 内部网络的交界面预测
            u_i2 = model_p(Xi)  + RBF(Xi)*model_h2(Xi)  # 外部网络的交界面预测
            Ji = criterion(u_i1, u_i2)
            
            loss = J + penalty * Ji
            error_t = evaluate()
            optim_h1.zero_grad()
            loss.backward()
            loss1_array.append(J1.data.cpu())
            loss_array.append((loss+loss2_array[-1]).data.cpu())
            error_array.append(error_t.data.cpu())
    
            if epoch%10==0:
                print(' epoch : %i, the loss : %f , loss1 : %f, inter : %f, error : %f' % (epoch, loss.data, J1.data, Ji.data, error_t.data))
            return loss
        optim_h1.step(closure)
        scheduler1.step()