Commit 45482566 authored by Greenwood, Scott's avatar Greenwood, Scott
Browse files

fix issue with autocsm being called in a loop and not clearing global variables, remove old code

parent 9fc7bd39
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -214,6 +214,8 @@ def main(json_file_path, project_path, base_path, parent_class, output_path, str
        unifrom (list[2] bool): controls if structure [0] and sources [1] should be assumed uniform or individually
        force_redeclare (bool): adds redeclare statement to file even when child class remains unchanged from the default value
    """
    global_variables_interface.clear()
    
    data_orig = helper_functions.read_json(json_file_path)
    
    #TODO: Data check section
+0 −176
Original line number Diff line number Diff line
# -*- coding: utf-8 -*-
"""
@author: Scott Greenwood

Copyright (c) 2024 UT-Battelle
Licensed under the terms of both the MIT license and the Apache License (Version 2.0).
Users may choose either license, at their discretion.
"""

import os
import pathlib

from . import modelica_create_model_nested
from . import modelica_create_fmu_dymola
from . import modelica_create_architecture

class ModelicaMethods:
    """
    This class provides methods for Modelica-specific tasks such as creating architecture,
    generating models, and building FMUs.
    
    Attributes:
        parent (AutoCSM): The parent AutoCSM object that stores configuration details.
        base_path (str): The base path where Modelica templates are located.
    """
    BASE_PATH = pathlib.Path(__file__).parent
    TEMPLATE_FOLDER = (pathlib.Path(BASE_PATH) / '../../../methods/modelica/ExaDigiT_AutoCSM/Templates/TemplateSystem').resolve()
    STRUCTURE_PATH = (pathlib.Path(BASE_PATH) / '../../../methods/modelica/ExaDigiT_AutoCSM/Templates/Structure.mo').resolve()
    EXADIGIT_PACKAGE_PATH = (pathlib.Path(BASE_PATH) / '../../../methods/modelica/ExaDigiT_AutoCSM/package.mo').resolve()

    SUPPORTED_ARCHITECTURES = ['nested']
    SUPPORTED_FMU_COMPILERS = ['dymola']
    
    def __init__(self, parent):
        self.parent = parent
        
    def validate_architecture(self):
        """
        Validates if the current architecture is supported.
    
        Raises:
            ValueError: If the architecture is not supported.
        """
        if self.parent.architecture not in self.SUPPORTED_ARCHITECTURES:
            raise ValueError(f"Unsupported architecture: {self.parent.architecture}. "
                             f"Supported architectures are: {self.SUPPORTED_ARCHITECTURES}")
    
    def validate_fmu_compiler(self, fmu_compiler):
        """
        Validates if the current fmu compiler is supported.
    
        Raises:
            ValueError: If the fmu compiler is not supported.
        """
        if fmu_compiler not in self.SUPPORTED_FMU_COMPILERS:
            raise ValueError(f"Unsupported fmu compiler: {fmu_compiler}. "
                             f"Supported fmu compilers are: {self.SUPPORTED_FMU_COMPILERS}")
       
    def validate_and_convert_paths(self, paths: list) -> list:
        """
        Validates a list of file paths, converts them to absolute paths, and checks if they exist.
        
        Args:
            paths (list): List of file paths (relative or absolute).
        
        Returns:
            list: List of dependencies as absolute paths.
        
        Raises:
            FileNotFoundError: If any of the file paths do not exist.
        """
        absolute_paths = []
        
        for path in paths:
            abs_path = pathlib.Path(path).resolve()  # Convert to absolute path
            if not abs_path.exists():  # Check if the file exists
                raise FileNotFoundError(f"The file '{abs_path}' does not exist.")
            absolute_paths.append(abs_path.as_posix())
        
        return absolute_paths
            
    def create_architecture(self, template_folder: str = None):
        """
        Creates the Modelica architecture by copying the template system structure.
        
        Args:
            template_folder (str, optional): Path to the template folder. If not provided, uses the default.
        """
        # Validate the architecture
        self.validate_architecture()
       
        # Update input parameters
        template_folder = template_folder or self.TEMPLATE_FOLDER.as_posix()
        
        try:
            modelica_create_architecture.main(self.parent.input_specification,
                                              self.parent.output_path,
                                              template_folder,
                                              self.parent.architecture)
        except Exception as e:
            raise RuntimeError(f"Failed to create architecture: {str(e)}")
        
    def create_model(self, structure_path: str = None, parent_class: str = 'ExaDigiT_AutoCSM.BaseClasses.Tests.PartialTest', **kwargs):
        """
        Creates the Modelica model for the given architecture.
        
        Args:
            structure_path (str, optional): Path to the model structure file. If not provided, uses default.
            parent_class (str): The base class used in the Modelica model.
            uniform (list, optional): A list indicating uniform settings. Defaults to [True, True].
        """
        # Validate the architecture
        self.validate_architecture()
        
        # Update input parameters
        structure_path = structure_path or self.STRUCTURE_PATH.as_posix()
        
        try:
            if self.parent.architecture == 'nested':
                # Extract parameters from kwargs
                uniform = kwargs.pop('uniform', None)
                uniform = [True, True] if uniform is None or not uniform else uniform
                
                modelica_create_model_nested.main(self.parent.input_specification,
                                                  self.parent.project_path,
                                                  pathlib.Path(self.parent.project_path).name,
                                                  parent_class,
                                                  self.parent.model_path,
                                                  structure_path,
                                                  uniform)
            #TODO: Add new architecture methods here
        except Exception as e:
            raise RuntimeError(f"Failed to create model: {str(e)}")
            
    def create_fmu(self,  dependencies: list = None,  fmu_compiler: str = 'dymola', experimentSettings: dict = None, **kwargs):
        """
        Generates an FMU (Functional Mock-up Unit) using the specified compiler.
        
        Args:
            dependencies (list, optional): List of dependencies required for FMU generation. If not provided, uses defaults.
            fmu_compiler (str): Compiler to use for FMU generation. Defaults to 'dymola'.
            experimentSettings (dict, optional): FMU experiment settings. Defaults to an empty dict.
            **kwargs: Additional keyword arguments passed to the FMU compiler method.
        """
        # Validate the fmu compiler
        self.validate_fmu_compiler(fmu_compiler)
            
        # Verify dependencies are valid
        dependencies = self.validate_and_convert_paths(dependencies)
        
        # Update input parameters
        dependencies = dependencies or []
        experimentSettings = experimentSettings or {}
    
        try:
            # Adds package if not already in dependency list
            project_package = (pathlib.Path(self.parent.project_path) / 'package.mo').resolve()
            if project_package.as_posix() not in dependencies:
                dependencies.append(project_package.as_posix())
            
            # This avoids redefining the ExaDigiT method template if it already was included in the dependency in a different location (e.g., a customized version)
            if '/'.join(list(self.EXADIGIT_PACKAGE_PATH.parts[-2])) not in dependencies:
                dependencies.append(self.EXADIGIT_PACKAGE_PATH.as_posix())
    
            if fmu_compiler == 'dymola':
                # Extract parameters from kwargs
                showwindow = kwargs.pop('showwindow', False)
                
                modelica_create_fmu_dymola.main(dependencies, 
                                                self.parent.model_path, 
                                                pathlib.Path(self.parent.output_path).resolve(),
                                                experimentSettings, 
                                                showwindow)
            #TODO: Add new fmu compiler methods here
        except Exception as e:
            raise RuntimeError(f"Failed to create FMU: {str(e)}")
 No newline at end of file