"""
Example shows how to use Artap together with localy installed Comsol Multiphysics

"""

from artap.executor import LocalComsolExecutor
from artap.problem import Problem
from artap.algorithm_scipy import ScipyOpt


class ComsolProblem(Problem):
    """
    Describe simple one objective optimization problem.

    """

    def set(self):
        self.name = "ComsolProblem"

        # Parameters must be defined in the Comsol model
        self.parameters = [{'name': 'a', 'initial_value': 10, 'bounds': [0.1, 100]},  # parameters a, b must be positive
                           {'name': 'b', 'initial_value': 10, 'bounds': [0.1, 100]}]

        self.costs = [{'name': 'F1', 'criteria': 'minimize'}]
        self.output_files = ["energy.txt"]

        # Executor serves for calling the Comsol Multiphisics
        self.executor = LocalComsolExecutor(self,
                                            problem_file="capacitor/capacitor.mph",  # File with the model
                                            output_files=self.output_files)  # file with results produced by Comsol

    # Calculate the value of the objective function
    def evaluate(self, individual):
        U = 10
        C_req = 5e-12  # the capacity 5 pF is required
        energy = self.executor.eval(individual)[0]
        capacity = 2 * energy / U ** 2
        f = abs(capacity - C_req)
        print(capacity)
        return [f / C_req]  # method evaluate must return list

    # This method processes files generated by 3rd party software, depends on files format
    def parse_results(self, output_files, individual):
        output_file = output_files[0]
        path = output_file
        with open(path) as file:
            content = file.read()

        lines = content.split("\n")
        line_with_results = lines[5]  # 5th line contains results

        result = float(line_with_results.split()[2])
        return [result]


if __name__ == "__main__":
    problem = ComsolProblem()  # Creating problem
    algorithm = ScipyOpt(problem)  # Algorithm from Scipy was choosen
    algorithm.options['algorithm'] = 'COBYLA'
    algorithm.options['n_iterations'] = 5
    algorithm.run()
