Skip to content

Commit 95b3e3e

Browse files
weiQingengWei
authored andcommitted
add batch id
1 parent 994bdc2 commit 95b3e3e

File tree

7 files changed

+110
-17
lines changed

7 files changed

+110
-17
lines changed

tests/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ Inside `dir/test_code.py` pytest will run any code in the main file and then cal
1717

1818
# gets evaluated first
1919
my_two = 2.0
20-
my_three = add_one(my_two)
20+
my_three = add_one(my_two)
21+
2122

2223
def add_one(x):
2324
# calls this function

tidy3d/plugins/adjoint/web.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ def start(self) -> None:
281281
To monitor progress of the :class:`Job`, call :meth:`Job.monitor` after started.
282282
"""
283283
if self.jax_info is not None:
284-
upload_jax_info(task_id=self.task_id, jax_info=self.jax_info, verbose=self.verbose)
284+
upload_jax_info(task_id=self.task_id(), jax_info=self.jax_info, verbose=self.verbose)
285285
super().start()
286286

287287

tidy3d/web/api/autograd/autograd.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1167,7 +1167,6 @@ def _run_async_tidy3d_bwd(
11671167
_ = run_kwargs.pop("path_dir", None)
11681168
batch = Batch(simulations=simulations, **batch_init_kwargs)
11691169
td.log.info(f"running {batch.simulation_type} batch with '_run_async_tidy3d_bwd()'")
1170-
11711170
batch.start()
11721171
batch.monitor()
11731172

tidy3d/web/api/container.py

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@ def _check_path_dir(path: str) -> None:
4444
"""Make sure local output directory exists and create it if not."""
4545

4646
@staticmethod
47-
def _check_folder(folder_name: str) -> None:
47+
def _check_folder(folder_name: str) -> Folder:
4848
"""Make sure ``folder_name`` exists on the web UI and create it if not."""
49-
Folder.get(folder_name, create=True)
49+
return Folder.get(folder_name, create=True)
5050

5151

5252
class Job(WebContainer):
@@ -235,24 +235,24 @@ def run(self, path: str = DEFAULT_DATA_PATH) -> SimulationDataType:
235235
self.monitor()
236236
return self.load(path=path)
237237

238-
@cached_property
239-
def task_id(self) -> TaskId:
238+
def task_id(self, batch_id: str = None) -> TaskId:
240239
"""The task ID for this ``Job``. Uploads the ``Job`` if it hasn't already been uploaded."""
241240
if self.task_id_cached:
242241
return self.task_id_cached
243242
self._check_folder(self.folder_name)
244-
return self._upload()
243+
return self._upload(batch_id)
245244

246-
def _upload(self) -> TaskId:
245+
def _upload(self, batch_id: str) -> TaskId:
247246
"""Upload this job and return the task ID for handling."""
248247
# upload kwargs with all fields except task_id
249248
upload_kwargs = {key: getattr(self, key) for key in self._upload_fields}
249+
upload_kwargs["batch_id"] = batch_id
250250
task_id = web.upload(**upload_kwargs)
251251
return task_id
252252

253-
def upload(self) -> None:
253+
def upload(self, batch_id: str = None) -> None:
254254
"""Upload this ``Job``."""
255-
_ = self.task_id
255+
_ = self.task_id(batch_id)
256256

257257
def get_info(self) -> TaskInfo:
258258
"""Return information about a :class:`Job`.
@@ -370,7 +370,9 @@ def estimate_cost(self, verbose: bool = True) -> float:
370370
Cost is calculated assuming the simulation runs for
371371
the full ``run_time``. If early shut-off is triggered, the cost is adjusted proportionately.
372372
"""
373-
return web.estimate_cost(self.task_id, verbose=verbose, solver_version=self.solver_version)
373+
return web.estimate_cost(
374+
self.task_id(), verbose=verbose, solver_version=self.solver_version
375+
)
374376

375377
@staticmethod
376378
def _check_path_dir(path: str) -> None:
@@ -511,6 +513,18 @@ class Batch(WebContainer):
511513
description="Name of folder to store member of each batch on web UI.",
512514
)
513515

516+
batch_id: str = pd.Field(
517+
None,
518+
title="Batch Id",
519+
description="ID of batch to store member of each batch on web UI.",
520+
)
521+
522+
batch_name: str = pd.Field(
523+
"batch",
524+
title="Batch Name",
525+
description="Name of batch to store member of each batch on web UI.",
526+
)
527+
514528
verbose: bool = pd.Field(
515529
True, title="Verbose", description="Whether to print info messages and progressbars."
516530
)
@@ -674,8 +688,15 @@ def num_jobs(self) -> int:
674688
def upload(self) -> None:
675689
"""Upload a series of tasks associated with this ``Batch`` using multi-threading."""
676690
self._check_folder(self.folder_name)
691+
batch_id = self.create_batch()
677692
with ThreadPoolExecutor(max_workers=self.num_workers) as executor:
678-
futures = [executor.submit(job.upload) for _, job in self.jobs.items()]
693+
futures = [
694+
executor.submit(
695+
job.upload,
696+
batch_id,
697+
)
698+
for _, job in self.jobs.items()
699+
]
679700

680701
# progressbar (number of tasks uploaded)
681702
if self.verbose:
@@ -711,6 +732,10 @@ def get_info(self) -> dict[TaskName, TaskInfo]:
711732
def start(self) -> None:
712733
"""Start running all tasks in the :class:`Batch`.
713734
735+
Parameters:
736+
batch_id: str
737+
Batch ID to start the tasks in.
738+
714739
Note
715740
----
716741
To monitor the running simulations, can call :meth:`Batch.monitor`.
@@ -1068,3 +1093,8 @@ def _check_path_dir(path_dir: str) -> None:
10681093
"""
10691094
if len(path_dir) > 0 and not os.path.exists(path_dir):
10701095
os.makedirs(path_dir, exist_ok=True)
1096+
1097+
def create_batch(self) -> str:
1098+
"""Create batch."""
1099+
folder = self._check_folder(self.folder_name)
1100+
return OptimizationBatch.create(self.batch_name, folder.folder_id)

tidy3d/web/api/webapi.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ def upload(
201201
source_required: bool = True,
202202
solver_version: Optional[str] = None,
203203
reduce_simulation: Literal["auto", True, False] = "auto",
204+
batch_id: str = None,
204205
) -> TaskId:
205206
"""
206207
Upload simulation to server, but do not start running :class:`.Simulation`.
@@ -230,7 +231,8 @@ def upload(
230231
target solver version.
231232
reduce_simulation: Literal["auto", True, False] = "auto"
232233
Whether to reduce structures in the simulation to the simulation domain only. Note: currently only implemented for the mode solver.
233-
234+
batch_id: str = None
235+
Batch id to upload tasks to.
234236
Returns
235237
-------
236238
str
@@ -260,7 +262,14 @@ def upload(
260262
task_type = stub.get_type()
261263

262264
task = SimulationTask.create(
263-
task_type, task_name, folder_name, callback_url, simulation_type, parent_tasks, "Gz"
265+
task_type,
266+
task_name,
267+
folder_name,
268+
callback_url,
269+
simulation_type,
270+
parent_tasks,
271+
"Gz",
272+
batch_id,
264273
)
265274
if verbose:
266275
console = get_logging_console()
@@ -385,6 +394,8 @@ def start(
385394
worker group
386395
pay_type: Union[PayType, str] = PayType.AUTO
387396
Which method to pay the simulation
397+
batch_id: str
398+
batch id
388399
Note
389400
----
390401
To monitor progress, can call :meth:`monitor` after starting simulation.

tidy3d/web/core/task_core.py

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
from .http_util import http
2525
from .s3utils import download_file, download_gz_file, upload_file
2626
from .stub import TaskStub
27-
from .types import PayType, Queryable, ResourceLifecycle, Submittable, Tidy3DResource
27+
from .types import OptimizationType, PayType, Queryable, ResourceLifecycle, Submittable, Tidy3DResource
2828

2929

3030
class Folder(Tidy3DResource, Queryable, extra=Extra.allow):
@@ -208,6 +208,7 @@ def create(
208208
simulation_type: str = "tidy3d",
209209
parent_tasks: Optional[list[str]] = None,
210210
file_type: str = "Gz",
211+
batch_id: str = None,
211212
) -> SimulationTask:
212213
"""Create a new task on the server.
213214
@@ -228,7 +229,8 @@ def create(
228229
List of related task ids.
229230
file_type: str
230231
the simulation file type Json, Hdf5, Gz
231-
232+
batch_id: str
233+
batch id
232234
Returns
233235
-------
234236
:class:`SimulationTask`
@@ -250,6 +252,7 @@ def create(
250252
"simulationType": simulation_type,
251253
"parentTasks": parent_tasks,
252254
"fileType": file_type,
255+
"batchId": batch_id,
253256
},
254257
)
255258
return SimulationTask(**resp, taskType=task_type, folder_name=folder_name)
@@ -671,3 +674,48 @@ def abort(self):
671674
return http.put(
672675
"tidy3d/tasks/abort", json={"taskType": self.task_type, "taskId": self.task_id}
673676
)
677+
678+
679+
class OptimizationBatch(ResourceLifecycle, extra=Extra.allow):
680+
"""OptimizationBatch."""
681+
682+
batch_id: Optional[str] = Field(
683+
...,
684+
title="batch_id",
685+
description="Batch ID number, set when the batch is uploaded, leave as None.",
686+
alias="optimizationId",
687+
)
688+
batch_name: Optional[str] = Field(
689+
None,
690+
title="batch_name",
691+
description="The name of batch, leave as None.",
692+
alias="optimizationName",
693+
)
694+
695+
@classmethod
696+
def create(cls, batch_name: str, folder_id: str) -> str:
697+
"""Create batch from server.
698+
699+
Parameters
700+
----------
701+
batch_name: str = None
702+
batch name.
703+
folder_id: str = None
704+
folder id.
705+
706+
Returns
707+
-------
708+
batch id: str
709+
710+
"""
711+
if folder_id is None:
712+
raise WebError("folder_id can't be None.")
713+
714+
resp = http.post(
715+
"tidy3d/optimization",
716+
json={"type": OptimizationType.BATCH.value, "name": batch_name, "folderId": folder_id},
717+
)
718+
return resp["optimizationId"]
719+
720+
def delete(self):
721+
return http.delete("tidy3d/optimization", json={"batch_id": self.batch_id})

tidy3d/web/core/types.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,7 @@ def _missing_(cls, value: object) -> PayType:
6767
if key in cls.__members__:
6868
return cls.__members__[key]
6969
return super()._missing_(value)
70+
71+
72+
class OptimizationType(str, Enum):
73+
BATCH = "BATCH"

0 commit comments

Comments
 (0)