pyemsol を使用したPythonスクリプト例#

モータ解析を想定した output.json のデータを取り出すサンプルコード#

output.json のデータを取り出すサンプルコード#
# coding: utf-8
"""
read_emsojson_motor.py – sample script for pyemsol
Copyright © 2025 Sicence Solutions International Laboratory, Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the “Software”), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in
    all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON‑INFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
# SPDX-License-Identifier: MIT

import json
import csv
import numpy as np

import dq_trans


def write_csv(filename, data, header):
    """
    Write data to a CSV file.

    Parameters:
    filename (str): The name of the CSV file.
    data (numpy.ndarray): The data to write to the CSV file.
    header (list of str): The header for the CSV file.
    """
    with open(filename, "w", newline="") as csvfile:  # Open in append mode
        csv_writer = csv.writer(csvfile)
        if csvfile.tell() == 0:  # If file is empty, write the header
            csv_writer.writerow(header)
        csv_writer.writerows(data)
        csv_writer.writerow("")


def write_postData_to_csv(output_list, region_factor, num_steps):
    # make angles array
    angles = dq_trans.generate_angle_array(num_steps)
    dq_header = ["Angle"]
    torque_header = ["Angle"]
    dq_data = []
    torque_data = []
    # Generate file names and process each JSON file
    for filename in output_list:
        # Check if the file exists
        with open(filename, "r") as file:
            data = json.load(file)

        header_base = filename.replace("output", "").replace(".json", "")
        dq_header.append(f"d:{header_base}")
        dq_header.append(f"q:{header_base}")
        torque_header.append(f"{header_base}")

        # Extract "flux" data
        # need to change the index to 0,1,2 for 3 phase motor
        f_a = data["postData"]["network"]["networkData"][0]["flux"]
        f_b = data["postData"]["network"]["networkData"][1]["flux"]
        f_c = data["postData"]["network"]["networkData"][2]["flux"]

        angles = angles[: len(f_a)]
        if len(dq_data) == 0:
            dq_data.append(angles)
            torque_data.append(angles)

        # Combine angles, v_a, v_b, and v_c into a single array
        flux_data = [angles, f_a, f_b, f_c]
        dq_output = dq_trans.abc2dq(flux_data)

        d = dq_output[0]
        q = dq_output[1]
        dq_data.append(d)
        dq_data.append(q)

        # Extract "torque" data
        force_json = data["postData"]["forceNodal"]["forceNodalData"]
        for j in range(len(force_json)):
            if force_json[j]["propertyNum"] == "rotor":
                torque = force_json[j]["forceMZ"]

        torque = np.array(torque, dtype=float)
        # Multiply torque by the region factor
        torque *= region_factor
        torque_data.append(torque)

    # Combine all data into a single array for CSV writing
    combined_data = np.column_stack(dq_data)
    # Write dq_output to CSV
    csv_file_name = "dq_output.csv"
    write_csv(csv_file_name, combined_data, dq_header)

    # Combine all data into a single array for CSV writing
    combined_data = np.column_stack(torque_data)
    # Write torque to CSV
    csv_file_name = "torque_output.csv"
    write_csv(csv_file_name, combined_data, torque_header)


# Example usage
output_list = [
    "output0Arms0deg.json",
    "output1Arms0deg.json",
    "output2Arms0deg.json",
    # Add more filenames as needed
]
region_factor = 1.0  # Example region factor
num_steps = 180  # Example number of steps

write_postData_to_csv(output_list, region_factor, num_steps)
# Note: The above code assumes that the JSON files are in the same directory as this script.

update_Time_Function を使用して時間関数を更新するサンプルコード#

update_Time_Function を使用してを使用して時間関数を更新するサンプルコード#
# coding: utf-8
"""
updateAmplitudesAndPhases.py – sample script for pyemsol
Copyright © 2025 Sicence Solutions International Laboratory, Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the “Software”), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in
    all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON‑INFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
# SPDX-License-Identifier: MIT

import os
import json
import numpy as np
import csv
import subprocess

import pyemsol


def write_list_to_file(filename, lst):
    """
    Write a list of strings to a text file.

    Parameters:
    filename (str): The name of the text file.
    lst (list of str): The list to write to the file.
    """
    with open(filename, "w") as file:
        for item in lst:
            file.write("%s\n" % item)


def read_list_from_file(filename):
    """
    Read a list of strings from a text file.

    Parameters:
    filename (str): The name of the text file.

    Returns:
    list of str: The list read from the file.
    """
    with open(filename, "r") as file:
        return [line.strip() for line in file]


def get_time_function(json_data, id):
    time_function = json_data["18_Time_Function"]
    for time in time_function:
        if time["TIME_ID"] == id:
            return time
    return None


def change_current_amplitude(json_data, rms, phase_number):
    amplitude = rms * np.sqrt(2)
    for i in range(phase_number):
        time = get_time_function(json_data, i + 1)
        time["AMPLITUDE"] = amplitude


def change_electrical_phase(json_data, phase, phase_number):
    for i in range(phase_number):
        time = get_time_function(json_data, i + 1)
        time["PHASE"] = phase + i * -360 / phase_number + 90


def modify_json_and_call_pyemsol(file_name, current_rms, electrical_phase, output_list_filename):
    current_directory = os.getcwd()
    os.chdir("Dmodel")

    # Step 1: Read the JSON file once
    with open(file_name, "r") as file:
        json_data = json.load(file)

    outputfilenames = []
    current_directory = os.getcwd()

    phase_number = 3  # assume 3-phase machine

    pyemsol.initialize(json_data, current_directory)

    total_counts = len(current_rms) * len(electrical_phase)
    count = 1
    for current in current_rms:
        current_outputfilenames = []
        change_current_amplitude(json_data, current, phase_number)
        for phase in electrical_phase:
            change_electrical_phase(json_data, phase, phase_number)

            time_function = json_data["18_Time_Function"]
            ret = pyemsol.update_Time_Function(time_function)
            #            ret = pyemsol.update_Time_Function(json_data)

            print(f"Calculation {count}/{total_counts}: Processing {current} Arms, {phase} deg.")
            count += 1

            output = pyemsol.solve()

            if os.path.exists("output.json"):
                outputname = f"output{current}Arms{phase}deg.json"
                if os.path.exists(outputname):
                    os.remove(outputname)
                os.rename("./output.json", outputname)
                current_outputfilenames.append(outputname)

        outputfilenames.append(current_outputfilenames)

    pyemsol.finalize()

    # Write the list of output filenames to a file
    write_list_to_file(output_list_filename, outputfilenames)
    return outputfilenames


# Example usage
current_rms = [1, 2, 3, 4, 5]
electrical_phase = [-90, 0, 90]
input_file_name = "input2D_static3A25deg.json"  #'input2D_transient3A25deg.json'
output_list_filename = "output_file_list.txt"
outputs = modify_json_and_call_pyemsol(input_file_name, current_rms, electrical_phase, output_list_filename)

update_properties_in_design_domain を使用して設計領域の材料特性データを更新するサンプルコード#

update_properties_in_design_domain を使用して設計領域の材料特性データを更新するサンプルコード#
# coding: utf-8
"""
updateMagneticProperties.py – sample script for pyemsol
Copyright © 2025 Sicence Solutions International Laboratory, Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the “Software”), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in
    all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON‑INFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
# SPDX-License-Identifier: MIT

import os
import json
import csv
import subprocess
import numpy as np
import pyemsol

import dq_trans


def write_list_to_file(filename, lst):
    """
    Write a list of strings to a text file.

    Parameters:
    filename (str): The name of the text file.
    lst (list of str): The list to write to the file.
    """
    with open(filename, "w") as file:
        for item in lst:
            file.write("%s\n" % item)


def read_list_from_file(filename):
    """
    Read a list of strings from a text file.

    Parameters:
    filename (str): The name of the text file.

    Returns:
    list of str: The list read from the file.
    """
    with open(filename, "r") as file:
        return [line.strip() for line in file]


# change magnetic property in "16_Material_Properties"
def change_magnetic_property(matData, prop_id, magnetic_property_mat_id_1):
    data3D = matData["16_1_3D_Element_Properties"]
    for element in data3D:
        if element["MAT_ID"] == prop_id:
            element["MagneticProperty"] = magnetic_property_mat_id_1


# change permeability in "16_Material_Properties"
def change_permeability(matData, prop_id, permeability):
    data3D = matData["16_1_3D_Element_Properties"]
    for element in data3D:
        if element["MAT_ID"] == prop_id:
            element["MagneticProperty"]["MU"] = permeability


def modify_json_and_call_pyemsol(file_name, folder_path, prop_ids, paraMu, output_list_filename):
    current_directory = os.getcwd()
    # Change the current working directory to the specified folder
    os.chdir(folder_path)
    print(folder_path)

    # Step 1: Read the JSON file once
    with open(file_name, "r") as file:
        json_data = json.load(file)

    # Loop through the elements in "16_1_3D_Element_Properties"
    matData = json_data["16_Material_Properties"]

    # Initialize variables to hold MagneticProperty values
    magnetic_property_mat_id_1 = None
    data3D = matData["16_1_3D_Element_Properties"]
    for element in data3D:
        if element["MAT_ID"] == 1:
            magnetic_property_mat_id_1 = element["MagneticProperty"]
            break

    outputfilenames = []
    current_directory = os.getcwd()

    pyemsol.initialize(json_data, current_directory)

    for mu in paraMu:
        for prop_id in prop_ids:
            change_permeability(matData, prop_id, mu)

            print("START: " + str(mu) + "_prop" + str(prop_id))

            # target property must have "is_DESIGN_DOMAIN" : 1,
            ret = pyemsol.update_properties_in_design_domain(matData)
            output = pyemsol.solve()

            if os.path.exists("output.json"):
                outputname = "outputMu" + str(mu) + "_prop" + str(prop_id) + ".json"
                if os.path.exists(outputname):
                    os.remove(outputname)
                os.rename("./output.json", "outputMu" + str(mu) + "_prop" + str(prop_id) + ".json")
                outputfilenames.append(outputname)

    pyemsol.finalize()

    for prop_id in prop_ids:
        change_permeability(matData, prop_id, 1.0)

    pyemsol.initialize(json_data, current_directory)

    for prop_id in prop_ids:
        change_magnetic_property(matData, prop_id, magnetic_property_mat_id_1)

        #        # Save the modified data back to the file
        #        save_file_name = 'mod_' + file_name
        #        with open(save_file_name, 'w') as file:
        #            json.dump(json_data, file, indent=4)

        # Call pyemsol
        ret = pyemsol.update_properties_in_design_space(matData)
        output = pyemsol.solve()

        if os.path.exists("output.json"):
            outputname = "outputBH_prop" + str(prop_id) + ".json"
            if os.path.exists(outputname):
                os.remove(outputname)
            os.rename("./output.json", "outputBH_prop" + str(prop_id) + ".json")
            outputfilenames.append(outputname)

    pyemsol.finalize()

    # Write the list of output filenames to a file
    write_list_to_file(output_list_filename, outputfilenames)

    # move back to the parent folder
    if folder_path != ".":
        os.chdir("..")

    return outputfilenames


def write_csv(filename, data, header):
    """
    Write data to a CSV file.

    Parameters:
    filename (str): The name of the CSV file.
    data (numpy.ndarray): The data to write to the CSV file.
    header (list of str): The header for the CSV file.
    """
    with open(filename, "w", newline="") as csvfile:  # Open in append mode
        csv_writer = csv.writer(csvfile)
        if csvfile.tell() == 0:  # If file is empty, write the header
            csv_writer.writerow(header)
        csv_writer.writerows(data)
        csv_writer.writerow("")


def write_flux_data_to_csv(output_list_filename, folder_path, region_factor, cycle):
    # Change the current working directory to the specified folder
    os.chdir(folder_path)
    print(folder_path + " csv")

    angles = dq_trans.generate_angle_array(cycle)
    dq_header = ["Angle"]
    torque_header = ["Angle"]
    dq_data = []
    torque_data = []
    # Generate file names and process each JSON file
    for filename in read_list_from_file(output_list_filename):
        with open(filename, "r") as file:
            data = json.load(file)

        header_base = filename.replace("output", "").replace(".json", "")
        dq_header.append(f"d:{header_base}")
        dq_header.append(f"q:{header_base}")
        torque_header.append(f"{header_base}")

        # Extract "flux" data
        f_a = data["postData"]["network"]["networkData"][0]["flux"]
        f_b = data["postData"]["network"]["networkData"][1]["flux"]
        f_c = data["postData"]["network"]["networkData"][2]["flux"]

        angles = angles[: len(f_a)]
        if len(dq_data) == 0:
            dq_data.append(angles)
            torque_data.append(angles)

        # Combine angles, v_a, v_b, and v_c into a single array
        flux_data = [angles, f_a, f_b, f_c]
        dq_output = dq_trans.abc2dq(flux_data)

        d = dq_output[0]
        q = dq_output[1]
        dq_data.append(d)
        dq_data.append(q)

        # Extract "torque" data
        force_json = data["postData"]["forceNodal"]["forceNodalData"]
        for j in range(len(force_json)):
            if force_json[j]["propertyNum"] == "rotor":
                torque = force_json[j]["forceMZ"]

        torque = np.array(torque, dtype=float)
        # Multiply torque by the region factor
        torque *= region_factor
        torque_data.append(torque)

    # Combine all data into a single array for CSV writing
    combined_data = np.column_stack(dq_data)
    # Write dq_output to CSV
    csv_file_name = "dq_output.csv"
    if folder_path != ".":
        csv_file_name = "dq_output_" + folder_path + ".csv"
    write_csv(csv_file_name, combined_data, dq_header)

    # Combine all data into a single array for CSV writing
    combined_data = np.column_stack(torque_data)
    # Write torque to CSV
    csv_file_name = "torque_output.csv"
    if folder_path != ".":
        csv_file_name = "torque_output_" + folder_path + ".csv"
    write_csv(csv_file_name, combined_data, torque_header)

    # move back to the parent folder
    if folder_path != ".":
        os.chdir("..")


# Example usage
prop_ids = [54, 53, 52, 51]
paraMu = [3.4, 7.6]
input_file_name = "input_cogging.json"
child_folder = "."
output_list_filename = "output_file_list.txt"
outputs = modify_json_and_call_pyemsol(input_file_name, child_folder, prop_ids, paraMu, output_list_filename)

write_flux_data_to_csv(output_list_filename, ".", 6, 144)