Loading AutoCSM/auto_csm.py +4 −2 Original line number Diff line number Diff line # -*- coding: utf-8 -*- """ Created on Fri Sep 20 11:54:58 2024 @author: Scott Greenwood @author: fig 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 pathlib Loading AutoCSM/helper_functions.py +5 −2 Original line number Diff line number Diff line # -*- coding: utf-8 -*- """ Created on Thu May 30 17:26:47 2024 @author: Scott Greenwood @author: fig 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 json def read_json(file_path): Loading AutoCSM/languages/julia/julia_methods.py +126 −18 Original line number Diff line number Diff line # -*- coding: utf-8 -*- """ Created on Wed Jun 5 13:45:13 2024 @author: Scott Greenwood @author: fig 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 Julia-specific dependencies here # Example: from julia_package import JuliaClass # from .additional_julia_method import additional_method import os import pathlib from ..language_method import LanguageMethod # Import Julia-specific dependencies here, for example: # from . import julia_create_model_nested # from . import julia_create_fmu_fmijl # from . import julia_create_architecture class JuliaMethods(LanguageMethod): """ Implements Julia-specific methods for creating architecture, generating models, and building FMUs. Attributes: METHOD_PATH (Path): The path where the Julia method to use is located. TEMPLATE_FOLDER (Path): Path to the folder containing the Modelica template system. STRUCTURE_PATH (Path): Path to the file defining the Modelica structure component. SUPPORTED_ARCHITECTURES (list): Architectures supported by Modelica. SUPPORTED_FMU_COMPILERS (list): FMU compilers supported by Modelica. """ METHOD_PATH = (pathlib.Path(LanguageMethod.BASE_PATH) / '../../methods/julia/UPDATEME').resolve() TEMPLATE_FOLDER = (METHOD_PATH / 'Templates/UPDATEME').resolve() STRUCTURE_PATH = (METHOD_PATH / 'Templates/UPDATEME.mo').resolve() SUPPORTED_ARCHITECTURES = ['UPDATEME'] SUPPORTED_FMU_COMPILERS = ['UPDATEME'] class JuliaMethods: def __init__(self, parent): self.parent = parent super().__init__(parent) # Call the parent class initializer def create_architecture(self, template_folder: str = None, **kwargs): """ Creates the Julia architecture by copying the template system structure. Args: template_folder (str, optional): Path to the template folder. If not provided, uses the default. **kwargs: Additional keyword arguments for creating the architecture. Raises: RuntimeError: If the architecture creation fails. """ # Call the parent logic super().create_architecture(template_folder) try: # Insert supported methods here, for example: # julia_create_architecture.main(self.parent.input_specification, # self.parent.output_path, # template_folder, # self.parent.architecture) pass except FileNotFoundError as e: raise RuntimeError(f"Template not found: {e}") 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 specified architecture. Args: structure_path (str, optional): Path to the model structure file. Defaults to self.STRUCTURE_PATH. parent_class (str): The base example model for constructing the model. uniform (list, optional): A list indicating uniform settings. Defaults to [True, True]. **kwargs: Additional keyword arguments for model creation. Raises: RuntimeError: If the model creation fails. """ # Call the parent logic structure_path = super().create_model(structure_path, **kwargs) try: # Insert supported methods here, for example: # 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 # julia_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) except FileNotFoundError as e: raise RuntimeError(f"File not found during model creation: {e}") 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 using the specified compiler. Args: dependencies (list[str], optional): List of dependencies required for FMU generation. fmu_compiler (str, optional): Compiler to use for FMU generation. Defaults to 'dymola'. experimentSettings (dict, optional): FMU experiment settings. Defaults to an empty dict. **kwargs: Additional keyword arguments for FMU creation. Raises: RuntimeError: If FMU creation fails. """ dependencies, experimentSettings = super().create_fmu(dependencies, fmu_compiler, experimentSettings, **kwargs) def read_input(self, file_path, *args, **kwargs): print(f"Julia: Reading input from {file_path} with architecture: {self.parent.architecture}, args: {args}, kwargs: {kwargs}") # Add Julia-specific read input implementation here # additional_method() # Use this to populate default dependencies # dependencies.append() def create_model(self, model_name, *args, **kwargs): print(f"Julia: Creating model {model_name} with architecture: {self.parent.architecture}, args: {args}, kwargs: {kwargs}") # Add Julia-specific create model implementation here try: # Insert supported methods here, for example: # if fmu_compiler == 'dymola': # # Extract parameters from kwargs # showwindow = kwargs.pop('showwindow', False) def create_fmu(self, fmu_name, *args, **kwargs): print(f"Julia: Creating FMU {fmu_name} with architecture: {self.parent.architecture}, args: {args}, kwargs: {kwargs}") # Add Julia-specific create FMU implementation here # julia_create_fmu_fmijl.main(dependencies, # self.parent.model_path, # pathlib.Path(self.parent.output_path).resolve(), # experimentSettings, # showwindow) except FileNotFoundError as e: raise RuntimeError(f"Dependency file not found: {e}") except Exception as e: raise RuntimeError(f"Failed to create FMU: {str(e)}") No newline at end of file AutoCSM/languages/language_method.py 0 → 100644 +162 −0 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 pathlib from abc import ABC, abstractmethod class LanguageMethod: """ A base class for methods that extend from different language methods, such as Modelica. This class provides basic structure and validation for methods that are extended by specific language methods (e.g., Modelica). Child classes must implement the following abstract methods: - create_architecture() - create_model() - create_fmu() Attributes: parent (AutoCSM): The parent AutoCSM object. BASE_PATH (Path): Base path where python methods are located (for relative path reconstruction). METHOD_PATH (Path): Path to the ExaDigiT language method implmentation. TEMPLATE_PATH (Path): Path to folder containing the template folder structure. STRUCTURE_PATH (Path): Path to the file defining the structure component. SUPPORTED_ARCHITECTURES (list): Supported architectures for the method. SUPPORTED_FMU_COMPILERS (list): Supported FMU compilers for the method. """ BASE_PATH = pathlib.Path(__file__).parent METHOD_PATH = None # To be overridden by child classes TEMPLATE_PATH = None # To be overridden by child classes STRUCTURE_PATH = None # To be overridden by child classes SUPPORTED_ARCHITECTURES = [] # To be overridden by child classes SUPPORTED_FMU_COMPILERS = [] # To be overridden by child classes 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 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 compilers are: {self.SUPPORTED_FMU_COMPILERS}") def validate_and_convert_paths(self, paths: list) -> list: """ Validates and converts a list of file paths to absolute paths. Args: paths (list): List of file paths (relative or absolute). Returns: list: List of validated absolute paths. Raises: FileNotFoundError: If any file path does not exist. """ absolute_paths = [] for path in paths: abs_path = pathlib.Path(path).resolve() if not abs_path.exists(): raise FileNotFoundError(f"The file '{abs_path}' does not exist.") absolute_paths.append(abs_path.as_posix()) return absolute_paths @abstractmethod def create_architecture(self, template_folder: str = None, **kwargs): """ Abstract method to create a language-supported architecture by copying the template system structure. Args: template_folder (str, optional): Path to the template folder. If not provided, uses the default TEMPLATE_FOLDER. Note: This method must be implemented by child classes to handle architecture creation specific to the language (e.g., Modelica, etc.). """ # Validate the architecture self.validate_architecture() # Update input parameters template_folder = template_folder or self.TEMPLATE_FOLDER.as_posix() return template_folder @abstractmethod def create_model(self, structure_path: str = None, **kwargs): """ Creates the model using the selected architecture. Args: structure_path (str, optional): Path to the model structure file. If not provided, uses teh default STRUCTURE_PATH. parent_class (str): The base example model for constructing the model. **kwargs: Additional keyword arguments passed to the method. Note: This method must be implemented by child classes to handle architecture creation specific to the language (e.g., Modelica, etc.). """ # Validate the architecture self.validate_architecture() # Update input parameters structure_path = structure_path or self.STRUCTURE_PATH.as_posix() return structure_path @abstractmethod def create_fmu(self, dependencies: list = None, fmu_compiler: str = '', experimentSettings: dict = None, **kwargs): """ Generates an FMU (Functional Mock-up Unit) using the specified compiler. Args: dependencies Optional[List[str]] List of dependencies required for FMU generation. If not provided, uses defaults. fmu_compiler (str): Compiler to use for FMU generation. experimentSettings (dict, optional): FMU experiment settings. Defaults to an empty dict. **kwargs: Additional keyword arguments passed to the method. Note: This method must be implemented by child classes to handle architecture creation specific to the language (e.g., Modelica, etc.). """ # 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 {} return dependencies, experimentSettings AutoCSM/languages/modelica/modelica_create_architecture.py +6 −3 Original line number Diff line number Diff line # -*- coding: utf-8 -*- """ Created on Fri May 24 11:41:24 2024 @author: Scott Greenwood @author: fig 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. TODO: Could add additional layer details to recreate the nested model structure of the generic approach - This would add to the Structure and ControlBus the appropirate information TODO: Could autopopulate model isntance in strcuture with parallel logic (if instanceNames provided) TODO: Could autopopulate model instance in structure with parallel logic (if instanceNames provided) """ import os import shutil import json Loading Loading
AutoCSM/auto_csm.py +4 −2 Original line number Diff line number Diff line # -*- coding: utf-8 -*- """ Created on Fri Sep 20 11:54:58 2024 @author: Scott Greenwood @author: fig 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 pathlib Loading
AutoCSM/helper_functions.py +5 −2 Original line number Diff line number Diff line # -*- coding: utf-8 -*- """ Created on Thu May 30 17:26:47 2024 @author: Scott Greenwood @author: fig 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 json def read_json(file_path): Loading
AutoCSM/languages/julia/julia_methods.py +126 −18 Original line number Diff line number Diff line # -*- coding: utf-8 -*- """ Created on Wed Jun 5 13:45:13 2024 @author: Scott Greenwood @author: fig 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 Julia-specific dependencies here # Example: from julia_package import JuliaClass # from .additional_julia_method import additional_method import os import pathlib from ..language_method import LanguageMethod # Import Julia-specific dependencies here, for example: # from . import julia_create_model_nested # from . import julia_create_fmu_fmijl # from . import julia_create_architecture class JuliaMethods(LanguageMethod): """ Implements Julia-specific methods for creating architecture, generating models, and building FMUs. Attributes: METHOD_PATH (Path): The path where the Julia method to use is located. TEMPLATE_FOLDER (Path): Path to the folder containing the Modelica template system. STRUCTURE_PATH (Path): Path to the file defining the Modelica structure component. SUPPORTED_ARCHITECTURES (list): Architectures supported by Modelica. SUPPORTED_FMU_COMPILERS (list): FMU compilers supported by Modelica. """ METHOD_PATH = (pathlib.Path(LanguageMethod.BASE_PATH) / '../../methods/julia/UPDATEME').resolve() TEMPLATE_FOLDER = (METHOD_PATH / 'Templates/UPDATEME').resolve() STRUCTURE_PATH = (METHOD_PATH / 'Templates/UPDATEME.mo').resolve() SUPPORTED_ARCHITECTURES = ['UPDATEME'] SUPPORTED_FMU_COMPILERS = ['UPDATEME'] class JuliaMethods: def __init__(self, parent): self.parent = parent super().__init__(parent) # Call the parent class initializer def create_architecture(self, template_folder: str = None, **kwargs): """ Creates the Julia architecture by copying the template system structure. Args: template_folder (str, optional): Path to the template folder. If not provided, uses the default. **kwargs: Additional keyword arguments for creating the architecture. Raises: RuntimeError: If the architecture creation fails. """ # Call the parent logic super().create_architecture(template_folder) try: # Insert supported methods here, for example: # julia_create_architecture.main(self.parent.input_specification, # self.parent.output_path, # template_folder, # self.parent.architecture) pass except FileNotFoundError as e: raise RuntimeError(f"Template not found: {e}") 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 specified architecture. Args: structure_path (str, optional): Path to the model structure file. Defaults to self.STRUCTURE_PATH. parent_class (str): The base example model for constructing the model. uniform (list, optional): A list indicating uniform settings. Defaults to [True, True]. **kwargs: Additional keyword arguments for model creation. Raises: RuntimeError: If the model creation fails. """ # Call the parent logic structure_path = super().create_model(structure_path, **kwargs) try: # Insert supported methods here, for example: # 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 # julia_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) except FileNotFoundError as e: raise RuntimeError(f"File not found during model creation: {e}") 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 using the specified compiler. Args: dependencies (list[str], optional): List of dependencies required for FMU generation. fmu_compiler (str, optional): Compiler to use for FMU generation. Defaults to 'dymola'. experimentSettings (dict, optional): FMU experiment settings. Defaults to an empty dict. **kwargs: Additional keyword arguments for FMU creation. Raises: RuntimeError: If FMU creation fails. """ dependencies, experimentSettings = super().create_fmu(dependencies, fmu_compiler, experimentSettings, **kwargs) def read_input(self, file_path, *args, **kwargs): print(f"Julia: Reading input from {file_path} with architecture: {self.parent.architecture}, args: {args}, kwargs: {kwargs}") # Add Julia-specific read input implementation here # additional_method() # Use this to populate default dependencies # dependencies.append() def create_model(self, model_name, *args, **kwargs): print(f"Julia: Creating model {model_name} with architecture: {self.parent.architecture}, args: {args}, kwargs: {kwargs}") # Add Julia-specific create model implementation here try: # Insert supported methods here, for example: # if fmu_compiler == 'dymola': # # Extract parameters from kwargs # showwindow = kwargs.pop('showwindow', False) def create_fmu(self, fmu_name, *args, **kwargs): print(f"Julia: Creating FMU {fmu_name} with architecture: {self.parent.architecture}, args: {args}, kwargs: {kwargs}") # Add Julia-specific create FMU implementation here # julia_create_fmu_fmijl.main(dependencies, # self.parent.model_path, # pathlib.Path(self.parent.output_path).resolve(), # experimentSettings, # showwindow) except FileNotFoundError as e: raise RuntimeError(f"Dependency file not found: {e}") except Exception as e: raise RuntimeError(f"Failed to create FMU: {str(e)}") No newline at end of file
AutoCSM/languages/language_method.py 0 → 100644 +162 −0 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 pathlib from abc import ABC, abstractmethod class LanguageMethod: """ A base class for methods that extend from different language methods, such as Modelica. This class provides basic structure and validation for methods that are extended by specific language methods (e.g., Modelica). Child classes must implement the following abstract methods: - create_architecture() - create_model() - create_fmu() Attributes: parent (AutoCSM): The parent AutoCSM object. BASE_PATH (Path): Base path where python methods are located (for relative path reconstruction). METHOD_PATH (Path): Path to the ExaDigiT language method implmentation. TEMPLATE_PATH (Path): Path to folder containing the template folder structure. STRUCTURE_PATH (Path): Path to the file defining the structure component. SUPPORTED_ARCHITECTURES (list): Supported architectures for the method. SUPPORTED_FMU_COMPILERS (list): Supported FMU compilers for the method. """ BASE_PATH = pathlib.Path(__file__).parent METHOD_PATH = None # To be overridden by child classes TEMPLATE_PATH = None # To be overridden by child classes STRUCTURE_PATH = None # To be overridden by child classes SUPPORTED_ARCHITECTURES = [] # To be overridden by child classes SUPPORTED_FMU_COMPILERS = [] # To be overridden by child classes 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 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 compilers are: {self.SUPPORTED_FMU_COMPILERS}") def validate_and_convert_paths(self, paths: list) -> list: """ Validates and converts a list of file paths to absolute paths. Args: paths (list): List of file paths (relative or absolute). Returns: list: List of validated absolute paths. Raises: FileNotFoundError: If any file path does not exist. """ absolute_paths = [] for path in paths: abs_path = pathlib.Path(path).resolve() if not abs_path.exists(): raise FileNotFoundError(f"The file '{abs_path}' does not exist.") absolute_paths.append(abs_path.as_posix()) return absolute_paths @abstractmethod def create_architecture(self, template_folder: str = None, **kwargs): """ Abstract method to create a language-supported architecture by copying the template system structure. Args: template_folder (str, optional): Path to the template folder. If not provided, uses the default TEMPLATE_FOLDER. Note: This method must be implemented by child classes to handle architecture creation specific to the language (e.g., Modelica, etc.). """ # Validate the architecture self.validate_architecture() # Update input parameters template_folder = template_folder or self.TEMPLATE_FOLDER.as_posix() return template_folder @abstractmethod def create_model(self, structure_path: str = None, **kwargs): """ Creates the model using the selected architecture. Args: structure_path (str, optional): Path to the model structure file. If not provided, uses teh default STRUCTURE_PATH. parent_class (str): The base example model for constructing the model. **kwargs: Additional keyword arguments passed to the method. Note: This method must be implemented by child classes to handle architecture creation specific to the language (e.g., Modelica, etc.). """ # Validate the architecture self.validate_architecture() # Update input parameters structure_path = structure_path or self.STRUCTURE_PATH.as_posix() return structure_path @abstractmethod def create_fmu(self, dependencies: list = None, fmu_compiler: str = '', experimentSettings: dict = None, **kwargs): """ Generates an FMU (Functional Mock-up Unit) using the specified compiler. Args: dependencies Optional[List[str]] List of dependencies required for FMU generation. If not provided, uses defaults. fmu_compiler (str): Compiler to use for FMU generation. experimentSettings (dict, optional): FMU experiment settings. Defaults to an empty dict. **kwargs: Additional keyword arguments passed to the method. Note: This method must be implemented by child classes to handle architecture creation specific to the language (e.g., Modelica, etc.). """ # 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 {} return dependencies, experimentSettings
AutoCSM/languages/modelica/modelica_create_architecture.py +6 −3 Original line number Diff line number Diff line # -*- coding: utf-8 -*- """ Created on Fri May 24 11:41:24 2024 @author: Scott Greenwood @author: fig 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. TODO: Could add additional layer details to recreate the nested model structure of the generic approach - This would add to the Structure and ControlBus the appropirate information TODO: Could autopopulate model isntance in strcuture with parallel logic (if instanceNames provided) TODO: Could autopopulate model instance in structure with parallel logic (if instanceNames provided) """ import os import shutil import json Loading