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:
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 ControllerPC-1que 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.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 PIDLIC-01manté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 − w0sob 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.

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.

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 ControllerePipe 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
- Substitua
PC-1por 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. - 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? - 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.