Add more test cases #228
GitHub Actions / Test Results
failed
Aug 11, 2023 in 0s
2 fail, 16 skipped, 475 pass in 2m 25s
Annotations
Check warning on line 0 in tests.api.test_energy_model_optimization
github-actions / Test Results
test_optimize_model[1node_Example] (tests.api.test_energy_model_optimization) failed
result.xml [took 3s]
Raw output
TypeError: At least one solver must be installed. Have a look at the FINE documentation to see how to install possible solvers. https://vsa-fine.readthedocs.io/en/latest/
client = <starlette.testclient.TestClient object at 0x7ff582dfd3c0>
normal_user_headers = {'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2OTI0NDg1NzgsInN1YiI6IjEifQ.dzGB81rDfKN5LWyxbvHhosqhFGdvZ-V3BS5BdnfB8Js'}
db = <sqlalchemy.orm.session.Session object at 0x7ff58064c3d0>
data_folder = '1node_Example'
@pytest.mark.slow
@pytest.mark.parametrize("data_folder", ["1node_Example", "Multi-regional_Example"])
def test_optimize_model(client: TestClient, normal_user_headers: Dict[str, str], db: Session, data_folder: str):
"""
Test optimizing an energy model.
"""
example_model = data_generator.create_example_model(db, data_folder)
> response = client.get(f"/models/{example_model.id}/optimize/", headers=normal_user_headers)
tests/api/test_energy_model_optimization.py:18:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/starlette/testclient.py:499: in get
return super().get(
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/httpx/_client.py:1041: in get
return self.request(
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/starlette/testclient.py:465: in request
return super().request(
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/httpx/_client.py:814: in request
return self.send(request, auth=auth, follow_redirects=follow_redirects)
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/httpx/_client.py:901: in send
response = self._send_handling_auth(
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/httpx/_client.py:929: in _send_handling_auth
response = self._send_handling_redirects(
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/httpx/_client.py:966: in _send_handling_redirects
response = self._send_single_request(request)
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/httpx/_client.py:1002: in _send_single_request
response = transport.handle_request(request)
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/starlette/testclient.py:342: in handle_request
raise exc
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/starlette/testclient.py:339: in handle_request
portal.call(self.app, scope, receive, send)
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/anyio/from_thread.py:277: in call
return cast(T_Retval, self.start_task_soon(func, *args).result())
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/concurrent/futures/_base.py:458: in result
return self.__get_result()
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/concurrent/futures/_base.py:403: in __get_result
raise self._exception
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/anyio/from_thread.py:217: in _call_func
retval = await retval
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/fastapi/applications.py:289: in __call__
await super().__call__(scope, receive, send)
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/starlette/applications.py:122: in __call__
await self.middleware_stack(scope, receive, send)
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/starlette/middleware/errors.py:184: in __call__
raise exc
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/starlette/middleware/errors.py:162: in __call__
await self.app(scope, receive, _send)
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/starlette/middleware/exceptions.py:79: in __call__
raise exc
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/starlette/middleware/exceptions.py:68: in __call__
await self.app(scope, receive, sender)
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/fastapi/middleware/asyncexitstack.py:20: in __call__
raise e
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/fastapi/middleware/asyncexitstack.py:17: in __call__
await self.app(scope, receive, send)
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/starlette/routing.py:718: in __call__
await route.handle(scope, receive, send)
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/starlette/routing.py:276: in handle
await self.app(scope, receive, send)
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/starlette/routing.py:66: in app
response = await func(request)
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/fastapi/routing.py:273: in app
raw_response = await run_endpoint_function(
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/fastapi/routing.py:192: in run_endpoint_function
return await run_in_threadpool(dependant.call, **values)
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/starlette/concurrency.py:41: in run_in_threadpool
return await anyio.to_thread.run_sync(func, *args)
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/anyio/to_thread.py:33: in run_sync
return await get_asynclib().run_sync_in_worker_thread(
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/anyio/_backends/_asyncio.py:877: in run_sync_in_worker_thread
return await future
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/anyio/_backends/_asyncio.py:807: in run
result = context.run(func, *args)
ensysmod/api/endpoints/energy_models.py:131: in optimize_model
result_file_path = optimize_esm(esM=esM)
ensysmod/core/fine_esm.py:215: in optimize_esm
esM.optimize(timeSeriesAggregation=True)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <FINE.energySystemModel.EnergySystemModel object at 0x7ff582fc31c0>
declaresOptimizationProblem = True, relaxIsBuiltBinary = False
timeSeriesAggregation = True, logFileName = '', threads = 3, solver = 'None'
timeLimit = None, optimizationSpecs = '', warmstart = False
def optimize(
self,
declaresOptimizationProblem=True,
relaxIsBuiltBinary=False,
timeSeriesAggregation=False,
logFileName="",
threads=3,
solver="None",
timeLimit=None,
optimizationSpecs="",
warmstart=False,
):
"""
Optimize the specified energy system for which a pyomo ConcreteModel instance is built or called upon.
A pyomo instance is optimized with the specified inputs, and the optimization results are further
processed.
**Default arguments:**
:param declaresOptimizationProblem: states if the optimization problem should be declared (True) or not (False).
(a) If true, the declareOptimizationProblem function is called and a pyomo ConcreteModel instance is built.
(b) If false a previously declared pyomo ConcreteModel instance is used.
|br| * the default value is True
:type declaresOptimizationProblem: boolean
:param relaxIsBuiltBinary: states if the optimization problem should be solved as a relaxed LP to get the lower
bound of the problem.
|br| * the default value is False
:type declaresOptimizationProblem: boolean
:param timeSeriesAggregation: states if the optimization of the energy system model should be done with
(a) the full time series (False) or
(b) clustered time series data (True).
|br| * the default value is False
:type timeSeriesAggregation: boolean
:param segmentation: states if the optimization of the energy system model based on clustered time series data
should be done with
(a) aggregated typical periods with the original time step length (False) or
(b) aggregated typical periods with further segmented time steps (True).
|br| * the default value is False
:type segmentation: boolean
:param logFileName: logFileName is used for naming the log file of the optimization solver output
if gurobi is used as the optimization solver.
If the logFileName is given as an absolute path (e.g. logFileName = os.path.join(os.getcwd(),
'Results', 'logFileName.txt')) the log file will be stored in the specified directory. Otherwise,
it will be stored by default in the directory where the executing python script is called.
|br| * the default value is 'job'
:type logFileName: string
:param threads: number of computational threads used for solving the optimization (solver dependent
input) if gurobi is used as the solver. A value of 0 results in using all available threads. If
a value larger than the available number of threads are chosen, the value will reset to the maximum
number of threads.
|br| * the default value is 3
:type threads: positive integer
:param solver: specifies which solver should solve the optimization problem (which of course has to be
installed on the machine on which the model is run).
|br| * the default value is 'gurobi'
:type solver: string
:param timeLimit: if not specified as None, indicates the maximum solve time of the optimization problem
in seconds (solver dependent input). The use of this parameter is suggested when running models in
runtime restricted environments (such as clusters with job submission systems). If the runtime
limitation is triggered before an optimal solution is available, the best solution obtained up
until then (if available) is processed.
|br| * the default value is None
:type timeLimit: strictly positive integer or None
:param optimizationSpecs: specifies parameters for the optimization solver (see the respective solver
documentation for more information). Example: 'LogToConsole=1 OptimalityTol=1e-6'
|br| * the default value is an empty string ('')
:type optimizationSpecs: string
:param warmstart: specifies if a warm start of the optimization should be considered
(not always supported by the solvers).
|br| * the default value is False
:type warmstart: boolean
"""
if not timeSeriesAggregation:
self.segmentation = False
if declaresOptimizationProblem:
self.declareOptimizationProblem(
timeSeriesAggregation=timeSeriesAggregation,
segmentation=self.segmentation,
relaxIsBuiltBinary=relaxIsBuiltBinary,
)
else:
if self.pyM is None:
raise TypeError(
"The optimization problem is not declared yet. Set the argument declaresOptimization"
" problem to True or call the declareOptimizationProblem function first."
)
# Get starting time of the optimization to, later on, obtain the total run time of the optimize function call
timeStart = time.time()
# Check correctness of inputs
utils.checkOptimizeInput(
timeSeriesAggregation,
self.isTimeSeriesDataClustered,
logFileName,
threads,
solver,
timeLimit,
optimizationSpecs,
warmstart,
)
# Store keyword arguments in the EnergySystemModel instance
self.solverSpecs["logFileName"], self.solverSpecs["threads"] = (
logFileName,
threads,
)
self.solverSpecs["solver"], self.solverSpecs["timeLimit"] = solver, timeLimit
self.solverSpecs["optimizationSpecs"], self.solverSpecs["hasTSA"] = (
optimizationSpecs,
timeSeriesAggregation,
)
# Check which solvers are available and choose default solver if no solver is specified explicitely
# Order of possible solvers in solverList defines the priority of chosen default solver.
solverList = ["gurobi", "glpk", "cbc"]
if solver != "None":
try:
opt.SolverFactory(solver).available()
except:
solver = "None"
if solver == "None":
for nSolver in solverList:
if solver == "None":
try:
if opt.SolverFactory(nSolver).available():
solver = nSolver
utils.output(
"Either solver not selected or specified solver not available."
+ str(nSolver)
+ " is set as solver.",
self.verbose,
0,
)
except:
pass
if solver == "None":
> raise TypeError(
"At least one solver must be installed."
" Have a look at the FINE documentation to see how to install possible solvers."
" https://vsa-fine.readthedocs.io/en/latest/"
)
E TypeError: At least one solver must be installed. Have a look at the FINE documentation to see how to install possible solvers. https://vsa-fine.readthedocs.io/en/latest/
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/FINE/energySystemModel.py:1602: TypeError
Check warning on line 0 in tests.api.test_energy_model_optimization
github-actions / Test Results
test_optimize_model[Multi-regional_Example] (tests.api.test_energy_model_optimization) failed
result.xml [took 31s]
Raw output
TypeError: At least one solver must be installed. Have a look at the FINE documentation to see how to install possible solvers. https://vsa-fine.readthedocs.io/en/latest/
client = <starlette.testclient.TestClient object at 0x7ff582dfd3c0>
normal_user_headers = {'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2OTI0NDg1NzgsInN1YiI6IjEifQ.dzGB81rDfKN5LWyxbvHhosqhFGdvZ-V3BS5BdnfB8Js'}
db = <sqlalchemy.orm.session.Session object at 0x7ff582915b10>
data_folder = 'Multi-regional_Example'
@pytest.mark.slow
@pytest.mark.parametrize("data_folder", ["1node_Example", "Multi-regional_Example"])
def test_optimize_model(client: TestClient, normal_user_headers: Dict[str, str], db: Session, data_folder: str):
"""
Test optimizing an energy model.
"""
example_model = data_generator.create_example_model(db, data_folder)
> response = client.get(f"/models/{example_model.id}/optimize/", headers=normal_user_headers)
tests/api/test_energy_model_optimization.py:18:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/starlette/testclient.py:499: in get
return super().get(
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/httpx/_client.py:1041: in get
return self.request(
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/starlette/testclient.py:465: in request
return super().request(
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/httpx/_client.py:814: in request
return self.send(request, auth=auth, follow_redirects=follow_redirects)
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/httpx/_client.py:901: in send
response = self._send_handling_auth(
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/httpx/_client.py:929: in _send_handling_auth
response = self._send_handling_redirects(
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/httpx/_client.py:966: in _send_handling_redirects
response = self._send_single_request(request)
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/httpx/_client.py:1002: in _send_single_request
response = transport.handle_request(request)
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/starlette/testclient.py:342: in handle_request
raise exc
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/starlette/testclient.py:339: in handle_request
portal.call(self.app, scope, receive, send)
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/anyio/from_thread.py:277: in call
return cast(T_Retval, self.start_task_soon(func, *args).result())
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/concurrent/futures/_base.py:458: in result
return self.__get_result()
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/concurrent/futures/_base.py:403: in __get_result
raise self._exception
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/anyio/from_thread.py:217: in _call_func
retval = await retval
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/fastapi/applications.py:289: in __call__
await super().__call__(scope, receive, send)
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/starlette/applications.py:122: in __call__
await self.middleware_stack(scope, receive, send)
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/starlette/middleware/errors.py:184: in __call__
raise exc
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/starlette/middleware/errors.py:162: in __call__
await self.app(scope, receive, _send)
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/starlette/middleware/exceptions.py:79: in __call__
raise exc
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/starlette/middleware/exceptions.py:68: in __call__
await self.app(scope, receive, sender)
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/fastapi/middleware/asyncexitstack.py:20: in __call__
raise e
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/fastapi/middleware/asyncexitstack.py:17: in __call__
await self.app(scope, receive, send)
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/starlette/routing.py:718: in __call__
await route.handle(scope, receive, send)
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/starlette/routing.py:276: in handle
await self.app(scope, receive, send)
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/starlette/routing.py:66: in app
response = await func(request)
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/fastapi/routing.py:273: in app
raw_response = await run_endpoint_function(
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/fastapi/routing.py:192: in run_endpoint_function
return await run_in_threadpool(dependant.call, **values)
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/starlette/concurrency.py:41: in run_in_threadpool
return await anyio.to_thread.run_sync(func, *args)
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/anyio/to_thread.py:33: in run_sync
return await get_asynclib().run_sync_in_worker_thread(
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/anyio/_backends/_asyncio.py:877: in run_sync_in_worker_thread
return await future
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/anyio/_backends/_asyncio.py:807: in run
result = context.run(func, *args)
ensysmod/api/endpoints/energy_models.py:131: in optimize_model
result_file_path = optimize_esm(esM=esM)
ensysmod/core/fine_esm.py:215: in optimize_esm
esM.optimize(timeSeriesAggregation=True)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <FINE.energySystemModel.EnergySystemModel object at 0x7ff580f19690>
declaresOptimizationProblem = True, relaxIsBuiltBinary = False
timeSeriesAggregation = True, logFileName = '', threads = 3, solver = 'None'
timeLimit = None, optimizationSpecs = '', warmstart = False
def optimize(
self,
declaresOptimizationProblem=True,
relaxIsBuiltBinary=False,
timeSeriesAggregation=False,
logFileName="",
threads=3,
solver="None",
timeLimit=None,
optimizationSpecs="",
warmstart=False,
):
"""
Optimize the specified energy system for which a pyomo ConcreteModel instance is built or called upon.
A pyomo instance is optimized with the specified inputs, and the optimization results are further
processed.
**Default arguments:**
:param declaresOptimizationProblem: states if the optimization problem should be declared (True) or not (False).
(a) If true, the declareOptimizationProblem function is called and a pyomo ConcreteModel instance is built.
(b) If false a previously declared pyomo ConcreteModel instance is used.
|br| * the default value is True
:type declaresOptimizationProblem: boolean
:param relaxIsBuiltBinary: states if the optimization problem should be solved as a relaxed LP to get the lower
bound of the problem.
|br| * the default value is False
:type declaresOptimizationProblem: boolean
:param timeSeriesAggregation: states if the optimization of the energy system model should be done with
(a) the full time series (False) or
(b) clustered time series data (True).
|br| * the default value is False
:type timeSeriesAggregation: boolean
:param segmentation: states if the optimization of the energy system model based on clustered time series data
should be done with
(a) aggregated typical periods with the original time step length (False) or
(b) aggregated typical periods with further segmented time steps (True).
|br| * the default value is False
:type segmentation: boolean
:param logFileName: logFileName is used for naming the log file of the optimization solver output
if gurobi is used as the optimization solver.
If the logFileName is given as an absolute path (e.g. logFileName = os.path.join(os.getcwd(),
'Results', 'logFileName.txt')) the log file will be stored in the specified directory. Otherwise,
it will be stored by default in the directory where the executing python script is called.
|br| * the default value is 'job'
:type logFileName: string
:param threads: number of computational threads used for solving the optimization (solver dependent
input) if gurobi is used as the solver. A value of 0 results in using all available threads. If
a value larger than the available number of threads are chosen, the value will reset to the maximum
number of threads.
|br| * the default value is 3
:type threads: positive integer
:param solver: specifies which solver should solve the optimization problem (which of course has to be
installed on the machine on which the model is run).
|br| * the default value is 'gurobi'
:type solver: string
:param timeLimit: if not specified as None, indicates the maximum solve time of the optimization problem
in seconds (solver dependent input). The use of this parameter is suggested when running models in
runtime restricted environments (such as clusters with job submission systems). If the runtime
limitation is triggered before an optimal solution is available, the best solution obtained up
until then (if available) is processed.
|br| * the default value is None
:type timeLimit: strictly positive integer or None
:param optimizationSpecs: specifies parameters for the optimization solver (see the respective solver
documentation for more information). Example: 'LogToConsole=1 OptimalityTol=1e-6'
|br| * the default value is an empty string ('')
:type optimizationSpecs: string
:param warmstart: specifies if a warm start of the optimization should be considered
(not always supported by the solvers).
|br| * the default value is False
:type warmstart: boolean
"""
if not timeSeriesAggregation:
self.segmentation = False
if declaresOptimizationProblem:
self.declareOptimizationProblem(
timeSeriesAggregation=timeSeriesAggregation,
segmentation=self.segmentation,
relaxIsBuiltBinary=relaxIsBuiltBinary,
)
else:
if self.pyM is None:
raise TypeError(
"The optimization problem is not declared yet. Set the argument declaresOptimization"
" problem to True or call the declareOptimizationProblem function first."
)
# Get starting time of the optimization to, later on, obtain the total run time of the optimize function call
timeStart = time.time()
# Check correctness of inputs
utils.checkOptimizeInput(
timeSeriesAggregation,
self.isTimeSeriesDataClustered,
logFileName,
threads,
solver,
timeLimit,
optimizationSpecs,
warmstart,
)
# Store keyword arguments in the EnergySystemModel instance
self.solverSpecs["logFileName"], self.solverSpecs["threads"] = (
logFileName,
threads,
)
self.solverSpecs["solver"], self.solverSpecs["timeLimit"] = solver, timeLimit
self.solverSpecs["optimizationSpecs"], self.solverSpecs["hasTSA"] = (
optimizationSpecs,
timeSeriesAggregation,
)
# Check which solvers are available and choose default solver if no solver is specified explicitely
# Order of possible solvers in solverList defines the priority of chosen default solver.
solverList = ["gurobi", "glpk", "cbc"]
if solver != "None":
try:
opt.SolverFactory(solver).available()
except:
solver = "None"
if solver == "None":
for nSolver in solverList:
if solver == "None":
try:
if opt.SolverFactory(nSolver).available():
solver = nSolver
utils.output(
"Either solver not selected or specified solver not available."
+ str(nSolver)
+ " is set as solver.",
self.verbose,
0,
)
except:
pass
if solver == "None":
> raise TypeError(
"At least one solver must be installed."
" Have a look at the FINE documentation to see how to install possible solvers."
" https://vsa-fine.readthedocs.io/en/latest/"
)
E TypeError: At least one solver must be installed. Have a look at the FINE documentation to see how to install possible solvers. https://vsa-fine.readthedocs.io/en/latest/
/opt/hostedtoolcache/Python/3.10.12/x64/lib/python3.10/site-packages/FINE/energySystemModel.py:1602: TypeError
Loading