Exemple #1
0
    def run(self):
        ret = False
        system = self.system

        if system.pflow.solved is False:
            logger.warning(
                'Power flow not solved. Eig analysis will not continue.')
            return ret
        elif system.dae.n == 0:
            logger.warning('No dynamic model. Eig analysis will not continue.')
            return ret

        t1, s = elapsed()
        logger.info('-> Eigenvalue Analysis:')

        system.dae.factorize = True
        exec(system.call.int)

        self.calc_state_matrix()
        self.calc_part_factor()

        self.dump_results()
        self.plot_results()
        ret = True

        t2, s = elapsed(t1)
        logger.info('Eigenvalue analysis finished in {:s}.'.format(s))

        return ret
Exemple #2
0
    def pre(self):
        """
        Initialize system for power flow study

        Returns
        -------
        None
        """
        logger.info('-> Power flow study: {} method, {} start'.format(
            self.config.method.upper(),
            'flat' if self.config.flatstart else 'non-flat'))

        t, s = elapsed()

        system = self.system
        dae = self.system.dae

        system.dae.init_xy()

        for device, pflow, init0 in zip(system.devman.devices,
                                        system.call.pflow, system.call.init0):
            if pflow and init0:
                system.__dict__[device].init0(dae)

        # check for islands
        system.check_islands(show_info=True)

        t, s = elapsed(t)
        logger.debug('Power flow initialized in {:s}.'.format(s))
Exemple #3
0
    def run(self, **kwargs):
        """
        call the power flow solution routine

        Returns
        -------
        bool
            True for success, False for fail
        """
        ret = None

        # initialization Y matrix and inital guess
        if not self.pre():
            return False

        t, _ = elapsed()

        # call solution methods
        if self.config.method == 'NR':
            ret = self.newton()
        elif self.config.method == 'DCPF':
            ret = self.dcpf()
        elif self.config.method in ('FDPF', 'FDBX', 'FDXB'):
            ret = self.fdpf()

        self.post()
        _, s = elapsed(t)

        if self.solved:
            logger.info(' Solution converged in {} in {} iterations'.format(
                s, self.niter))
        else:
            logger.warning(' Solution failed in {} in {} iterations'.format(
                s, self.niter))
        return ret
Exemple #4
0
    def init(self):
        """
        Initialize time domain simulation

        Returns
        -------
        None
        """
        system = self.system

        if self.t != self.config.t0:
            logger.warning(
                'TDS has been previously run and cannot be re-initialized. Please reload the system.'
            )
            return False

        if system.pflow.solved is False:
            logger.info('Attempting to solve power flow before TDS.')
            if not system.pflow.run():
                return False

        t, s = elapsed()

        # Assign indices for post-powerflow device variables
        system.xy_addr1()

        # Assign variable names for bus injections and line flows if enabled
        system.varname.resize_for_flows()
        system.varname.bus_line_names()

        # Reshape dae to retain power flow solutions
        system.dae.init1()

        # Initialize post-powerflow device variables
        for device, init1 in zip(system.devman.devices, system.call.init1):
            if init1:
                system.__dict__[device].init1(system.dae)

        t, s = elapsed(t)

        if system.dae.n:
            logger.debug('Dynamic models initialized in {:s}.'.format(s))
        else:
            logger.debug('No dynamic model loaded.')

        # system.dae flags initialize
        system.dae.factorize = True
        system.dae.mu = 1.0
        system.dae.kg = 0.0

        self.initialized = True

        return True
Exemple #5
0
    def dump_results(self):
        """
        Dump simulation results to ``dat`` and ``lst`` files

        Returns
        -------
        None
        """
        system = self.system

        t, _ = elapsed()

        if self.success and (not system.files.no_output):
            system.varout.dump()
            _, s = elapsed(t)
            logger.info('Simulation data dumped in {:s}.'.format(s))
Exemple #6
0
    def init(self):
        """
        Initialize time domain simulation

        Returns
        -------
        None
        """
        system = self.system
        config = self.config
        dae = self.system.dae
        if system.pflow.solved is False:
            return

        t, s = elapsed()

        # Assign indices for post-powerflow device variables
        system.xy_addr1()

        # Assign variable names for bus injections and line flows if enabled
        system.varname.resize_for_flows()
        system.varname.bus_line_names()

        # Reshape dae to retain power flow solutions
        system.dae.init1()

        # Initialize post-powerflow device variables
        for device, init1 in zip(system.devman.devices, system.call.init1):
            if init1:
                system.__dict__[device].init1(system.dae)

        # compute line and area flow
        if config.compute_flows:
            dae.init_fg()
            self.compute_flows()  # TODO: move to PowerSystem

        t, s = elapsed(t)

        if system.dae.n:
            logger.debug('Dynamic models initialized in {:s}.'.format(s))
        else:
            logger.debug('No dynamic model loaded.')

        # system.dae flags initialize
        system.dae.factorize = True
        system.dae.mu = 1.0
        system.dae.kg = 0.0
Exemple #7
0
    def pre(self):
        """
        Initialize system for power flow study

        Returns
        -------
        None
        """

        if self.solved and self.system.tds.initialized:
            logger.error(
                'TDS has been initialized. Cannot solve power flow again.')
            return False

        logger.info('-> Power flow study: {} method, {} start'.format(
            self.config.method.upper(),
            'flat' if self.config.flatstart else 'non-flat'))

        t, s = elapsed()

        system = self.system
        dae = self.system.dae

        system.dae.init_xy()

        for device, pflow, init0 in zip(system.devman.devices,
                                        system.call.pflow, system.call.init0):
            if pflow and init0:
                system.__dict__[device].init0(dae)

        # check for islands
        system.check_islands(show_info=True)

        # reset internal storage
        self.reset()

        t, s = elapsed(t)
        logger.debug('Power flow initialized in {:s}.'.format(s))

        return True
Exemple #8
0
    def run(self, **kwargs):
        """
        Run time domain simulation

        Returns
        -------
        bool
            Success flag
        """

        # check if initialized
        if not self.initialized:
            if self.init() is False:
                logger.info(
                    'Call to TDS initialization failed in `tds.run()`.')

        ret = False
        system = self.system
        config = self.config
        dae = self.system.dae

        # maxit = config.maxit
        # tol = config.tol

        if system.pflow.solved is False:
            logger.warning(
                'Power flow not solved. Simulation cannot continue.')
            return ret
        t0, _ = elapsed()
        t1 = t0

        self.streaming_init()

        logger.info('')
        logger.info('-> Time Domain Simulation: {} method, t={} s'.format(
            self.config.method, self.config.tf))

        self.load_pert()

        self.run_step0()

        config.qrtstart = time()

        while self.t < config.tf:
            self.check_fixed_times()
            self.calc_time_step()

            if self.callpert is not None:
                self.callpert(self.t, self.system)

            if self.h == 0:
                break
            # progress time and set time in dae
            self.t += self.h
            dae.t = self.t

            # backup actual variables
            self.x0 = matrix(dae.x)
            self.y0 = matrix(dae.y)
            self.f0 = matrix(dae.f)

            # apply fixed_time interventions and perturbations
            self.event_actions()

            # reset flags used in each step
            self.err = 1
            self.niter = 0
            self.convergence = False

            self.implicit_step()

            if self.convergence is False:
                try:
                    self.restore_values()
                    continue
                except ValueError:
                    self.t = config.tf
                    ret = False
                    break

            self.step += 1
            self.compute_flows()
            system.varout.store(self.t, self.step)
            self.streaming_step()

            # plot variables and display iteration status
            perc = max(
                min((self.t - config.t0) / (config.tf - config.t0) * 100, 100),
                0)

            # show iteration info every 30 seconds or every 20%

            t2, _ = elapsed(t1)
            if t2 - t1 >= 30:
                t1 = t2
                logger.info(
                    ' ({:.0f}%) time = {:.4f}s, step = {}, niter = {}'.format(
                        100 * self.t / config.tf, self.t, self.step,
                        self.niter))

            if perc > self.next_pc or self.t == config.tf:
                self.next_pc += 20
                logger.info(
                    ' ({:.0f}%) time = {:.4f}s, step = {}, niter = {}'.format(
                        100 * self.t / config.tf, self.t, self.step,
                        self.niter))

            # compute max rotor angle difference
            # diff_max = anglediff()

            # quasi-real-time check and wait
            rt_end = config.qrtstart + (self.t - config.t0) * config.kqrt

            if config.qrt:
                # the ending time has passed
                if time() - rt_end > 0:
                    # simulation is too slow
                    if time() - rt_end > config.kqrt:
                        logger.debug(
                            'Simulation over-run at t={:4.4g} s.'.format(
                                self.t))
                # wait to finish
                else:
                    self.headroom += (rt_end - time())
                    while time() - rt_end < 0:
                        sleep(1e-5)

        if config.qrt:
            logger.debug('RT headroom time: {} s.'.format(str(self.headroom)))

        if self.t != config.tf:
            logger.error(
                'Reached minimum time step. Convergence is not likely.')
            ret = False
        else:
            ret = True

        if system.config.dime_enable:
            system.streaming.finalize()

        _, s = elapsed(t0)

        if ret is True:
            logger.info(' Time domain simulation finished in {:s}.'.format(s))
        else:
            logger.info(' Time domain simulation failed in {:s}.'.format(s))

        self.success = ret
        self.dump_results(success=self.success)

        return ret
Exemple #9
0
def main(args=None):
    """
    The main function of the Andes command-line tool.

    This function executes the following workflow:

     * Parse the command line inputs
     * Show the tool preamble
     * Output the requested helps, edit/save configs or remove outputs. Exit
       the main program if any of the above is executed
     * Process the input files and call ``main.run()`` using single- or
       multi-processing
     * Show the execution time and exit

    Returns
    -------
    None
    """
    t0, _ = elapsed()

    # parser command line arguments
    if args is None:
        parser = cli_parser()
        args = vars(cli_new(parser))
    elif not isinstance(args, dict):
        args = vars(args)

    # configure stream handler verbose level
    config_logger(log_path=misc.get_log_dir(),
                  file=True,
                  stream=True,
                  stream_level=args.get('verbose', logging.INFO))

    # show preamble
    preamble()

    # ----- Debug only -----
    # logger.debug('command line arguments:')
    # logger.debug(pprint.pformat(args))
    # ----------------------

    if andeshelp(**args) or search(**args) or edit_conf(
            **args) or remove_output(**args) or save_config(**args):
        return

    # process input files
    filename = args.get('filename', ())
    if isinstance(filename, str):
        filename = [filename]

    if len(filename) == 0:
        logger.info('error: no input file. Try \'andes -h\' for help.')

    # preprocess cli args
    path = args.get('input_path', os.getcwd())
    ncpu = args.get('ncpu', 0)
    if ncpu == 0 or ncpu > os.cpu_count():
        ncpu = os.cpu_count()

    cases = []

    for file in filename:
        # use absolute path for cases which will be respected by FileMan
        full_paths = os.path.abspath(os.path.join(path, file))
        found = glob.glob(full_paths)
        if len(found) == 0:
            logger.info('error: file {} does not exist.'.format(full_paths))
        else:
            cases += found

    # remove folders and make cases unique
    cases = list(set(cases))
    valid_cases = []
    for case in cases:
        if os.path.isfile(case):
            valid_cases.append(case)
Exemple #10
0
            job.start()

            start_msg = 'Process {:d} <{:s}> started.'.format(idx, file)
            print(start_msg)
            logger.debug(start_msg)

            if (idx % ncpu == ncpu - 1) or (idx == len(valid_cases) - 1):
                sleep(0.1)
                for job in jobs:
                    job.join()
                jobs = []

        # restore command line output when all jobs are done
        logger.handlers[1].setLevel(logging.INFO)

    t0, s0 = elapsed(t0)

    if len(valid_cases) == 1:
        logger.info('-> Single process finished in {:s}.'.format(s0))
    elif len(valid_cases) >= 2:
        logger.info('-> Multiple processes finished in {:s}.'.format(s0))

    return


def run(case,
        routine=None,
        profile=False,
        dump_raw=False,
        pid=-1,
        show_data=None,