Pular para conteúdo

Controladores Personalizados e Redes

Neste tutorial você abre dois dos samples dinâmicos distribuídos com o DWSIM na GUI Clássica: o tanque de água cujo nível é mantido por um controlador escrito em Python que substitui o PID, e uma rede de abastecimento de água de distrito cujo nível de tanque é mantido pela pressão de ajuste de uma válvula redutora de pressão. O primeiro mostra o que o bloco Python Controller oferece quando um PID não é a lei certa; o segundo mostra uma malha de controle cuja variável manipulada mora dentro de uma rede de dutos.

O que você vai aprender

  • O que o bloco Python Controller recebe a cada passo e o que precisa devolver
  • Como um controlador baseado em modelo usa a equação da válvula e o balanço do tanque diretamente
  • Como um PID pode manipular uma variável dentro de uma unidade Pipe Network, e o que bias e span significam quando essa variável é uma pressão

Pré-requisitos

  • Ter completado Controle de Nível PID: o tanque, a equação da válvula e o vocabulário de malha são reaproveitados
  • Python básico: atribuições, if, aritmética

Visão Geral do Processo

Dois flowsheets da lista Samples:

  1. Dynamic Simulation - Water Tank Level with Custom Controller: o tanque dos tutoriais anteriores (entrada 10 kg/s a 1,3 bar, V-01 com Kv fixo 100, T-01 de 2 m³, V-02 com Kv 400), com um Python Controller PC-1 que substitui o PID, setpoint 1,7 m, e um conjunto de eventos que muda a entrada para 15, 7,5, 30 e de volta a 10 kg/s em 2, 7, 10 e 15 min.
  2. Pipe Network - District Supply with Tank Level Control (Dynamic): um header a 8 bar, uma adutora de 2 km, uma válvula redutora de pressão ajustada em 3,41 bar, um ramal de 400 m e uma entrega a 1,2 bar, tudo dentro de uma unidade Pipe Network; a jusante, um tanque de 24 m³ e uma válvula de controle de vazão para o distrito. Um PID LIC-01 mantém o nível do tanque em 3 m movendo a pressão de ajuste da PRV.

Diagrama de Fluxo do Processo

graph LR
    IN["inlet<br/>10 kg/s (degraus)"] --> V1["V-01"]
    V1 --> T["T-01<br/>2 m³"]
    T --> V2["V-02<br/>Kv 400"]
    V2 --> OUT["outlet"]
    T -. nível .-> PC["PC-1<br/>(Python)<br/>SP 1,7 m"]
    PC -. abertura .-> V2
graph LR
    H["header<br/>8 bar"] --> NET["WATERNET<br/>adutora 2 km → PRV-01 → ramal 400 m"]
    NET --> D["delivered<br/>1,2 bar"]
    D --> TK["TK-01<br/>24 m³, 6 m"]
    TK --> FCV["FCV-01<br/>Kv 170"]
    FCV --> DIS["district"]
    TK -. nível .-> LIC["LIC-01<br/>SP 3 m"]
    LIC -. ajuste da PRV .-> NET

Parâmetros de Projeto

Parâmetro Tanque com controlador Python Rede de distrito
Pacote termodinâmico Steam Tables Steam Tables
Alimentação 10 kg/s, 1,3 bar, spec de Vazão 34,7 kg/s a 8 bar (header, spec de Pressão dentro da rede)
Holdup T-01: 2 m³, 2 m, nível 1,7 m TK-01: 24 m³, 6 m, nível 3,0 m
Variável manipulada abertura da V-02 (%) pressão de ajuste da PRV-01 (Pa)
Setpoint 1,7 m 3,0 m
Controlador script Python, abaixo PID Kp 3, Ki 0,004, ação direta, bias 341.435 Pa, span 200.000 Pa, limites de 1,6 a 6,5 bar
Integrador passo 1 s, 30 min passo 5 s, 60 min
Eventos entrada 15 kg/s em 2 min, 7,5 em 7, 30 em 10, 10 em 15 setpoint da LIC-01 3,6 m em 30 min

Passo a Passo na GUI Clássica

1. Abrir o sample do controlador personalizado

File > Samples (ou a lista Samples na tela inicial), Dynamic Simulation - Water Tank Level with Custom Controller. Ligue o Modo Dinâmico se estiver desligado.

2. Ler o script

Dê dois cliques em PC-1 e abra o script. A cada passo de integração o DWSIM o executa com três nomes já definidos: Flowsheet (o objeto do flowsheet), Me (o controlador) e PV (o valor atual da variável controlada). O script precisa deixar dois nomes definidos ao terminar: MV, o valor escrito na variável manipulada, e SP, o setpoint com que trabalhou.

Este é um controlador baseado em modelo. Ele lê o nível e o volume do tanque, as pressões dos dois lados da V-02 e a vazão de entrada atual, e calcula a abertura em três partes:

  • uma abertura base abt0 = 23,8 %, a abertura que passa 10 kg/s no nível de projeto;
  • uma correção antecipatória pela mudança de vazão, direto da equação da válvula: a abertura extra necessária para passar wnew − w0 sob a queda de pressão atual;
  • uma correção realimentada pelo erro de nível, dimensionada para o nível voltar a uma taxa que cresce com o quadrado do erro.

A soma é limitada entre 0 e 100 % e devolvida como MV. Sem ganhos para sintonizar: a equação da válvula e a área do tanque são o modelo.

O script do controlador Python

3. Rodar o schedule

Dynamics > Integrator Controls, Sch1, Run. Trinta minutos a 1 s levam um ou dois minutos. O conjunto de eventos Perturbation muda a entrada quatro vezes.

4. Ler os resultados

O nível fica em 1,71 m a corrida inteira, a menos de 0,04 m do setpoint mesmo quando a entrada triplica para 30 kg/s. A V-02 responde a cada degrau de imediato: 31,7 % no início, 29,9 % depois que a malha acomoda, 44,8 % a partir de 2 min (15 kg/s), 22,4 % a partir de 7 min (7,5 kg/s), 89,6 % a partir de 10 min (30 kg/s) e de volta a 29,9 % depois de 15 min. O termo antecipatório faz a maior parte do trabalho: a abertura salta com a vazão e o termo realimentado só apara o pequeno erro de nível que sobra.

Nível e abertura com o controlador Python

5. Abrir o sample da rede de distrito

Pipe Network - District Supply with Tank Level Control (Dynamic). Este sample precisa da unidade Pipe Network, que vem na edição Patreon, e os trechos de água e a válvula redutora dele pedem o Patreon nível 3 para o regime permanente e para a corrida dinâmica; abaixo desse nível o erro diz os blocos, o nível pedido e o nível atual.

6. Ler a malha

Dê dois cliques em LIC-01. A variável controlada é o Liquid Level de TK-01; a variável manipulada é PRV-01: Setting Pressure dentro de WATERNET, em pascals. O controlador é de ação direta: um nível que sobe baixa o ajuste da PRV, menos água chega ao tanque, o nível recua. O bias é 341.435 Pa (o ajuste no ponto de projeto) e o span é 200.000 Pa: uma unidade de saída do controlador move o ajuste em 2 bar. Sem span o controlador calcularia a saída em metros e prenderia a válvula num limite no primeiro passo; este é o caso para o qual o span foi feito.

7. Rodar o schedule (Patreon)

Integrator Controls, Sch1, Run: uma hora a 5 s. Em 30 min o conjunto de eventos muda o setpoint para 3,6 m; o ajuste da PRV sobe, o ramal passa mais, e o nível sobe até o novo setpoint ao longo dos minutos seguintes enquanto a FCV-01 continua entregando ao distrito.

Resultados e Validação

Variável Esperado Unidade
Nível do tanque com o controlador Python, corrida inteira 1,67 a 1,75 m
Abertura da V-02 a 15, 7,5, 30 e 10 kg/s 44,8, 22,4, 89,6, 29,9 %
Nível do tanque de distrito antes do degrau de setpoint 3,0 m
Ajuste da PRV no ponto de projeto 3,41 bar

Resultados esperados

O controlador Python mantém o nível dentro de 4 cm durante degraus de alimentação de −25 % a +200 % porque conhece a equação da válvula; um PID com a sintonia do tutorial anterior mostraria um pico de vários centímetros a cada degrau. A malha da rede mantém um nível com uma pressão: uma variável manipulada em pascals precisa de bias e span em pascals.

Entendendo os Resultados

Um PID não sabe nada sobre o processo; essa é a sua força e o seu limite. O controlador Python aqui sabe duas coisas, a equação da válvula e a seção transversal do tanque, e as usa para calcular a abertura que equilibra as vazões antes de o nível se mover. Isso é antecipação (feedforward), e é por isso que o nível mal se mexe quando a alimentação triplica. O termo realimentado continua lá para o que o modelo não sabe: a densidade, o Kv exato, a pressão de saída derivando. Todo controlador baseado em modelo tem esse formato, uma previsão mais uma correção, e o bloco Python é o lugar de escrever um quando os blocos PID e MPC embutidos não servem.

A rede de distrito mostra a outra metade do vocabulário de malha. A variável manipulada é um ajuste de pressão no fundo de uma rede de dutos; o ganho de processo dessa pressão até o nível do tanque passa pela hidráulica do ramal, e o tamanho dele é o que o span codifica. Ler uma malha começa pelas unidades das suas duas pontas.

Regras do script

O script roda uma vez por passo, então mantenha-o curto: sem laços que esperam, sem acesso a arquivo. Use Flowsheet.GetObject("tag") para alcançar qualquer objeto, GetDynamicProperty("...") para nível e pressão, GetMassFlow() e GetPressure() nas correntes. Defina MV e SP antes da última linha; deixar qualquer um indefinido para a corrida com um erro que nomeia o controlador. Me.ResetRequested é verdadeiro no primeiro passo de uma corrida, que é onde o script limpa o histórico.

Automatizando Este Tutorial

Arquivos neste repositório

  • Script Python: examples/dynamics/06_run_samples.py
  • No DWSIM: lista Samples na tela inicial, Dynamic Simulation - Water Tank Level with Custom Controller e Pipe Network - District Supply with Tank Level Control (Dynamic)
import os
import sys

import pythonnet
pythonnet.load("netfx")              # DWSIM is a .NET Framework application
import clr  # noqa: E402

DWSIM_BIN = os.environ.get("DWSIM_BIN")
if not DWSIM_BIN:
    raise SystemExit("Set DWSIM_BIN to the DWSIM installation folder before running.")
for sub in ("", "unitops", "ppacks", "extenders"):
    sys.path.append(os.path.join(DWSIM_BIN, sub))
clr.AddReference("DWSIM.Automation")
clr.AddReference("DWSIM.Automation.FluentAPI")
clr.AddReference("DWSIM.UnitOperations")

from DWSIM.Automation.FluentAPI import Flowsheet

# the samples ship in the "samples" folder of the DWSIM installation; DWSIM_SAMPLES overrides it
samples = os.environ.get("DWSIM_SAMPLES", os.path.join(DWSIM_BIN, "samples"))

# the custom controller sample, run as it ships
fs = Flowsheet.Load(os.path.join(samples, "Dynamic Simulation - Water Tank Level with Custom Controller.dwxmz"))
fs.Solve()
result = fs.RunDynamics("Sch1").FromCurrentState(True).Execute()
level = result.GetSeries("Level")
opening = result.GetSeries("V2")
print(f"level: min {level.Min:.3f} m, max {level.Max:.3f} m")
for t in (60.0, 300.0, 540.0, 720.0, 1200.0):
    print(f"t = {t:5.0f} s  V-02 = {opening.ValueAt(t):5.1f} %")

# the district network (Patreon): the same call; the run reports the licence
# level it needs in result.Errors when the key does not cover it. The sample ships
# with the Patreon edition only, so the open edition skips this part.
network = os.path.join(samples, "Pipe Network - District Supply with Tank Level Control (Dynamic).dwxmz")
if os.path.isfile(network):
    net = Flowsheet.Load(network)
    r = net.RunDynamics("Sch1").FromCurrentState(True).Execute()
    print(r.Completed, [str(e)[:80] for e in r.Errors])
    if r.Completed:
        print(r.GetSeries("TK-01 Liquid Level").Final)
else:
    print("district network sample not found (Patreon edition only), skipped")

Abra o sample com dwsim.flowsheet.open, rode o schedule com as ferramentas dwsim.dynamics.* e leia as variáveis monitoradas do resultado.

A saída pode variar

Os resultados dependem da qualidade de raciocínio do LLM e da precisão no uso das ferramentas. Sempre verifique se a simulação corresponde à sua intenção antes de confiar nos números.

Abra o sample do DWSIM "Dynamic Simulation - Water Tank Level with Custom
Controller" via servidor MCP, rode o schedule "Sch1" (30 min), e informe o nível
mínimo e máximo do tanque e a abertura da V-02 em 1, 5, 9, 12 e 20 minutos. Depois
explique, pelo script Python do controlador PC-1, qual termo da abertura muda quando
a vazão de entrada muda e qual termo muda quando o nível se afasta de 1,7 m.

Exercícios

  1. Substitua PC-1 por um PID (Kp 2, Ki 0,1, offset 30 %, span 100) e rode o mesmo conjunto de eventos. Compare os picos de nível a cada degrau.
  2. No script, zere a correção antecipatória (deltaabtF = 0.0) e rode de novo. Quanto o nível se move no degrau de 30 kg/s?
  3. Escreva um controlador que abre a V-02 por completo sempre que o nível passa de 1,8 m e fora disso mantém abt0. É estável? O que a válvula faz?

Leitura Complementar

Referências selecionadas da bibliografia técnica do DWSIM.

  • D. E. Seborg, T. F. Edgar, D. A. Mellichamp & F. J. Doyle. (2016). Process Dynamics and Control. Wiley
  • T. E. Marlin. (2000). Process Control: Designing Processes and Control Systems for Dynamic Performance. McGraw-Hill

Próximos Passos

Isto fecha a trilha de Dinâmica. As páginas de Treinamento de Operadores levam estes modelos de planta a um simulador conduzido por instrutor com falhas, cenários e pontuação.