This section describes the settings and usage of Python API.
SimWorks provides a Python application programming interface (API) called simworks, which allows users to interact with SimWorks software (such as FDTD, FDE, and FDFD) through Python scripts to achieve the following functions.
This Python API interface enables greater freedom in data processing, automated simulation execution, parameter optimization, high-performance computing, etc., which meets users' advanced needs such as secondary development.
The following describes how to configure the Python environment so that it can correctly load the native DLL and Python API library of SimWorks simulation software.
To enable interaction between SimWorks software and Python programming language, the user needs to have Python installed on the local machine. Python 3.12 version and above are recommended. If you have not installed it, it is recommended that you download the Python development tool for free, for example PyCharm.
The SimWorks Python API requires the numpy library, so it is recommended to install it using tools such as pip.
Append the directory of simworks.py to the current directory and use the append() function to add the path with the interface module so that the import class can successfully retrieve the simworks API. Take the default software installation directory as an example for detailed explanation:
import os, sys
os.add_dll_directory(r"C:\Program Files\SimWorks\SimWorks FD Solutions\bin")
sys.path.append(r"C:\Program Files\SimWorks\SimWorks FD Solutions\api\python")
import simworks
import numpy as np
chmod +x ./appimage_file.AppImage
--appimage-extract
option./appimage_file.AppImage --appimage-extract
import sys, os
sys.path.append("squashfs-root/api/usr/api/python/")
Contents/api/python/
.Contents/api/python/
.The Python API architecture supports both local and remote invocation and is capable of operating across different operating systems. Remote invocation is implemented through client-server communication: the server program runs persistently and listens on a specified port, while the client establishes a socket channel to communicate with the server through this port. The client sends invocation requests to the server, which parses the requests, starts the fd_solutions
locally to execute tasks, and returns the results to the client, enabling cross-platform remote invocation.
To establish two-way communication between the client and server, the server must first configure the communication port. Before the first run, follow these steps (the related script files are located in the /api/interop_server/scripts/
directory of the software):
Run the generate_certificate
script to generate a self-signed certificate. Follow the prompts to save the certificate file and retain the $(hostname)_server.crt
file, which will need to be sent to the client later.
Run the interop_server_start
script to start the interop_server
service.
Once the server setup is complete, the client needs to connect:
Before the first run, obtain the $(hostname)_server.crt
file from the server and import it into the client. Trust the server's self-signed certificate to establish an SSL-encrypted channel between the client and server.
In the Python script, use the args
parameter to pass the server's IP address and the port on which the interop_server
is listening. Other script commands can be used as usual.
After usage, the server needs to be shut down:
Run the interop_server_stop
script to stop the interop_server
service.
Encrypted Connection Configuration
The above process establishes an SSL-encrypted connection by default. Users can choose whether to enable encryption based on their network environment:
In the Python script, the encrypted_connection
parameter controls whether SSL encryption is enabled, and the ca_certificate
parameter specifies the path to the CA certificate. Example code is as follows:
# Use encrypted connection and specify the CA certificate. The client will use both the system's CA certificates and the user-specified CA certificate.
args = {"hostname": "192.168.1.74", "port": 8088, "encrypted_connection": True, "ca_certificate": r"D:\windows\certs\name_server.crt"}
# Use encrypted connection without specifying a certificate. The client will use the system's CA certificates.
args = {"hostname": "192.168.1.74", "port": 8088}
# Or
args = {"hostname": "192.168.1.74", "port": 8088, "encrypted_connection": True}
# Do not use encrypted connection
args = {"hostname": "192.168.1.74", "port": 8088, "encrypted_connection": False}
import os
import sys
os.add_dll_directory(r"C:\Program Files\SimWorks\SimWorks FD Solutions\bin")
sys.path.append(r"C:\Program Files\SimWorks\SimWorks FD Solutions\api\python")
import simworks
import numpy as np
if __name__ == "__main__":
with simworks.FD() as fd:
# Add fdtd solver
fd.addfdtd()
fd.set("x",0)
fd.set("x span", 8e-6)
fd.set("y",0)
fd.set("y span",3e-6)
fd.set("z",0)
fd.set("z span",3e-6)
fd.set("boundary conditions x max","PML")
fd.set("boundary conditions x min","PML")
fd.set("boundary conditions y max","periodic")
fd.set("boundary conditions y min","periodic")
fd.set("boundary conditions z max","PML")
fd.set("boundary conditions z min","PML")
# Add rectangle structure
fd.addrect()
fd.set("x", 0)
fd.set("x span", 0.5e-6)
fd.set("y", 1e-6)
fd.set("y span", 2e-6)
fd.set("z", 0)
fd.set("z span", 2e-6)
# Set the material of rectangle
fd.set("material", "Ag (Silver)_CRC")
# Save project
fd.saveproject('F:\\pythondebug\\runfdtd.mpps')
# Source
fd.addplane()
fd.set('direction', 'Forward')
fd.set('incident axis', 'x')
fd.set('x', -2e-6)
fd.set('y', 0)
fd.set('y span', 6e-6)
fd.set('z', 0)
fd.set('z span', 6e-6)
fd.set('central wavelength', 1550e-9)
fd.set('wavelength span', 0)
# Monitor
fd.addpowermonitor()
fd.set("name", "T")
fd.set("spatial type", "2D X normal")
fd.set("x", 2e-6)
fd.set("y", 0)
fd.set("z", 0)
fd.set("y span", 6e-6)
fd.set("z span", 6e-6)
# Run FDTD
fd.run()
# Obtain the simulation results
Ex = fd.getdata("FDTD::T", "E", "Ex")
f = fd.getdata("FDTD::T", "E", "f")
sp = fd.getdata("FDTD::Plane", "sourcepower", "sourcepower")
print("done")
Data transfer between SimWorks and Python in the SimWorks interface is illustrated here. When launching the SimWorks Finite Difference Solutions using the Python API, a connection is established between the two environments. The workspaces are not shared. Instead, variables are transferred using an identical copy, with forward and backward transfers performed based on the conversion types defined in the getv() and putv() functions.
The SimWorks API supports the following data types: Real/Complex/String/Matrix/Struct/Cell/Dataset (matrixdataset and unstructureddataset). See the following code for detailed implementation:
import os
import sys
os.add_dll_directory(r"C:\Program Files\SimWorks\SimWorks FD Solutions\bin")
sys.path.append(r"C:\Program Files\SimWorks\SimWorks FD Solutions\api\python")
import simworks
import numpy as np
if __name__ == "__main__":
with simworks.Simworks('fd') as fd:
# Run the defined scripts in the SimWorks GUI
fd.eval("addpoly;")
# Generate various data types
fd.eval("str = 'test string content';")
fd.eval(f"mdmds = reshape({[str(i) + str(i + 1) for i in range(3*4*5)]}, [3, 4, 5]);")
fd.eval("mdc = [1+2j, 3+4j; 5+6j, 7+8j];")
fd.eval("C = {1, 2, 3; 'text', rand(5,10,2), {11; 22; 33} };")
fd.eval("E2=struct()")
fd.eval("E2.x=1;E2.y=2;E2.f=1.55e-6;E2.Ex=rand(5,5);")
# Generate the combination of allowed data types
fd.eval("{0} = struct;".format(field_result_name) +
"{0}.E = getdata('{1}','E');".format(field_result_name, monitor_name))
# Get variables from SimWorks FD Solutions
var_str = fd.getv("str")
var_mdmds = fd.getv("mdmds")
var_mdc = fd.getv("mdc")
var_cellA=fd.getv("C")
var_E=fd.getv("E2")
# Put variables from Python back to SimWorks FD Solutions
fd.putv("num", np.array([12, 13]))
fd.putv("putcomplex_np_mat", np.array([[1 + 2j, 3 + 4j], [5 + 6j, 7 + 8j]]))
fd.putv("put_mdmdr", np.arange(3 * 4 * 5).reshape([3, 4, 5]))
fd.putv("putstrmat", np.array([["123", "45678", "6789"], ['9101112', '13141516171819', '1457']], order='F'))
fd.putv("putemptystrmat", np.array([], dtype=np.str_))
fd.putv("putcell",var_cellA)
fd.putv("putstruct",var_E)
fd.savematlabmatfile('Y:\\pythondebug\\struct.mat')
print("done")