Evaluate value and/or gradient of objective function. Args: rho_vector: list of design weights (which is itself a list). Each list in the list represents the design weights for one design region. The design weights are updated to the specified values.
(
self,
rho_vector: List[List[float]] = None,
need_value: bool = True,
need_gradient: bool = True,
beta: float = None,
)
| 157 | self.gradient = [] |
| 158 | |
| 159 | def __call__( |
| 160 | self, |
| 161 | rho_vector: List[List[float]] = None, |
| 162 | need_value: bool = True, |
| 163 | need_gradient: bool = True, |
| 164 | beta: float = None, |
| 165 | ) -> Tuple[List[np.ndarray], List[List[np.ndarray]]]: |
| 166 | """Evaluate value and/or gradient of objective function. |
| 167 | |
| 168 | Args: |
| 169 | rho_vector: list of design weights (which is itself a list). Each |
| 170 | list in the list represents the design weights for one design |
| 171 | region. The design weights are updated to the specified values. |
| 172 | The objective functions and their gradients are then evaluated |
| 173 | using these design weights. |
| 174 | need_value: whether forward simulations for evaluating the objective |
| 175 | functions are necessary. Default is True. |
| 176 | need_gradient: whether adjoint simulations for evaluating the |
| 177 | gradients are necessary. Default is True. |
| 178 | beta: the strength (or "bias") of projecting the design weights in |
| 179 | rho_vector using a hyperbolic tangent function. Default is None. |
| 180 | |
| 181 | Returns: |
| 182 | A 2-tuple (f0, gradient) for which: |
| 183 | f0 is the list of values of the objective functions. |
| 184 | gradient is a list (over objective functions) of lists (over design |
| 185 | regions) of 2d arrays (design weights by frequencies) of |
| 186 | derivatives. If there is only a single objective function, the |
| 187 | outer 1-element list is replaced by just that element, and |
| 188 | similarly if there is only one design region then those 1-element |
| 189 | list are replaced by just those elements. In addition, if there is |
| 190 | only one frequency then the innermost array is squeezed to a 1d |
| 191 | array. For example, if there is only a single objective function, |
| 192 | a single design region, and a single frequency, then gradient is |
| 193 | simply a 1d array of the derivatives. |
| 194 | """ |
| 195 | if rho_vector: |
| 196 | self.update_design(rho_vector=rho_vector, beta=beta) |
| 197 | |
| 198 | # Run forward run if requested |
| 199 | if need_value and self.current_state == "INIT": |
| 200 | print("Starting forward run...") |
| 201 | self.forward_run() |
| 202 | |
| 203 | # Run adjoint simulation and calculate gradient if requested |
| 204 | if need_gradient: |
| 205 | if self.current_state == "INIT": |
| 206 | # we need to run a forward run before an adjoint run |
| 207 | print("Starting forward run...") |
| 208 | self.forward_run() |
| 209 | print("Starting adjoint run...") |
| 210 | self.adjoint_run() |
| 211 | print("Calculating gradient...") |
| 212 | self.calculate_gradient() |
| 213 | elif self.current_state == "FWD": |
| 214 | print("Starting adjoint run...") |
| 215 | self.adjoint_run() |
| 216 | print("Calculating gradient...") |
no test coverage detected