Skip to content

Commit 0fee7a6

Browse files
committed
updating webapi
1 parent 2ce5542 commit 0fee7a6

File tree

16 files changed

+218
-787
lines changed

16 files changed

+218
-787
lines changed

.github/workflows/tidy3d-python-client-tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ jobs:
262262
BRANCH_NAME="${STEPS_EXTRACT_BRANCH_NAME_OUTPUTS_BRANCH_NAME}"
263263
echo $BRANCH_NAME
264264
# Allow only Jira keys from known projects, even if the branch has an author prefix
265-
ALLOWED_JIRA_PROJECTS=("FXC" "SCEM")
265+
ALLOWED_JIRA_PROJECTS=("FXC" "SCEM" "SCRF")
266266
JIRA_PROJECT_PATTERN=$(IFS='|'; echo "${ALLOWED_JIRA_PROJECTS[*]}")
267267
JIRA_PATTERN="(${JIRA_PROJECT_PATTERN})-[0-9]+"
268268

docs/api/submit_simulations.rst

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,6 @@ Information Containers
9494
:template: module.rst
9595

9696
tidy3d.web.core.task_info.TaskInfo
97-
tidy3d.web.core.task_info.TaskStatus
9897

9998

10099
Mode Solver Web API

docs/notebooks

Submodule notebooks updated 85 files

tidy3d/components/mode/mode_solver.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2655,7 +2655,7 @@ def _validate_modes_size(self) -> None:
26552655
"frequencies or modes."
26562656
)
26572657

2658-
def validate_pre_upload(self, source_required: bool = True) -> None:
2658+
def validate_pre_upload(self) -> None:
26592659
"""Validate the fully initialized mode solver is ok for upload to our servers."""
26602660
self._validate_modes_size()
26612661

tidy3d/components/mode/simulation.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -612,8 +612,8 @@ def plot_pml_mode_plane(
612612
"""
613613
return self._mode_solver.plot_pml(ax=ax)
614614

615-
def validate_pre_upload(self, source_required: bool = False) -> None:
615+
def validate_pre_upload(self) -> None:
616616
super().validate_pre_upload()
617-
self._mode_solver.validate_pre_upload(source_required=source_required)
617+
self._mode_solver.validate_pre_upload()
618618

619619
_boundaries_for_zero_dims = validate_boundaries_for_zero_dims(warn_on_change=False)

tidy3d/plugins/smatrix/component_modelers/base.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,5 +343,9 @@ def run(
343343
)
344344
return data.smatrix()
345345

346+
def validate_pre_upload(self):
347+
"""Validate the modeler before upload."""
348+
self.base_sim.validate_pre_upload(source_required=False)
349+
346350

347351
AbstractComponentModeler.update_forward_refs()

tidy3d/plugins/smatrix/component_modelers/modal.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,11 @@ class ModalComponentModeler(AbstractComponentModeler):
5959
"by ``element_mappings``, the simulation corresponding to this column is skipped automatically.",
6060
)
6161

62+
@property
63+
def base_sim(self):
64+
"""The base simulation."""
65+
return self.simulation
66+
6267
@cached_property
6368
def sim_dict(self) -> SimulationMap:
6469
"""Generates all :class:`.Simulation` objects for the S-matrix calculation.

tidy3d/plugins/smatrix/component_modelers/terminal.py

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -223,15 +223,17 @@ def _warn_refactor_2_10(cls, values):
223223

224224
@property
225225
def _sim_with_sources(self) -> Simulation:
226-
"""Instance of :class:`.Simulation` with all sources and absorbers added for each port, for troubleshooting."""
226+
"""Instance of :class:`.Simulation` with all sources and absorbers added for each port, for plotting."""
227227

228228
sources = [port.to_source(self._source_time) for port in self.ports]
229229
absorbers = [
230230
port.to_absorber()
231231
for port in self.ports
232232
if isinstance(port, WavePort) and port.absorber
233233
]
234-
return self.simulation.updated_copy(sources=sources, internal_absorbers=absorbers)
234+
return self.simulation.updated_copy(
235+
sources=sources, internal_absorbers=absorbers, validate=False
236+
)
235237

236238
@equal_aspect
237239
@add_ax_if_none
@@ -382,18 +384,17 @@ def matrix_indices_run_sim(self) -> tuple[NetworkIndex, ...]:
382384
def sim_dict(self) -> SimulationMap:
383385
"""Generate all the :class:`.Simulation` objects for the port parameter calculation."""
384386

387+
# Check base simulation for grid size at ports
388+
TerminalComponentModeler._check_grid_size_at_ports(self.base_sim, self._lumped_ports)
389+
TerminalComponentModeler._check_grid_size_at_wave_ports(self.base_sim, self._wave_ports)
390+
385391
sim_dict = {}
386392
# Now, create simulations with wave port sources and mode solver monitors for computing port modes
387393
for network_index in self.matrix_indices_run_sim:
388394
task_name, sim_with_src = self._add_source_to_sim(network_index)
389395
# update simulation
390396
sim_dict[task_name] = sim_with_src
391397

392-
# Check final simulations for grid size at ports
393-
for _, sim in sim_dict.items():
394-
TerminalComponentModeler._check_grid_size_at_ports(sim, self._lumped_ports)
395-
TerminalComponentModeler._check_grid_size_at_wave_ports(sim, self._wave_ports)
396-
397398
return SimulationMap(keys=tuple(sim_dict.keys()), values=tuple(sim_dict.values()))
398399

399400
@cached_property
@@ -414,7 +415,10 @@ def _base_sim_no_radiation_monitors(self) -> Simulation:
414415

415416
# Make an initial simulation with new grid_spec to determine where LumpedPorts are snapped
416417
sim_wo_source = self.simulation.updated_copy(
417-
grid_spec=grid_spec, lumped_elements=lumped_resistors
418+
grid_spec=grid_spec,
419+
lumped_elements=lumped_resistors,
420+
validate=False,
421+
deep=False,
418422
)
419423
snap_centers = {}
420424
for port in self._lumped_ports:
@@ -480,7 +484,11 @@ def _base_sim_no_radiation_monitors(self) -> Simulation:
480484
)
481485

482486
# update base simulation with updated set of shared components
483-
sim_wo_source = sim_wo_source.copy(update=update_dict)
487+
sim_wo_source = sim_wo_source.updated_copy(
488+
**update_dict,
489+
validate=False,
490+
deep=False,
491+
)
484492

485493
# extrude port structures
486494
sim_wo_source = self._extrude_port_structures(sim=sim_wo_source)
@@ -527,7 +535,9 @@ def base_sim(self) -> Simulation:
527535
"""The base simulation with all components added, including radiation monitors."""
528536
base_sim_tmp = self._base_sim_no_radiation_monitors
529537
mnts_with_radiation = list(base_sim_tmp.monitors) + list(self._finalized_radiation_monitors)
530-
return base_sim_tmp.updated_copy(monitors=mnts_with_radiation)
538+
grid_spec = GridSpec.from_grid(base_sim_tmp.grid)
539+
# We skipped validations up to now, here we finally validate the base sim
540+
return base_sim_tmp.updated_copy(monitors=mnts_with_radiation, grid_spec=grid_spec)
531541

532542
def _generate_radiation_monitor(
533543
self, simulation: Simulation, auto_spec: DirectivityMonitorSpec
@@ -712,7 +722,10 @@ def _add_source_to_sim(self, source_index: NetworkIndex) -> tuple[str, Simulatio
712722
)
713723
task_name = self.get_task_name(port=port, mode_index=mode_index)
714724

715-
return (task_name, self.base_sim.updated_copy(sources=[port_source]))
725+
return (
726+
task_name,
727+
self.base_sim.updated_copy(sources=[port_source], validate=False, deep=False),
728+
)
716729

717730
@cached_property
718731
def _source_time(self):
@@ -958,6 +971,8 @@ def _extrude_port_structures(self, sim: Simulation) -> Simulation:
958971
sim = sim.updated_copy(
959972
grid_spec=GridSpec.from_grid(sim.grid),
960973
structures=[*sim.structures, *all_new_structures],
974+
validate=False,
975+
deep=False,
961976
)
962977

963978
return sim

tidy3d/web/__init__.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
load,
3131
load_simulation,
3232
monitor,
33-
postprocess_start,
3433
real_cost,
3534
start,
3635
test,
@@ -58,7 +57,6 @@
5857
"load",
5958
"load_simulation",
6059
"monitor",
61-
"postprocess_start",
6260
"real_cost",
6361
"run",
6462
"run_async",

tidy3d/web/api/container.py

Lines changed: 3 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -389,25 +389,7 @@ def status(self) -> str:
389389
"""Return current status of :class:`Job`."""
390390
if self.load_if_cached:
391391
return "success"
392-
if web._is_modeler_batch(self.task_id):
393-
detail = self.get_info()
394-
status = detail.totalStatus.value
395-
return status
396-
else:
397-
return self.get_info().status
398-
399-
@property
400-
def postprocess_status(self) -> Optional[str]:
401-
"""Return current postprocess status of :class:`Job` if it is a Component Modeler."""
402-
if web._is_modeler_batch(self.task_id):
403-
detail = self.get_info()
404-
return detail.postprocessStatus
405-
else:
406-
log.warning(
407-
f"Task ID '{self.task_id}' is not a modeler batch job. "
408-
"'postprocess_start' is only applicable to Component Modelers"
409-
)
410-
return
392+
return self.get_info().status
411393

412394
def start(self, priority: Optional[int] = None) -> None:
413395
"""Start running a :class:`Job`.
@@ -548,37 +530,6 @@ def estimate_cost(self, verbose: bool = True) -> float:
548530
return 0.0
549531
return web.estimate_cost(self.task_id, verbose=verbose, solver_version=self.solver_version)
550532

551-
def postprocess_start(self, worker_group: Optional[str] = None, verbose: bool = True) -> None:
552-
"""
553-
If the job is a modeler batch, checks if the run is complete and starts
554-
the postprocess phase.
555-
556-
This function does not wait for postprocessing to finish and is only
557-
applicable to Component Modeler batch jobs.
558-
559-
Parameters
560-
----------
561-
worker_group : Optional[str] = None
562-
The specific worker group to run the postprocessing task on.
563-
verbose : bool = True
564-
Whether to print info messages. This overrides the Job's 'verbose' setting for this call.
565-
"""
566-
# First, confirm that the task is a modeler batch job.
567-
if not web._is_modeler_batch(self.task_id):
568-
# If not, inform the user and exit.
569-
# This warning is important and should not be suppressed.
570-
log.warning(
571-
f"Task ID '{self.task_id}' is not a modeler batch job. "
572-
"'postprocess_start' is only applicable to Component Modelers"
573-
)
574-
return
575-
576-
# If it is a modeler batch, call the dedicated function to start postprocessing.
577-
# The verbosity is a combination of the job's setting and the method's parameter.
578-
web.postprocess_start(
579-
batch_id=self.task_id, verbose=(self.verbose and verbose), worker_group=worker_group
580-
)
581-
582533
@staticmethod
583534
def _check_path_dir(path: PathLike) -> None:
584535
"""Make sure parent directory of ``path`` exists and create it if not.
@@ -1043,21 +994,6 @@ def get_run_info(self) -> dict[TaskName, RunInfo]:
1043994
run_info_dict[task_name] = run_info
1044995
return run_info_dict
1045996

1046-
def postprocess_start(self, worker_group: Optional[str] = None, verbose: bool = True) -> None:
1047-
"""
1048-
Start the postprocess phase for all applicable jobs in the batch.
1049-
1050-
This simply forwards to each Job's `postprocess_start(...)`. The Job decides
1051-
whether it's a Component Modeler task and whether it can/should start now.
1052-
This method does not wait for postprocessing to finish.
1053-
"""
1054-
if self.verbose and verbose:
1055-
console = get_logging_console()
1056-
console.log("Attempting to start postprocessing for jobs in the batch.")
1057-
1058-
for job in self.jobs.values():
1059-
job.postprocess_start(worker_group=worker_group, verbose=verbose)
1060-
1061997
def monitor(
1062998
self,
1063999
*,
@@ -1069,7 +1005,6 @@ def monitor(
10691005
"""
10701006
Monitor progress of each running task.
10711007
1072-
- For Component Modeler jobs, automatically triggers postprocessing once run finishes.
10731008
- Optionally downloads results as soon as a job reaches final success.
10741009
- Rich progress bars in verbose mode; quiet polling otherwise.
10751010
@@ -1095,16 +1030,8 @@ def monitor(
10951030
self._check_path_dir(path_dir=path_dir)
10961031
download_executor = ThreadPoolExecutor(max_workers=self.num_workers)
10971032

1098-
def _should_download(job: Job) -> bool:
1099-
status = job.status
1100-
if not web._is_modeler_batch(job.task_id):
1101-
return status == "success"
1102-
if status == "success":
1103-
return True
1104-
return status == "run_success" and getattr(job, "postprocess_status", None) == "success"
1105-
11061033
def schedule_download(job: Job) -> None:
1107-
if download_executor is None or not _should_download(job):
1034+
if download_executor is None or job.status not in COMPLETED_STATES:
11081035
return
11091036
task_id = job.task_id
11101037
if task_id in downloads_started:
@@ -1128,12 +1055,7 @@ def schedule_download(job: Job) -> None:
11281055
def check_continue_condition(job: Job) -> bool:
11291056
if job.load_if_cached:
11301057
return False
1131-
status = job.status
1132-
if not web._is_modeler_batch(job.task_id):
1133-
return status not in END_STATES
1134-
if status == "run_success":
1135-
return job.postprocess_status not in END_STATES
1136-
return status not in END_STATES
1058+
return job.status not in END_STATES
11371059

11381060
def pbar_description(
11391061
task_name: str, status: str, max_name_length: int, status_width: int
@@ -1157,9 +1079,6 @@ def pbar_description(
11571079
max_task_name = max(len(task_name) for task_name in self.jobs.keys())
11581080
max_name_length = min(30, max(max_task_name, 15))
11591081

1160-
# track which modeler jobs we've already kicked into postprocess
1161-
postprocess_started_tasks: set[str] = set()
1162-
11631082
try:
11641083
console = None
11651084
progress_columns = []
@@ -1195,17 +1114,6 @@ def pbar_description(
11951114
for task_name, job in self.jobs.items():
11961115
status = job.status
11971116

1198-
# auto-start postprocess for modeler jobs when run finishes
1199-
if (
1200-
web._is_modeler_batch(job.task_id)
1201-
and status == "run_success"
1202-
and job.task_id not in postprocess_started_tasks
1203-
):
1204-
job.postprocess_start(
1205-
worker_group=postprocess_worker_group, verbose=True
1206-
)
1207-
postprocess_started_tasks.add(job.task_id)
1208-
12091117
schedule_download(job)
12101118

12111119
if self.verbose:

0 commit comments

Comments
 (0)