Código fonte para idecomp.decomp.dadger

from idecomp.decomp.modelos.dadger import LeituraDadger
from idecomp.decomp.modelos.dadger import TE, SB, UH, CT, UE, DP, CD, PQ  # noqa
from idecomp.decomp.modelos.dadger import RI, IA, TX, GP, NI, DT, MP, MT  # noqa
from idecomp.decomp.modelos.dadger import FD, VE, RE, LU, FU, FT, FI, VI  # noqa
from idecomp.decomp.modelos.dadger import AC, IR, CI, CE, FC, TI, RQ, EZ  # noqa
from idecomp.decomp.modelos.dadger import HV, LV, CV, HQ, LQ, CQ, AR, EV  # noqa
from idecomp.decomp.modelos.dadger import FJ, HE, CM, RT, FP  # noqa
from idecomp._utils.arquivo import ArquivoRegistros
from idecomp._utils.dadosarquivo import DadosArquivoRegistros
from idecomp._utils.escritaregistros import EscritaRegistros

from copy import deepcopy
from typing import Type, List, Optional, TypeVar, Any


[documentos]class Dadger(ArquivoRegistros): """ Armazena os dados de entrada gerais do DECOMP. Esta classe lida com as informações de entrada fornecidas ao DECOMP no `dadger.rvx`. Possui métodos para acessar individualmente cada registro, editá-lo e também cria alguns novos registros. Atualmente, são suportados os registros: `TE`, `SB`, `UH`, `CT`, `DP`, `TX`, `GP`, `NI`, `DT`, `RE`, `LU`, `VI`, `IR`, `FC`, `TI`, `HV`, `LV`, `HQ`, `LQ` `HE`, `EV` e `FJ`. É possível ler as informações existentes em arquivos a partir do método `le_arquivo()` e escreve um novo arquivo a partir do método `escreve_arquivo()`. """ T = TypeVar("T") def __init__(self, dados: DadosArquivoRegistros) -> None: """ Construtor padrão """ super().__init__(dados) # Override
[documentos] @classmethod def le_arquivo(cls, diretorio: str, nome_arquivo="dadger.rv0") -> 'Dadger': """ Realiza a leitura de um arquivo "dadger.rvx" existente em um diretório. :param diretorio: O caminho relativo ou completo para o diretório onde se encontra o arquivo :type diretorio: str :param nome_arquivo: Nome do arquivo a ser lido, potencialmente especificando a revisão. Tem como valor default "dadger.rv0" :type nome_arquivo: str, optional :return: Um objeto :class:`Dadger` com informações do arquivo lido """ leitor = LeituraDadger(diretorio) r = leitor.le_arquivo(nome_arquivo) return cls(r)
[documentos] def escreve_arquivo(self, diretorio: str, nome_arquivo="dadger.rv0"): """ Realiza a escrita de um arquivo com as informações do objeto :class:`Dadger` :param diretorio: O caminho relativo ou completo para o diretório onde será escrito o arquivo. :type diretorio: str :param nome_arquivo: Nome do arquivo a ser escrito.Tem como valor default "dadger.rv0" :type nome_arquivo: str, optional """ escritor = EscritaRegistros(diretorio) escritor.escreve_arquivo(self._dados, nome_arquivo)
def __obtem_registro(self, tipo: Type[T]) -> T: """ """ for b in self._registros: if isinstance(b, tipo): return b raise ValueError(f"Não foi encontrado um registro do tipo {tipo}") def __obtem_registro_do_estagio(self, tipo: Type[T], codigo: int, estagio: int) -> Optional[T]: regs: List[Any] = self.__obtem_registros(tipo) for r in regs: if all([r.codigo == codigo, r.estagio == estagio]): return r return None def __obtem_registros(self, tipo: Type[T]) -> List[T]: registros = [] for b in self._registros: if isinstance(b, tipo): registros.append(b) return registros @property def te(self) -> TE: """ Obtém o (único) registro que define o nome do estudo no :class:`Dadger` :return: Um registro do tipo :class:`TE`. """ r = self.__obtem_registro(TE) return r
[documentos] def sb(self, codigo: int) -> SB: """ Obtém um registro que define os subsistemas existentes no estudo descrito pelo :class:`Dadger`. :param codigo: Índice do código que especifica o registro do subsistema :type codigo: int :return: Um registro do tipo :class:`SB` """ regs: List[SB] = self.__obtem_registros(SB) for r in regs: if r.codigo == codigo: return r raise ValueError("Não foi encontrado registro SB" + f" para o código {codigo}")
[documentos] def uh(self, codigo: int) -> UH: """ Obtém um registro que define uma usina hidrelétrica existente no estudo descrito pelo :class:`Dadger`. :param codigo: Índice do código que especifica o registro da UHE :type codigo: int :return: Um registro do tipo :class:`UH` """ regs: List[UH] = self.__obtem_registros(UH) for r in regs: if r.codigo == codigo: return r raise ValueError("Não foi encontrado registro UH" + f" para a UHE {codigo}")
[documentos] def ct(self, codigo: int, estagio: int) -> CT: """ Obtém um registro que define uma usina termelétrica existente no estudo descrito pelo :class:`Dadger`. :param codigo: Índice do código que especifica o registro da UTE :type codigo: int :param estagio: Índice do estágio associado ao registro :type estagio: int :return: Um registro do tipo :class:`CT` """ regs: List[CT] = self.__obtem_registros(CT) for r in regs: if all([r.codigo == codigo, r.estagio == estagio]): return r raise ValueError("Não foi encontrado registro CT" + f" para a UTE {codigo} no estágio" + f" {estagio}.")
[documentos] def dp(self, estagio: int, subsistema: int) -> DP: """ Obtém um registro que define as durações dos patamares no estudo descrito pelo :class:`Dadger`. :param estagio: Índice do estágio sobre o qual serão definidas as durações dos patamares :type estagio: int :param subsistema: Índice do subsistema para o qual valerão os patamares. :type subsistema: int :return: Um registro do tipo :class:`DP` """ regs: List[DP] = self.__obtem_registros(DP) for r in regs: if all([r.estagio == estagio, r.subsistema == subsistema]): return r raise ValueError("Não foi encontrado registro DP" + f" para o subsistema {subsistema}" + f" no estágio {estagio})")
[documentos] def ac(self, uhe: int, modificacao: str, mes: str = None, semana: int = None, ano: int = None ) -> AC: """ Obtém um registro que define modificações nos parâmetros das UHE em um :class:`Dadger`. :param uhe: código da UHE modificada :type uhe: int :param modificacao: mnemônico da modificação realizada :type modificacao: str :return: Um registro do tipo :class:`AC` """ def __atende(r: AC) -> bool: condicoes: List[bool] = [r.uhe == uhe, r.modificacao == modificacao] if mes is not None: condicoes.append(r.mes == mes) if semana is not None: condicoes.append(r.semana == semana) if ano is not None: condicoes.append(r.ano == ano) return all(condicoes) regs: List[AC] = self.__obtem_registros(AC) for r in regs: if __atende(r): return r raise ValueError("Não foi encontrado registro AC" + f" para a UHE {uhe}" + f" que modifique {modificacao})")
[documentos] def cd(self, numero_curva: int, subsistema: int) -> CD: """ Obtém um registro que define as curvas de déficit no estudo descrito pelo :class:`Dadger`. :param numero_curva: Índice da curva de déficit descrita :type numero_curva: int :param subsistema: Índice do subsistema para o qual valerá a curva. :type subsistema: int :return: Um registro do tipo :class:`CD` """ regs: List[CD] = self.__obtem_registros(CD) for r in regs: if all([r.numero_curva == numero_curva, r.subsistema == subsistema]): return r raise ValueError("Não foi encontrado registro CD" + f" para o subsistema {subsistema}" + f" na curva {numero_curva})")
@property def tx(self) -> TX: """ Obtém o (único) registro que define a taxa de desconto aplicada no estudo definido no :class:`Dadger` :return: Um registro do tipo :class:`TX`. """ return self.__obtem_registro(TX) @property def gp(self) -> GP: """ Obtém o (único) registro que define o gap para convergência considerado no estudo definido no :class:`Dadger` :return: Um registro do tipo :class:`GP`. """ return self.__obtem_registro(GP) @property def ni(self) -> NI: """ Obtém o (único) registro que define o número máximo de iterações do DECOMP no estudo definido no :class:`Dadger` :return: Um registro do tipo :class:`NI`. """ return self.__obtem_registro(NI) @property def dt(self) -> DT: """ Obtém o (único) registro que define a data de referência do estudo definido no :class:`Dadger` :return: Um registro do tipo :class:`DT`. """ return self.__obtem_registro(DT)
[documentos] def re(self, codigo: int) -> RE: """ Obtém um registro que cadastra uma restrição elétrica existente no estudo descrito pelo :class:`Dadger`. :param codigo: Índice do código que especifica o registro da restrição elétrica :type codigo: int :return: Um registro do tipo :class:`RE` """ regs: List[RE] = self.__obtem_registros(RE) for r in regs: if r.codigo == codigo: return r raise ValueError("Não foi encontrado registro RE" + f" com código {codigo}")
[documentos] def lu(self, codigo: int, estagio: int) -> LU: """ Obtém um registro que especifica os limites inferiores e superiores por patamar de uma restrição elétrica existente no estudo descrito pelo :class:`Dadger`. :param codigo: Índice do código que especifica o registro da restrição elétrica :type codigo: int :param estagio: Estágio sobre o qual valerão os limites da restrição elétricas :type estagio: int :return: Um registro do tipo :class:`LU` **Exemplos** Para um objeto :class:`Dadger` que possua uma restrição RE de código 1, definida para os estágios de 1 a 5, com limites LU definidos apenas para o estágio 1, estes podem ser acessados com: >>> lu = dadger.lu(1, 1) >>> lu <idecomp.decomp.modelos.dadger.LU object at 0x0000026E5C269550> Se for acessado o registro LU de um estágio fora dos limites da restrição RE, isso resultará em um erro: >>> dadger.lu(1, 7) Traceback (most recent call last): ... ValueError: Estágio 7 fora dos limites do registro RE Por outro lado, se for acessado o registro LU em um estágio dentro dos limites do registro RE, porém sem limites próprios definidos, será criado um registro idêntico ao do último estágio existente, e este será retornado: >>> lu2 = dadger.lu(1, 5) >>> lu.limites_inferiores == lu2.limites_inferiores True """ def cria_registro(modelo: LU, estagio_final: int) -> LU: copia = deepcopy(modelo) copia.estagio = estagio # Procura pelo registro do próximo estágio proximo = None for est in range(estagio, estagio_final + 1): r = self.__obtem_registro_do_estagio(LU, codigo, est) if r is not None: proximo = r break if proximo is not None: delta = (proximo._ordem - modelo._ordem) / 2.0 else: delta = 0.1 copia._ordem += delta self._registros.append(copia) return copia # Obtém o registro RE associado re = self.re(codigo) # Confere se o estágio pedido está no intervalo # do registro RE if not (re.estagio_inicial <= estagio <= re.estagio_final): raise ValueError(f"Estágio {estagio} fora dos limites" + " do registro RE") # Tenta obter um registro já existente reg = self.__obtem_registro_do_estagio(LU, codigo, estagio) if reg is not None: return reg # Se não conseguir, cria mais um registro, idêntico ao do # último estágio existente, e retorna. for est in range(re.estagio_inicial, estagio): r = self.__obtem_registro_do_estagio(LU, codigo, est) if r is not None: reg = r if reg is None: raise ValueError("Registro não encontrado") return cria_registro(reg, re.estagio_final)
[documentos] def vi(self, uhe: int) -> VI: """ Obtém um registro que especifica os tempos de viagem da água em uma UHE existente no no estudo descrito pelo :class:`Dadger`. :param uhe: Índice da UHE associada aos tempos de viagem :type uhe: int :return: Um registro do tipo :class:`VI` """ regs: List[VI] = self.__obtem_registros(VI) for r in regs: if r.uhe == uhe: return r raise ValueError("Não foi encontrado registro VI" + f" para a UHE {uhe}")
[documentos] def ir(self, tipo: str) -> IR: """ Obtém um registro que especifica os relatórios de saída a serem produzidos pelo DECOMP após a execução do estudo descrito no :class:`Dadger`. :param tipo: Mnemônico do tipo de relatório especificado no registro :type tipo: str :return: Um registro do tipo :class:`IR` """ regs: List[IR] = self.__obtem_registros(IR) for r in regs: if r.tipo == tipo: return r raise ValueError("Não foi encontrado registro IR" + f" com mnemônico {tipo}")
[documentos] def rt(self, mnemonico: str) -> RT: """ Obtém um registro que especifica uma retirada de restrição de soleira de vertedouro ou canal de desvio. :param mnemonico: Mnemônico da restrição retirada (CRISTA ou DESVIO) :type mnemonico: str :return: Um registro do tipo :class:`RT` """ regs: List[RT] = self.__obtem_registros(RT) for r in regs: if r.restricao == mnemonico: return r raise ValueError("Não foi encontrado registro RT" + f" com mnemônico {mnemonico}")
[documentos] def fc(self, tipo: str) -> FC: """ Obtém um registro que especifica os caminhos para os arquivos com a FCF do NEWAVE. :param tipo: Mnemônico do tipo de FCF especificado no registro :type tipo: str :return: Um registro do tipo :class:`FC` """ regs: List[FC] = self.__obtem_registros(FC) for r in regs: if r.tipo == tipo: return r raise ValueError("Não foi encontrado registro FC" + f" com mnemônico {tipo}")
[documentos] def ti(self, codigo: int) -> TI: """ Obtém um registro que especifica as taxas de irrigação por posto (UHE) existente no estudo especificado no :class:`Dadger` :param codigo: Código do posto da UHE associada no registro :type codigo: int :return: Um registro do tipo :class:`TI` """ regs: List[TI] = self.__obtem_registros(TI) for r in regs: if r.codigo == codigo: return r raise ValueError("Não foi encontrado registro TI" + f" para a UHE {codigo}")
[documentos] def fp(self, codigo: int, estagio: int) -> FP: """ Obtém um registro que especifica as taxas de irrigação por posto (UHE) existente no estudo especificado no :class:`Dadger` :param codigo: Código do posto da UHE associada no registro :type codigo: int :param estagio: Estágio de definição da FP da UHE :type estagio: int :return: Um registro do tipo :class:`FP` """ r = self.__obtem_registro_do_estagio(FP, codigo, estagio) if r is not None: return r else: raise ValueError("Registro não encontrado registro FP" + f"para a UHE {codigo} no estágio {estagio}")
[documentos] def rq(self, ree: int) -> RQ: """ Obtém um registro que especifica as vazões mínimas históricas por REE existentes no estudo especificado no :class:`Dadger` :param ree: Código do REE :type ree: int :return: Um registro do tipo :class:`RQ` """ regs: List[RQ] = self.__obtem_registros(RQ) for r in regs: if r.ree == ree: return r raise ValueError("Não foi encontrado registro RQ" + f" para o REE {ree}")
[documentos] def ve(self, codigo: int) -> VE: """ Obtém um registro que especifica os volumes de espera por posto (UHE) existente no estudo especificado no :class:`Dadger` :param codigo: Código do posto da UHE associada :type codigo: int :return: Um registro do tipo :class:`VE` """ regs: List[VE] = self.__obtem_registros(VE) for r in regs: if r.codigo == codigo: return r raise ValueError("Não foi encontrado registro VE" + f" para a UHE {codigo}")
[documentos] def hv(self, codigo: int) -> HV: """ Obtém um registro que cadastra uma restrição de volume mínimo armazenado existente no estudo descrito pelo :class:`Dadger`. :param codigo: Índice do código que especifica o registro da restrição de volume mínimo :type codigo: int :return: Um registro do tipo :class:`HV` """ regs: List[HV] = self.__obtem_registros(HV) for r in regs: if r.codigo == codigo: return r raise ValueError("Não foi encontrado registro HV" + f" para UHE {codigo}")
[documentos] def lv(self, codigo: int, estagio: int) -> LV: """ Obtém um registro que especifica os limites inferior e superior de uma restrição de volume mínimo existente no estudo descrito pelo :class:`Dadger`. :param codigo: Índice do código que especifica o registro da restrição de volume mínimo :type codigo: int :param estagio: Estágio sobre o qual valerão os limites da restrição :type estagio: int :return: Um registro do tipo :class:`LV` **Exemplos** Para um objeto :class:`Dadger` que possua uma restrição HV de código 1, definida para os estágios de 1 a 5, com limites LV definidos apenas para o estágio 1, estes podem ser acessados com: >>> lv = dadger.lv(1, 1) >>> lv <idecomp.decomp.modelos.dadger.LV object at 0x0000026E5C269550> Se for acessado o registro LV de um estágio fora dos limites da restrição HV, isso resultará em um erro: >>> dadger.lv(1, 7) Traceback (most recent call last): ... ValueError: Estágio 7 fora dos limites do registro HV Por outro lado, se for acessado o registro LV em um estágio dentro dos limites do registro HV, porém sem limites próprios definidos, será criado um registro idêntico ao do último estágio existente, e este será retornado: >>> lv2 = dadger.lv(1, 5) >>> lv.limite_inferior == lv2.limite_inferior True """ def cria_registro(modelo: LV, estagio_final: int) -> LV: copia = deepcopy(modelo) copia.estagio = estagio # Procura pelo registro do próximo estágio proximo = None for est in range(estagio, estagio_final + 1): r = self.__obtem_registro_do_estagio(LV, codigo, est) if r is not None: proximo = r break if proximo is not None: delta = (proximo._ordem - modelo._ordem) / 2.0 else: delta = 0.1 copia._ordem += delta self._registros.append(copia) return copia # Obtém o registro HV associado hv = self.hv(codigo) # Confere se o estágio pedido está no intervalo # do registro HV if not (hv.estagio_inicial <= estagio <= hv.estagio_final): raise ValueError(f"Estágio {estagio} fora dos limites" + " do registro HV") # Tenta obter um registro já existente reg = self.__obtem_registro_do_estagio(LV, codigo, estagio) if reg is not None: return reg # Se não conseguir, cria mais um registro, idêntico ao do # último estágio existente, e retorna. for est in range(hv.estagio_inicial, estagio): r = self.__obtem_registro_do_estagio(LV, codigo, est) if r is not None: reg = r if reg is None: raise ValueError("Registro não encontrado") return cria_registro(reg, hv.estagio_final)
[documentos] def hq(self, codigo: int) -> HQ: """ Obtém um registro que cadastra uma restrição de vazão existente no estudo descrito pelo :class:`Dadger`. :param codigo: Índice do código que especifica o registro da restrição de vazão :type codigo: int :return: Um registro do tipo :class:`HQ` """ regs: List[HQ] = self.__obtem_registros(HQ) for r in regs: if r.codigo == codigo: return r raise ValueError("Não foi encontrado registro HQ" + f" com o código {codigo}")
[documentos] def lq(self, codigo: int, estagio: int) -> LQ: """ Obtém um registro que especifica os limites inferiores e superiores por patamar de uma restrição de vazão existente no estudo descrito pelo :class:`Dadger`. :param codigo: Índice do código que especifica o registro da restrição de vazão :type codigo: int :param estagio: Estágio sobre o qual valerão os limites da restrição de vazão :type estagio: int :return: Um registro do tipo :class:`LQ` **Exemplos** Para um objeto :class:`Dadger` que possua uma restrição HQ de código 1, definida para os estágios de 1 a 5, com limites LQ definidos apenas para o estágio 1, estes podem ser acessados com: >>> lq = dadger.lq(1, 1) >>> lq <idecomp.decomp.modelos.dadger.LQ object at 0x0000026E5C269550> Se for acessado o registro LQ de um estágio fora dos limites da restrição HQ, isso resultará em um erro: >>> dadger.lq(1, 7) Traceback (most recent call last): ... ValueError: Estágio 7 fora dos limites do registro HQ Por outro lado, se for acessado o registro LQ em um estágio dentro dos limites do registro HQ, porém sem limites próprios definidos, será criado um registro idêntico ao do último estágio existente, e este será retornado: >>> lq2 = dadger.lq(1, 5) >>> lq.limites_inferiores == lq2.limites_inferiores True """ def cria_registro(modelo: LQ, estagio_final: int) -> LQ: copia = deepcopy(modelo) copia.estagio = estagio # Procura pelo registro do próximo estágio proximo = None for est in range(estagio, estagio_final + 1): r = self.__obtem_registro_do_estagio(LQ, codigo, est) if r is not None: proximo = r break if proximo is not None: delta = (proximo._ordem - modelo._ordem) / 2.0 else: delta = 0.1 copia._ordem += delta self._registros.append(copia) return copia # Obtém o registro HQ associado hq = self.hq(codigo) # Confere se o estágio pedido está no intervalo # do registro HQ if not (hq.estagio_inicial <= estagio <= hq.estagio_final): raise ValueError(f"Estágio {estagio} fora dos limites" + " do registro HQ") # Tenta obter um registro já existente reg = self.__obtem_registro_do_estagio(LQ, codigo, estagio) if reg is not None: return reg # Se não conseguir, cria mais um registro, idêntico ao do # último estágio existente, e retorna. for est in range(hq.estagio_inicial, estagio): r = self.__obtem_registro_do_estagio(LQ, codigo, est) if r is not None: reg = r if reg is None: raise ValueError("Registro não encontrado") return cria_registro(reg, hq.estagio_final)
[documentos] def he(self, codigo: int, estagio: int) -> HE: """ Obtém um registro que cadastra uma restrição de energia armazenada existente no estudo descrito pelo :class:`Dadger`. :param codigo: Índice do código que especifica o registro da restrição de energia armazenada :type codigo: int :param estagio: Índice do estágio para o qual vale a restrição de energia armazenada :type estagio: int :return: Um registro do tipo :class:`HE` """ r = self.__obtem_registro_do_estagio(HE, codigo, estagio) if r is not None: return r else: raise ValueError("Registro não encontrado")
@property def ev(self) -> EV: """ Obtém o (único) registro que define a evaporação :class:`Dadger` :return: Um registro do tipo :class:`EV`. """ r = self.__obtem_registro(EV) return r @property def fj(self) -> FJ: """ Obtém o (único) registro que define o arquivo `polinjus` :class:`Dadger` :return: Um registro do tipo :class:`FJ`. """ r = self.__obtem_registro(FJ) return r