From 0bca877e06e42159aafa4ace3df0632d1dac45c8 Mon Sep 17 00:00:00 2001 From: Thomas Bellier Date: Sun, 9 Jul 2023 14:52:18 +1000 Subject: [PATCH] Initial commit not tested nor working --- .gitignore | 6 + lca4mdao/__init__.py | 1 + lca4mdao/database.py | 74 +++++++ lca4mdao/lca.py | 37 ++++ lca4mdao/main.py | 202 +++++++++++++++++++ lca4mdao/optimizer/__init__.py | 1 + lca4mdao/optimizer/pymoo_optimizer.py | 270 ++++++++++++++++++++++++++ lca4mdao/sellar.py | 194 ++++++++++++++++++ xdsm/Generic.py | 58 ++++++ xdsm/Generic_env.py | 55 ++++++ xdsm/Generic_env.tex | 27 +++ xdsm/Generic_env.tikz | 139 +++++++++++++ xdsm/Generic_normal.tex | 27 +++ xdsm/Generic_normal.tikz | 179 +++++++++++++++++ xdsm/Sellar.py | 41 ++++ xdsm/Sellar_env.tex | 27 +++ xdsm/Sellar_env.tikz | 126 ++++++++++++ xdsm/Sellar_normal.tex | 27 +++ xdsm/Sellar_normal.tikz | 105 ++++++++++ 19 files changed, 1596 insertions(+) create mode 100644 .gitignore create mode 100644 lca4mdao/__init__.py create mode 100644 lca4mdao/database.py create mode 100644 lca4mdao/lca.py create mode 100644 lca4mdao/main.py create mode 100644 lca4mdao/optimizer/__init__.py create mode 100644 lca4mdao/optimizer/pymoo_optimizer.py create mode 100644 lca4mdao/sellar.py create mode 100644 xdsm/Generic.py create mode 100644 xdsm/Generic_env.py create mode 100644 xdsm/Generic_env.tex create mode 100644 xdsm/Generic_env.tikz create mode 100644 xdsm/Generic_normal.tex create mode 100644 xdsm/Generic_normal.tikz create mode 100644 xdsm/Sellar.py create mode 100644 xdsm/Sellar_env.tex create mode 100644 xdsm/Sellar_env.tikz create mode 100644 xdsm/Sellar_normal.tex create mode 100644 xdsm/Sellar_normal.tikz diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e38c5fe --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +*.csv +*.html +*.pyc +*.png +.idea/* +tests/* diff --git a/lca4mdao/__init__.py b/lca4mdao/__init__.py new file mode 100644 index 0000000..f102a9c --- /dev/null +++ b/lca4mdao/__init__.py @@ -0,0 +1 @@ +__version__ = "0.0.1" diff --git a/lca4mdao/database.py b/lca4mdao/database.py new file mode 100644 index 0000000..47c41fe --- /dev/null +++ b/lca4mdao/database.py @@ -0,0 +1,74 @@ +import brightway2 as bw +from bw2data.parameters import ActivityParameter, DatabaseParameter, ProjectParameter, Group +import pandas as pd +from peewee import IntegrityError + +#### Setup +bw.projects.set_current("Example") +bw.bw2setup() +print(bw.projects.report()) + + +def setup_ecoinvent(): + if bw.Database("ecoinvent 3.8 cutoff").random() is None: + fp = '/home/dmsm/t.bellier/Documents/Code/BE_LCA/datasets_old' + ei = bw.SingleOutputEcospold2Importer(fp, "ecoinvent 3.8 cutoff") + ei.apply_strategies() + ei.statistics() + ei.write_database() + else: + print("ecoinvent 3.8 cutoff already imported") + ecoinvent = bw.Database("ecoinvent 3.8 cutoff") + print(ecoinvent.random()) + + +def build_data(): + sellar = bw.Database('sellar') + sellar.register() + sellar.delete() + + wood = ('ecoinvent 3.8 cutoff', 'a63dd664a99c9e82c192f8c50a9b4cfb') + steel = ('ecoinvent 3.8 cutoff', '580b7aea44c188e5958b4c6bd6ec515a') + + data = { + ("sellar", "sellar_problem"): { + 'name': 'sellar_problem', + 'unit': 'unit', + 'location': 'GLO', + 'exchanges': [{ + 'input': wood, + 'amount': 0., + 'formula': "wood", + 'type': 'technosphere' + }, { + 'input': steel, + 'amount': 0., + 'formula': "steel", + 'type': 'technosphere' + }] + } + } + + sellar.write(data) + + env_data = [{ + 'name': 'wood', + 'amount': 0., + }, { + 'name': 'steel', + 'amount': 0., + }] + + bw.parameters.new_database_parameters(env_data, "sellar") + + for a in sellar: + # a.new_exchange(amount=0., input=concrete, type="technosphere", formula="concrete_volume").save() + + bw.parameters.add_exchanges_to_group("lca_parameters", a) + + ActivityParameter.recalculate_exchanges("lca_parameters") + + +if __name__ == '__main__': + setup_ecoinvent() + build_data() diff --git a/lca4mdao/lca.py b/lca4mdao/lca.py new file mode 100644 index 0000000..4cf7213 --- /dev/null +++ b/lca4mdao/lca.py @@ -0,0 +1,37 @@ +import openmdao.api as om +import brightway2 as bw +import numpy as np +from bw2data.parameters import ActivityParameter + + +class GWP(om.ExplicitComponent): + + def setup(self): + # Inputs outside the module + self.add_input('y1', val=0.) + self.add_input('y2', val=0.) + + # Outputs + self.add_output('GWP', units='kg') + + def compute(self, inputs, outputs): + y1 = inputs['y1'] + y2 = inputs['y2'] + env_data = [{ + 'name': 'wood', + 'amount': y2, + }, { + 'name': 'steel', + 'amount': y1, + }] + # bw.parameters.new_project_parameters(project_data) + bw.parameters.new_database_parameters(env_data, "sellar") + # ActivityParameter.recalculate_exchanges("project_parameters_group") + ActivityParameter.recalculate_exchanges("lca_parameters") + functional_unit = {("sellar", "sellar_problem"): 1} + method_key = ('ReCiPe Midpoint (H) V1.13', 'climate change', 'GWP100') + method = bw.methods[method_key] + lca = bw.LCA(functional_unit, method_key) + lca.lci() + lca.lcia() + outputs['GWP'] = lca.score diff --git a/lca4mdao/main.py b/lca4mdao/main.py new file mode 100644 index 0000000..ac79068 --- /dev/null +++ b/lca4mdao/main.py @@ -0,0 +1,202 @@ +import openmdao.api as om +import numpy as np +import pandas as pd +from pymoo.termination.default import DefaultSingleObjectiveTermination, DefaultMultiObjectiveTermination +from pymoo.termination.ftol import MultiObjectiveSpaceTermination + +from optimizer.pymoo_optimizer import PymooDriver +from sellar import SellarDis1, SellarDis2 +from lca import GWP +from database import setup_ecoinvent, build_data + + +class SellarMDALCA(om.Group): + """ + Group containing the Sellar MDA. + """ + + def setup(self): + cycle = self.add_subsystem('cycle', om.Group(), promotes=['*']) + cycle.add_subsystem('d1', SellarDis1(), promotes_inputs=['x', 'z', 'y2'], + promotes_outputs=['y1']) + cycle.add_subsystem('d2', SellarDis2(), promotes_inputs=['z', 'y1'], + promotes_outputs=['y2']) + + cycle.set_input_defaults('x', 1.0) + cycle.set_input_defaults('z', np.array([5.0, 2.0])) + + # Nonlinear Block Gauss Seidel is a gradient free solver + cycle.nonlinear_solver = om.NonlinearBlockGS() + + self.add_subsystem('obj_cmp', om.ExecComp('obj = x**2 + z[1] + y1 + exp(-y2)', + z=np.array([0.0, 0.0]), x=0.0), + promotes=['x', 'z', 'y1', 'y2', 'obj']) + + self.add_subsystem('con_cmp1', om.ExecComp('con1 = 3.16 - y1'), promotes=['con1', 'y1']) + self.add_subsystem('con_cmp2', om.ExecComp('con2 = y2 - 24.0'), promotes=['con2', 'y2']) + self.add_subsystem('lca', GWP(), promotes=['y1', 'y2', 'GWP']) + + +def compute(objective1='obj', objective2='GWP', constraint=None): + prob = om.Problem() + prob.model = SellarMDALCA() + + prob.driver = om.ScipyOptimizeDriver() + prob.driver.options['optimizer'] = 'COBYLA' + # prob.driver.options['maxiter'] = 100 + prob.driver.options['tol'] = 1e-8 + + prob.model.add_design_var('x', lower=0, upper=10) + prob.model.add_design_var('z', lower=0, upper=10) + prob.model.add_objective(objective1) + prob.model.add_constraint('con1', upper=0) + prob.model.add_constraint('con2', upper=0) + if constraint is not None: + prob.model.add_constraint(objective2, upper=constraint) + + # Ask OpenMDAO to finite-difference across the model to compute the gradients for the optimizer + prob.model.approx_totals() + + prob.setup() + prob.set_solver_print(level=0) + + prob.run_driver() + objective1_value = prob.get_val(objective1)[0] + objective2_value = prob.get_val(objective2)[0] + print(prob.get_val('x'), prob.get_val('z')) + + return objective1_value, objective2_value + + +def multi_objective(): + prob = om.Problem() + prob.model = SellarMDALCA() + + prob.driver = PymooDriver() + prob.driver.options['algorithm'] = 'NSGA2' + prob.driver.options['termination'] = DefaultMultiObjectiveTermination( + xtol=1e-8, + cvtol=1e-6, + ftol=1e-2, + period=20, + n_max_gen=200, + n_max_evals=100000 + ) + + prob.driver.options['verbose'] = True + prob.driver.options['algorithm_options'] = {'pop_size': 50} + + prob.model.add_design_var('x', lower=0, upper=10) + prob.model.add_design_var('z', lower=0, upper=10) + prob.model.add_objective('GWP') + prob.model.add_objective('obj') + prob.model.add_constraint('con1', upper=0) + prob.model.add_constraint('con2', upper=0) + + # Ask OpenMDAO to finite-difference across the model to compute the gradients for the optimizer + prob.model.approx_totals() + + prob.setup() + prob.set_solver_print(level=0) + prob.run_driver() + res = prob.driver.result + print(res.pop.get("X"), res.opt.get("X"), res.X) + print(res.pop.get("F"), res.opt.get("F"), res.F) + + # convert array into dataframe + DF = pd.DataFrame(res.F) + + # save the dataframe as a csv file + DF.to_csv("results/SellarWoodSteelPymoo.csv") + + +if __name__ == '__main__': + setup_ecoinvent() + build_data() + # multi_objective() + print(compute()) + print(compute(objective1='GWP', objective2='obj')) + + +def old_main(): + # setup_ecoinvent() + # build_data() + points = 50 + results = np.zeros((points, 2)) + results[0] = np.array(compute(objective1='GWP', objective2='obj')) + results[points - 1] = np.array(compute(objective1='obj', objective2='GWP'))[::-1] + constraints = np.linspace(results[0, 1], results[-1, 1], points)[1:-1] + for k in range(1, points - 1): + results[k] = np.array(compute(objective1='GWP', objective2='obj', constraint=constraints[k - 1])) + # convert array into dataframe + DF = pd.DataFrame(results) + + # save the dataframe as a csv file + DF.to_csv("results/SellarWoodSteel.csv") + print(results) + + +def old(): + prob = om.Problem() + prob.model = SellarMDALCA() + + prob.driver = om.ScipyOptimizeDriver() + prob.driver.options['optimizer'] = 'SLSQP' + # prob.driver.options['maxiter'] = 100 + prob.driver.options['tol'] = 1e-8 + + prob.model.add_design_var('x', lower=0, upper=10) + prob.model.add_design_var('z', lower=0, upper=10) + prob.model.add_objective('obj') + prob.model.add_constraint('con1', upper=0) + prob.model.add_constraint('con2', upper=0) + + # Ask OpenMDAO to finite-difference across the model to compute the gradients for the optimizer + prob.model.approx_totals() + + prob.setup() + prob.set_solver_print(level=0) + + prob.run_driver() + + print('minimum found at') + print(prob.get_val('x')[0]) + print(prob.get_val('z')) + + print('minumum objective') + print(prob.get_val('obj')[0]) + + print('GWP at objective') + print(prob.get_val('GWP')[0]) + + prob = om.Problem() + prob.model = SellarMDALCA() + + prob.driver = om.ScipyOptimizeDriver() + prob.driver.options['optimizer'] = 'COBYLA' + # prob.driver.options['maxiter'] = 100 + prob.driver.options['tol'] = 1e-8 + + prob.model.add_design_var('x', lower=0, upper=10) + prob.model.add_design_var('z', lower=0, upper=10) + prob.model.add_objective('GWP') + prob.model.add_constraint('con1', upper=0) + prob.model.add_constraint('con2', upper=0) + + # Ask OpenMDAO to finite-difference across the model to compute the gradients for the optimizer + prob.model.approx_totals() + + prob.setup() + prob.set_solver_print(level=0) + + prob.run_driver() + + print('minimum found at') + print(prob.get_val('x')[0]) + print(prob.get_val('z')) + + print('minimum GWP') + print(prob.get_val('GWP')[0]) + + print('objective at minimum GWP') + print(prob.get_val('obj')[0]) diff --git a/lca4mdao/optimizer/__init__.py b/lca4mdao/optimizer/__init__.py new file mode 100644 index 0000000..a22e37e --- /dev/null +++ b/lca4mdao/optimizer/__init__.py @@ -0,0 +1 @@ +from .pymoo_optimizer import PymooDriver, OpenMDAOProblem diff --git a/lca4mdao/optimizer/pymoo_optimizer.py b/lca4mdao/optimizer/pymoo_optimizer.py new file mode 100644 index 0000000..fd8f4b3 --- /dev/null +++ b/lca4mdao/optimizer/pymoo_optimizer.py @@ -0,0 +1,270 @@ +import numpy as np +from openmdao.core.driver import Driver +from openmdao.core.problem import Problem +from pymoo.algorithms.moo.nsga2 import NSGA2 +from pymoo.algorithms.soo.nonconvex.de import DE +from pymoo.algorithms.soo.nonconvex.ga import GA +from pymoo.core.problem import ElementwiseProblem +from pymoo.core.termination import Termination +from pymoo.optimize import minimize + +_optimizers = {'NSGA2', 'GA', 'DE'} +_gradient_optimizers = {''} +_hessian_optimizers = {''} +_bounds_optimizers = {'NSGA2', 'GA', 'DE'} +_constraint_optimizers = {'NSGA2', 'GA', 'DE'} +_constraint_grad_optimizers = _gradient_optimizers & _constraint_optimizers +_eq_constraint_optimizers = {''} +_global_optimizers = {'NSGA2', 'GA', 'DE'} +_multi_objectives_optimizers = {'NSGA2', } + +_algorithms_dict = { + 'NSGA2': NSGA2, + 'GA': GA, + 'DE': DE, +} + +CITATIONS = """ +@article{pymoo, + author={J. {Blank} and K. {Deb}}, + journal={IEEE Access}, + title={pymoo: Multi-Objective Optimization in Python}, + year={2020}, + volume={8}, + number={}, + pages={89497-89509}, +}""" + + +class OpenMDAOProblem(ElementwiseProblem): + def __init__(self, problem: Problem, design_vars, **kwargs): + self.problem = problem + n_var, n_obj, n_ieq_constr, n_eq_constr, xl, xu, var_names, var_sizes, obj_names, con_names = \ + self._get_pymoo_parameters(problem, design_vars) + super(OpenMDAOProblem, self).__init__( + n_var=n_var, + n_obj=n_obj, + n_ieq_constr=n_ieq_constr, + n_eq_constr=n_eq_constr, + xl=xl, + xu=xu, + **kwargs) + self.var_names = var_names + self.var_sizes = var_sizes + self.obj_names = obj_names + self.con_names = con_names + # print(var_names, obj_names, con_names, n_var, n_obj, n_ieq_constr) + + @staticmethod + def _get_pymoo_parameters(problem: Problem, design_vars): + var_names = [] + var_sizes = [] + xl = [] + xu = [] + for name, meta in design_vars.items(): + size = meta['global_size'] if meta['distributed'] else meta['size'] + var_sizes.append(size) + meta_low = meta['lower'] + meta_high = meta['upper'] + for j in range(size): + if isinstance(meta_low, np.ndarray): + p_low = meta_low[j] + else: + p_low = meta_low + if isinstance(meta_high, np.ndarray): + p_high = meta_high[j] + else: + p_high = meta_high + xu.append(p_high) + xl.append(p_low) + var_names.append(name) + n_var = sum(var_sizes) + objs = problem.driver.get_objective_values() + obj_names = list(objs.keys()) + n_obj = len(obj_names) + in_cons = problem.driver.get_constraint_values(ctype='ineq') + eq_cons = problem.driver.get_constraint_values(ctype='eq') + con_names = list(in_cons.keys()) + list(eq_cons.keys()) + n_ieq_constr = len(in_cons.keys()) + n_eq_constr = len(eq_cons.keys()) + xl = np.array(xl) + xu = np.array(xu) + return n_var, n_obj, n_ieq_constr, n_eq_constr, xl, xu, var_names, var_sizes, obj_names, con_names + + def _evaluate(self, x, out, *args, **kwargs): + i = 0 + for size, n in zip(self.var_sizes, self.var_names): + if size == 1: + self.problem.set_val(n, x[i]) + else: + self.problem.set_val(n, np.array(x[i:i + size])) + i += size + self.problem.run_model() + # objectives = [self.problem.model.get_val(n) for n in self.obj_names] + out["F"] = np.array([self.problem.model.get_val(n) for n in self.obj_names]) + if self.n_constr > 0: + # constraints = self.problem.driver.get_constraint_values(driver_scaling=True) + out["G"] = np.array([self.problem.model.get_val(n) for n in self.con_names]) + # print(x, out) + + +class PymooDriver(Driver): + def __init__(self, **kwargs): + """ + Initialize the PymooDriver. + """ + super().__init__(**kwargs) + + # What we support + self.supports['optimization'] = True + self.supports['inequality_constraints'] = True + self.supports['equality_constraints'] = True + self.supports['two_sided_constraints'] = True + self.supports['linear_constraints'] = True + self.supports['simultaneous_derivatives'] = True + self.supports['multiple_objectives'] = True + + # What we don't support + self.supports['active_set'] = False + self.supports['integer_design_vars'] = False + self.supports['distributed_design_vars'] = False + self.supports._read_only = True + + # The user places optimizer-specific settings in here. + self.opt_settings = {} + + self.result = None + self._grad_cache = None + self._con_cache = None + self._con_idx = {} + self._obj_and_nlcons = None + self._dvlist = None + self._lincongrad_cache = None + self.fail = False + self.iter_count = 0 + # self._check_jac = False + self._exc_info = None + self._total_jac_format = 'array' + + self.cite = CITATIONS + + def _declare_options(self): + """ + Declare options before kwargs are processed in the init method. + """ + self.options.declare('algorithm', 'NSGA2', values=_optimizers, + desc='Name of algorithm to use') + self.options.declare('algorithm_options', dict(), types=dict, + desc='Option dictionary to be passed to the Algorithm') + self.options.declare('termination', None, types=(tuple, Termination), + desc='Option dictionary to be passed to the Algorithm') + # self.options.declare('tol', 1.0e-6, lower=0.0, + # desc='Tolerance for termination. For detailed ' + # 'control, use solver-specific options.') + # self.options.declare('maxiter', 200, lower=0, + # desc='Maximum number of iterations.') + self.options.declare('verbose', False, types=bool, + desc='Set to False to prevent printing of Pymoo convergence messages') + # self.options.declare('singular_jac_behavior', default='warn', + # values=['error', 'warn', 'ignore'], + # desc='Defines behavior of a zero row/col check after first call to' + # 'compute_totals:' + # 'error - raise an error.' + # 'warn - raise a warning.' + # "ignore - don't perform check.") + # self.options.declare('singular_jac_tol', default=1e-16, + # desc='Tolerance for zero row/column check.') + + def _get_name(self): + """ + Get name of current optimizer. + + Returns + ------- + str + The name of the current optimizer. + """ + return "Pymoo_" + self.options['algorithm'] + + def _setup_driver(self, problem): + """ + Prepare the driver for execution. + + This is the final thing to run during setup. + + Parameters + ---------- + problem : + Pointer + """ + super()._setup_driver(problem) + opt = self.options['algorithm'] + + self.supports._read_only = False + self.supports['gradients'] = opt in _gradient_optimizers + self.supports['inequality_constraints'] = opt in _constraint_optimizers + self.supports['two_sided_constraints'] = opt in _constraint_optimizers + self.supports['equality_constraints'] = opt in _eq_constraint_optimizers + self.supports['multiple_objectives'] = opt in _multi_objectives_optimizers + self.supports._read_only = True + # self._check_jac = self.options['singular_jac_behavior'] in ['error', 'warn'] + + # Raises error if multiple objectives are not supported, but more objectives were defined. + if not self.supports['multiple_objectives'] and len(self._objs) > 1: + msg = '{} currently does not support multiple objectives.' + raise RuntimeError(msg.format(self.msginfo)) + + def get_driver_objective_calls(self): + """ + Return number of objective evaluations made during a driver run. + + Returns + ------- + int + Number of objective evaluations made during a driver run. + """ + if self.result and hasattr(self.result, 'nfev'): # TODO : check pymoo API + return self.result.nfev + else: + return None + + def get_driver_derivative_calls(self): + """ + Return number of derivative evaluations made during a driver run. + + Returns + ------- + int + Number of derivative evaluations made during a driver run. + """ + if self.result and hasattr(self.result, 'njev'): # TODO : check pymoo API + return self.result.njev + else: + return None + + def run(self): + """ + Optimize the problem using selected Pymoo optimizer. + + Returns + ------- + bool + Failure flag; True if failed to converge, False is successful. + """ + problem = self._problem() + self.iter_count = 0 + self._check_for_missing_objective() + + model = problem.model + + self._con_cache = self.get_constraint_values() + self._dvlist = list(self._designvars) + + algo = _algorithms_dict[self.options['algorithm']](**self.options['algorithm_options']) + pymoo_problem = OpenMDAOProblem(problem, self._designvars) + res = minimize(pymoo_problem, algo, self.options['termination'], verbose=self.options['verbose']) + self.result = res + self.fail = not res.success + if pymoo_problem.n_obj <= 1: + pymoo_problem.evaluate(res.X) + return self.fail diff --git a/lca4mdao/sellar.py b/lca4mdao/sellar.py new file mode 100644 index 0000000..a4c8c41 --- /dev/null +++ b/lca4mdao/sellar.py @@ -0,0 +1,194 @@ +import openmdao.api as om +import numpy as np +from pymoo.termination.default import DefaultSingleObjectiveTermination + +from optimizer.pymoo_optimizer import PymooDriver + + +class SellarDis1(om.ExplicitComponent): + """ + Component containing Discipline 1 -- no derivatives version. + """ + + def setup(self): + # Global Design Variable + self.add_input('z', val=np.zeros(2)) + + # Local Design Variable + self.add_input('x', val=0.) + + # Coupling parameter + self.add_input('y2', val=1.0) + + # Coupling output + self.add_output('y1', val=1.0) + + def setup_partials(self): + # Finite difference all partials. + self.declare_partials('*', '*', method='fd') + + def compute(self, inputs, outputs): + """ + Evaluates the equation + y1 = z1**2 + z2 + x1 - 0.2*y2 + """ + z1 = inputs['z'][0] + z2 = inputs['z'][1] + x1 = inputs['x'] + y2 = inputs['y2'] + + outputs['y1'] = z1 ** 2 + z2 + x1 - 0.2 * y2 + + +class SellarDis2(om.ExplicitComponent): + """ + Component containing Discipline 2 -- no derivatives version. + """ + + def setup(self): + # Global Design Variable + self.add_input('z', val=np.zeros(2)) + + # Coupling parameter + self.add_input('y1', val=1.0) + + # Coupling output + self.add_output('y2', val=1.0) + + def setup_partials(self): + # Finite difference all partials. + self.declare_partials('*', '*', method='fd') + + def compute(self, inputs, outputs): + """ + Evaluates the equation + y2 = y1**(.5) + z1 + z2 + """ + + z1 = inputs['z'][0] + z2 = inputs['z'][1] + y1 = inputs['y1'] + + # Note: this may cause some issues. However, y1 is constrained to be + # above 3.16, so lets just let it converge, and the optimizer will + # throw it out + if y1.real < 0.0: + y1 *= -1 + + outputs['y2'] = y1 ** .5 + z1 + z2 + + +class SellarMDA(om.Group): + """ + Group containing the Sellar MDA. + """ + + def setup(self): + cycle = self.add_subsystem('cycle', om.Group(), promotes=['*']) + cycle.add_subsystem('d1', SellarDis1(), promotes_inputs=['x', 'z', 'y2'], + promotes_outputs=['y1']) + cycle.add_subsystem('d2', SellarDis2(), promotes_inputs=['z', 'y1'], + promotes_outputs=['y2']) + + cycle.set_input_defaults('x', 1.0) + cycle.set_input_defaults('z', np.array([5.0, 2.0])) + + # Nonlinear Block Gauss Seidel is a gradient free solver + cycle.nonlinear_solver = om.NonlinearBlockGS() + + self.add_subsystem('obj_cmp', om.ExecComp('obj = x**2 + z[1] + y1 + exp(-y2)', + z=np.array([0.0, 0.0]), x=0.0), + promotes=['x', 'z', 'y1', 'y2', 'obj']) + + self.add_subsystem('con_cmp1', om.ExecComp('con1 = 3.16 - y1'), promotes=['con1', 'y1']) + self.add_subsystem('con_cmp2', om.ExecComp('con2 = y2 - 24.0'), promotes=['con2', 'y2']) + + +if __name__ == '__main__': + """Run 1 : pymoo + """ + prob = om.Problem() + prob.model = SellarMDA() + + """ + prob.driver = om.ScipyOptimizeDriver() + prob.driver.options['optimizer'] = 'SLSQP' + # prob.driver.options['maxiter'] = 100 + prob.driver.options['tol'] = 1e-8 + """ + + prob.driver = PymooDriver() + prob.driver.options['algorithm'] = 'NSGA2' + prob.driver.options['termination'] = DefaultSingleObjectiveTermination( + xtol=1e-8, + cvtol=1e-6, + ftol=1e-6, + period=20, + n_max_gen=200, + n_max_evals=100000 + ) + + prob.driver.options['verbose'] = True + prob.driver.options['algorithm_options'] = {'pop_size': 30} + + prob.model.add_design_var('x', lower=0, upper=10) + prob.model.add_design_var('z', lower=0, upper=10) + prob.model.add_objective('obj') + prob.model.add_constraint('con1', upper=0) + prob.model.add_constraint('con2', upper=0) + + # Ask OpenMDAO to finite-difference across the model to compute the gradients for the optimizer + prob.model.approx_totals() + + prob.setup() + prob.set_solver_print(level=0) + + prob.run_driver() + + # print(prob.driver.result.X, prob.driver.result.F, prob.driver.result.G) + + # print('minimum found at') + # print(prob.driver.result.X[0]) + # print(prob.driver.result.X[1:3]) + # + # print('minumum objective') + # print(prob.driver.result.F[0]) + + print('minimum found at') + print(prob.get_val('x')[0]) + print(prob.get_val('z')) + + print('minumum objective') + print(prob.get_val('obj')[0]) + + """Run 2 : scipy + """ + + prob = om.Problem() + prob.model = SellarMDA() + + prob.driver = om.ScipyOptimizeDriver() + prob.driver.options['optimizer'] = 'SLSQP' + # prob.driver.options['maxiter'] = 100 + prob.driver.options['tol'] = 1e-8 + + prob.model.add_design_var('x', lower=0, upper=10) + prob.model.add_design_var('z', lower=0, upper=10) + prob.model.add_objective('obj') + prob.model.add_constraint('con1', upper=0) + prob.model.add_constraint('con2', upper=0) + + # Ask OpenMDAO to finite-difference across the model to compute the gradients for the optimizer + prob.model.approx_totals() + + prob.setup() + prob.set_solver_print(level=0) + + prob.run_driver() + + print('minimum found at') + print(prob.get_val('x')[0]) + print(prob.get_val('z')) + + print('minumum objective') + print(prob.get_val('obj')[0]) diff --git a/xdsm/Generic.py b/xdsm/Generic.py new file mode 100644 index 0000000..081d3c1 --- /dev/null +++ b/xdsm/Generic.py @@ -0,0 +1,58 @@ +from pyxdsm.XDSM import XDSM, OPT, SOLVER, FUNC, IFUNC, METAMODEL, IGROUP, GROUP + +x = XDSM(use_sfmath=True) + +x.add_system("input", OPT, r"\text{Optimizer}") +x.add_system("mda", SOLVER, r"\text{MDA}") +x.add_system("Discipline", GROUP, (r"\text{Technical}", r"\text{Disciplines}")) + +x.add_system("Obj", IFUNC, (r"\text{Technical}", r"\text{Objective}")) +x.add_system("Cons", IGROUP, (r"\text{Technical}", r"\text{Constraints}")) + +x.add_system("Env", METAMODEL, r"\text{LCA}") + +x.add_system("EObj", IFUNC, (r"\text{Environmental}", r"\text{Objective}")) +x.add_system("ECons", IGROUP, (r"\text{Environmental}", r"\text{Constraints}")) + +x.add_input("input", r"\bar{x^{*}}") +x.add_input("mda", r"\bar{y^{*}}") + +# x.connect("input", "mda", r"x^{*}") +x.connect("input", "Discipline", r"\bar{x}") +x.connect("mda", "Discipline", r"\bar{y}") +x.connect("input", "Obj", r"\bar{x}") +x.connect("mda", "Obj", r"\bar{y}") +x.connect("input", "Cons", r"\bar{x}") +x.connect("mda", "Cons", r"\bar{y}") +x.connect("Discipline", "Obj", r"\bar{z}") +x.connect("Discipline", "Cons", r"\bar{z}") +x.connect("Discipline", "mda", r"\bar{y^{*}}") +x.connect("Obj", "input", r"f_t") +x.connect("Cons", "input", r"\bar{c_t}") + +x.connect("input", "Env", r"\bar{x}") +x.connect("mda", "Env", r"\bar{y}") +x.connect("Discipline", "Env", r"\bar{z}") +# x.connect("input", "EObj", r"\bar{x}") +# x.connect("mda", "EObj", r"\bar{y}") +# x.connect("input", "ECons", r"\bar{x}") +# x.connect("mda", "ECons", r"\bar{y}") +# x.connect("Discipline", "EObj", r"\bar{z}") +# x.connect("Discipline", "ECons", r"\bar{z}") + +x.connect("Env", "EObj", r"\bar{y_e}") +x.connect("Env", "ECons", r"\bar{y_e}") + +x.add_output("Obj", r"f_t", side="right") +x.add_output("Cons", r"\bar{c_t}", side="right") + +x.add_output("EObj", r"f_e", side="right") +x.add_output("ECons", r"\bar{c_e}", side="right") + +x.write("Generic_normal", build=True) + + +# x.connect("Discipline", "Env", r"y_1") +# x.connect("D2", "Env", r"y_2") +# +# x.write("Generic_env", build=True) diff --git a/xdsm/Generic_env.py b/xdsm/Generic_env.py new file mode 100644 index 0000000..33d90bd --- /dev/null +++ b/xdsm/Generic_env.py @@ -0,0 +1,55 @@ +from pyxdsm.XDSM import XDSM, OPT, SOLVER, FUNC, IFUNC, METAMODEL, IGROUP, GROUP + +x = XDSM(use_sfmath=True) + +x.add_system("input", OPT, r"\text{Optimizer}") +x.add_system("mda", SOLVER, r"\text{MDA}") +x.add_system("Discipline", GROUP, (r"\text{Technical}", r"\text{Disciplines}")) + +x.add_system("Env", FUNC, r"\text{LCA}") + +x.add_system("Obj", IGROUP, r"\text{Objectives}") +x.add_system("Cons", IGROUP, r"\text{Constraints}") + +# x.add_system("EObj", IFUNC, (r"\text{Environmental}", r"\text{Objective}")) +# x.add_system("ECons", IGROUP, (r"\text{Environmental}", r"\text{Constraints}")) + +x.add_input("input", r"\bar{x^{*}}") +x.add_input("mda", r"\bar{y^{*}}") + +# x.connect("input", "mda", r"x^{*}") +x.connect("input", "Discipline", r"\bar{x}") +x.connect("mda", "Discipline", r"\bar{y}") +x.connect("input", "Obj", r"\bar{x}") +x.connect("mda", "Obj", r"\bar{y}") +x.connect("input", "Cons", r"\bar{x}") +x.connect("mda", "Cons", r"\bar{y}") +x.connect("Discipline", "Obj", r"\bar{z}") +x.connect("Discipline", "Cons", r"\bar{z}") +x.connect("Discipline", "mda", r"\bar{y^{*}}") +x.connect("Obj", "input", r"f_t,f_e") +x.connect("Cons", "input", r"\bar{c_t},\bar{c_e}") + +x.connect("input", "Env", r"\bar{x}") +x.connect("mda", "Env", r"\bar{y}") +x.connect("Discipline", "Env", r"\bar{z}") +# x.connect("input", "EObj", r"\bar{x}") +# x.connect("mda", "EObj", r"\bar{y}") +# x.connect("input", "ECons", r"\bar{x}") +# x.connect("mda", "ECons", r"\bar{y}") +# x.connect("Discipline", "EObj", r"\bar{z}") +# x.connect("Discipline", "ECons", r"\bar{z}") + +x.connect("Env", "Obj", r"\bar{y_e}") +x.connect("Env", "Cons", r"\bar{y_e}") + +x.add_output("Obj", r"f_t,f_e", side="right") +x.add_output("Cons", r"\bar{c_t},\bar{c_e}", side="right") + +# x.add_output("EObj", r"f_e", side="right") +# x.add_output("ECons", r"\bar{c_e}", side="right") +# +# x.connect("EObj", "input", r"f_e") +# x.connect("ECons", "input", r"\bar{c_e}") + +x.write("Generic_env", build=True) diff --git a/xdsm/Generic_env.tex b/xdsm/Generic_env.tex new file mode 100644 index 0000000..14d2fb1 --- /dev/null +++ b/xdsm/Generic_env.tex @@ -0,0 +1,27 @@ + +% XDSM diagram created with pyXDSM 2.3.0. +\documentclass{article} +\usepackage{geometry} +\usepackage{amsfonts} +\usepackage{amsmath} +\usepackage{amssymb} +\usepackage{tikz} + +% Optional packages such as sfmath set through python interface +\usepackage{sfmath} + +% Define the set of TikZ packages to be included in the architecture diagram document +\usetikzlibrary{arrows,chains,positioning,scopes,shapes.geometric,shapes.misc,shadows} + + +% Set the border around all of the architecture diagrams to be tight to the diagrams themselves +% (i.e. no longer need to tinker with page size parameters) +\usepackage[active,tightpage]{preview} +\PreviewEnvironment{tikzpicture} +\setlength{\PreviewBorder}{5pt} + +\begin{document} + +\input{"Generic_env.tikz"} + +\end{document} diff --git a/xdsm/Generic_env.tikz b/xdsm/Generic_env.tikz new file mode 100644 index 0000000..7a6cce7 --- /dev/null +++ b/xdsm/Generic_env.tikz @@ -0,0 +1,139 @@ + +%%% Preamble Requirements %%% +% \usepackage{geometry} +% \usepackage{amsfonts} +% \usepackage{amsmath} +% \usepackage{amssymb} +% \usepackage{tikz} + +% Optional packages such as sfmath set through python interface +% \usepackage{sfmath} + +% \usetikzlibrary{arrows,chains,positioning,scopes,shapes.geometric,shapes.misc,shadows} + +%%% End Preamble Requirements %%% + +\input{"/home/dmsm/t.bellier/anaconda3/envs/LCA_Module/lib/python3.9/site-packages/pyxdsm/diagram_styles"} +\begin{tikzpicture} + +\matrix[MatrixSetup]{ +%Row 0 +\node [DataIO] (output_input) {$\bar{x^{*}}$};& +\node [DataIO] (output_mda) {$\bar{y^{*}}$};& +& +& +& +& +& +\\ +%Row 1 +\node [Optimization] (input) {$\text{Optimizer}$};& +& +\node [DataInter] (input-Discipline) {$\bar{x}$};& +\node [DataInter] (input-Env) {$\bar{x}$};& +\node [DataInter] (input-Obj) {$\bar{x}$};& +\node [DataInter] (input-Cons) {$\bar{x}$};& +& +\\ +%Row 2 +& +\node [MDA] (mda) {$\text{MDA}$};& +\node [DataInter] (mda-Discipline) {$\bar{y}$};& +\node [DataInter] (mda-Env) {$\bar{y}$};& +\node [DataInter] (mda-Obj) {$\bar{y}$};& +\node [DataInter] (mda-Cons) {$\bar{y}$};& +& +\\ +%Row 3 +& +\node [DataInter] (Discipline-mda) {$\bar{y^{*}}$};& +\node [Group] (Discipline) {$\begin{array}{c}\text{Technical} \\ \text{Disciplines}\end{array}$};& +\node [DataInter] (Discipline-Env) {$\bar{z}$};& +\node [DataInter] (Discipline-Obj) {$\bar{z}$};& +\node [DataInter] (Discipline-Cons) {$\bar{z}$};& +& +\\ +%Row 4 +& +& +& +\node [Function] (Env) {$\text{LCA}$};& +\node [DataInter] (Env-Obj) {$\bar{y_e}$};& +\node [DataInter] (Env-Cons) {$\bar{y_e}$};& +& +\\ +%Row 5 +\node [DataInter] (Obj-input) {$f_t,f_e$};& +& +& +& +\node [ImplicitGroup] (Obj) {$\text{Objectives}$};& +& +& +\node [DataIO] (right_output_Obj) {$f_t,f_e$};\\ +%Row 6 +\node [DataInter] (Cons-input) {$\bar{c_t},\bar{c_e}$};& +& +& +& +& +\node [ImplicitGroup] (Cons) {$\text{Constraints}$};& +& +\node [DataIO] (right_output_Cons) {$\bar{c_t},\bar{c_e}$};\\ +%Row 7 +& +& +& +& +& +& +& +\\ +}; + +% XDSM process chains + + +\begin{pgfonlayer}{data} +\path +% Horizontal edges +(input) edge [DataLine] (input-Discipline) +(mda) edge [DataLine] (mda-Discipline) +(input) edge [DataLine] (input-Obj) +(mda) edge [DataLine] (mda-Obj) +(input) edge [DataLine] (input-Cons) +(mda) edge [DataLine] (mda-Cons) +(Discipline) edge [DataLine] (Discipline-Obj) +(Discipline) edge [DataLine] (Discipline-Cons) +(Discipline) edge [DataLine] (Discipline-mda) +(Obj) edge [DataLine] (Obj-input) +(Cons) edge [DataLine] (Cons-input) +(input) edge [DataLine] (input-Env) +(mda) edge [DataLine] (mda-Env) +(Discipline) edge [DataLine] (Discipline-Env) +(Env) edge [DataLine] (Env-Obj) +(Env) edge [DataLine] (Env-Cons) +(Obj) edge [DataLine] (right_output_Obj) +(Cons) edge [DataLine] (right_output_Cons) +% Vertical edges +(input-Discipline) edge [DataLine] (Discipline) +(mda-Discipline) edge [DataLine] (Discipline) +(input-Obj) edge [DataLine] (Obj) +(mda-Obj) edge [DataLine] (Obj) +(input-Cons) edge [DataLine] (Cons) +(mda-Cons) edge [DataLine] (Cons) +(Discipline-Obj) edge [DataLine] (Obj) +(Discipline-Cons) edge [DataLine] (Cons) +(Discipline-mda) edge [DataLine] (mda) +(Obj-input) edge [DataLine] (input) +(Cons-input) edge [DataLine] (input) +(input-Env) edge [DataLine] (Env) +(mda-Env) edge [DataLine] (Env) +(Discipline-Env) edge [DataLine] (Env) +(Env-Obj) edge [DataLine] (Obj) +(Env-Cons) edge [DataLine] (Cons) +(input) edge [DataLine] (output_input) +(mda) edge [DataLine] (output_mda); +\end{pgfonlayer} + +\end{tikzpicture} diff --git a/xdsm/Generic_normal.tex b/xdsm/Generic_normal.tex new file mode 100644 index 0000000..790009f --- /dev/null +++ b/xdsm/Generic_normal.tex @@ -0,0 +1,27 @@ + +% XDSM diagram created with pyXDSM 2.3.0. +\documentclass{article} +\usepackage{geometry} +\usepackage{amsfonts} +\usepackage{amsmath} +\usepackage{amssymb} +\usepackage{tikz} + +% Optional packages such as sfmath set through python interface +\usepackage{sfmath} + +% Define the set of TikZ packages to be included in the architecture diagram document +\usetikzlibrary{arrows,chains,positioning,scopes,shapes.geometric,shapes.misc,shadows} + + +% Set the border around all of the architecture diagrams to be tight to the diagrams themselves +% (i.e. no longer need to tinker with page size parameters) +\usepackage[active,tightpage]{preview} +\PreviewEnvironment{tikzpicture} +\setlength{\PreviewBorder}{5pt} + +\begin{document} + +\input{"Generic_normal.tikz"} + +\end{document} diff --git a/xdsm/Generic_normal.tikz b/xdsm/Generic_normal.tikz new file mode 100644 index 0000000..7eaac52 --- /dev/null +++ b/xdsm/Generic_normal.tikz @@ -0,0 +1,179 @@ + +%%% Preamble Requirements %%% +% \usepackage{geometry} +% \usepackage{amsfonts} +% \usepackage{amsmath} +% \usepackage{amssymb} +% \usepackage{tikz} + +% Optional packages such as sfmath set through python interface +% \usepackage{sfmath} + +% \usetikzlibrary{arrows,chains,positioning,scopes,shapes.geometric,shapes.misc,shadows} + +%%% End Preamble Requirements %%% + +\input{"/home/dmsm/t.bellier/anaconda3/envs/LCA_Module/lib/python3.9/site-packages/pyxdsm/diagram_styles"} +\begin{tikzpicture} + +\matrix[MatrixSetup]{ +%Row 0 +\node [DataIO] (output_input) {$\bar{x^{*}}$};& +\node [DataIO] (output_mda) {$\bar{y^{*}}$};& +& +& +& +& +& +& +& +\\ +%Row 1 +\node [Optimization] (input) {$\text{Optimizer}$};& +& +\node [DataInter] (input-Discipline) {$\bar{x}$};& +\node [DataInter] (input-Obj) {$\bar{x}$};& +\node [DataInter] (input-Cons) {$\bar{x}$};& +\node [DataInter] (input-Env) {$\bar{x}$};& +& +& +& +\\ +%Row 2 +& +\node [MDA] (mda) {$\text{MDA}$};& +\node [DataInter] (mda-Discipline) {$\bar{y}$};& +\node [DataInter] (mda-Obj) {$\bar{y}$};& +\node [DataInter] (mda-Cons) {$\bar{y}$};& +\node [DataInter] (mda-Env) {$\bar{y}$};& +& +& +& +\\ +%Row 3 +& +\node [DataInter] (Discipline-mda) {$\bar{y^{*}}$};& +\node [Group] (Discipline) {$\begin{array}{c}\text{Technical} \\ \text{Disciplines}\end{array}$};& +\node [DataInter] (Discipline-Obj) {$\bar{z}$};& +\node [DataInter] (Discipline-Cons) {$\bar{z}$};& +\node [DataInter] (Discipline-Env) {$\bar{z}$};& +& +& +& +\\ +%Row 4 +\node [DataInter] (Obj-input) {$f_t$};& +& +& +\node [ImplicitFunction] (Obj) {$\begin{array}{c}\text{Technical} \\ \text{Objective}\end{array}$};& +& +& +& +& +& +\node [DataIO] (right_output_Obj) {$f_t$};\\ +%Row 5 +\node [DataInter] (Cons-input) {$\bar{c_t}$};& +& +& +& +\node [ImplicitGroup] (Cons) {$\begin{array}{c}\text{Technical} \\ \text{Constraints}\end{array}$};& +& +& +& +& +\node [DataIO] (right_output_Cons) {$\bar{c_t}$};\\ +%Row 6 +& +& +& +& +& +\node [Metamodel] (Env) {$\text{LCA}$};& +\node [DataInter] (Env-EObj) {$\bar{y_e}$};& +\node [DataInter] (Env-ECons) {$\bar{y_e}$};& +& +\\ +%Row 7 +& +& +& +& +& +& +\node [ImplicitFunction] (EObj) {$\begin{array}{c}\text{Environmental} \\ \text{Objective}\end{array}$};& +& +& +\node [DataIO] (right_output_EObj) {$f_e$};\\ +%Row 8 +& +& +& +& +& +& +& +\node [ImplicitGroup] (ECons) {$\begin{array}{c}\text{Environmental} \\ \text{Constraints}\end{array}$};& +& +\node [DataIO] (right_output_ECons) {$\bar{c_e}$};\\ +%Row 9 +& +& +& +& +& +& +& +& +& +\\ +}; + +% XDSM process chains + + +\begin{pgfonlayer}{data} +\path +% Horizontal edges +(input) edge [DataLine] (input-Discipline) +(mda) edge [DataLine] (mda-Discipline) +(input) edge [DataLine] (input-Obj) +(mda) edge [DataLine] (mda-Obj) +(input) edge [DataLine] (input-Cons) +(mda) edge [DataLine] (mda-Cons) +(Discipline) edge [DataLine] (Discipline-Obj) +(Discipline) edge [DataLine] (Discipline-Cons) +(Discipline) edge [DataLine] (Discipline-mda) +(Obj) edge [DataLine] (Obj-input) +(Cons) edge [DataLine] (Cons-input) +(input) edge [DataLine] (input-Env) +(mda) edge [DataLine] (mda-Env) +(Discipline) edge [DataLine] (Discipline-Env) +(Env) edge [DataLine] (Env-EObj) +(Env) edge [DataLine] (Env-ECons) +(Obj) edge [DataLine] (right_output_Obj) +(Cons) edge [DataLine] (right_output_Cons) +(EObj) edge [DataLine] (right_output_EObj) +(ECons) edge [DataLine] (right_output_ECons) +% Vertical edges +(input-Discipline) edge [DataLine] (Discipline) +(mda-Discipline) edge [DataLine] (Discipline) +(input-Obj) edge [DataLine] (Obj) +(mda-Obj) edge [DataLine] (Obj) +(input-Cons) edge [DataLine] (Cons) +(mda-Cons) edge [DataLine] (Cons) +(Discipline-Obj) edge [DataLine] (Obj) +(Discipline-Cons) edge [DataLine] (Cons) +(Discipline-mda) edge [DataLine] (mda) +(Obj-input) edge [DataLine] (input) +(Cons-input) edge [DataLine] (input) +(input-Env) edge [DataLine] (Env) +(mda-Env) edge [DataLine] (Env) +(Discipline-Env) edge [DataLine] (Env) +(Env-EObj) edge [DataLine] (EObj) +(Env-ECons) edge [DataLine] (ECons) +(input) edge [DataLine] (output_input) +(mda) edge [DataLine] (output_mda); +\end{pgfonlayer} + +\end{tikzpicture} diff --git a/xdsm/Sellar.py b/xdsm/Sellar.py new file mode 100644 index 0000000..6cb5c39 --- /dev/null +++ b/xdsm/Sellar.py @@ -0,0 +1,41 @@ +from pyxdsm.XDSM import XDSM, OPT, SOLVER, FUNC, IFUNC, METAMODEL + +x = XDSM(use_sfmath=True) + +# x.add_system("input", OPT, r"\text{Optimizer}") +# x.add_system("mda", SOLVER, r"\text{MDA}") +x.add_system("D1", FUNC, (r"\text{Discipline 1}", r"y_1 = z_{1}^{2}+z_2+x_1-0.2y_2")) +# x.add_system("D2", FUNC, r"\text{Discipline 2}\ \y_2=\sqrt{y_{1}}+z_1+z_2") +x.add_system("D2", FUNC, (r"\text{Discipline 2}", r"y_2=\sqrt{y_{1}}+z_1+z_2")) +x.add_system("Obj", IFUNC, (r"\text{Objective}", r"f=x^{2}+z_1+y_1+e^{-y_2}")) +x.add_system("C1", IFUNC, (r"\text{Constraint 1}", r"g_1=3.16-y_1")) +x.add_system("C2", IFUNC, (r"\text{Constraint 2}", r"g_2=y_2-24.0")) + +x.connect("D1", "D2", r"y_1") +x.connect("D1", "Obj", r"y_1") +x.connect("D1", "C1", r"y_1") +x.connect("D2", "D1", r"y_2") +x.connect("D2", "Obj", r"y_2") +x.connect("D2", "C2", r"y_2") +# x.connect("T", "E", r"trajectory") + +x.add_input("D1", r"x,z_1,z_2") +x.add_input("Obj", r"x,z_1") +x.add_input("D2", r"z_1,z_2") + +x.add_output("Obj", r"f", side="right") +x.add_output("C1", r"g_1", side="right") +x.add_output("C2", r"g_2", side="right") +# x.add_output("T", "trajectory", side="right") +# x.add_output("T", r"n_{dyn} max", side="right") +# x.add_output("T", r"heat max", side="right") +# x.add_output("T", "apogee", side="right") +# x.add_output("T", "perigee", side="right") +x.write("Sellar_normal", build=True) + +x.add_system("Env", METAMODEL, r"\text{LCA}") +x.connect("D1", "Env", r"y_1") +x.connect("D2", "Env", r"y_2") + +x.add_output("Env", r"GWP", side="right") +x.write("Sellar_env", build=True) diff --git a/xdsm/Sellar_env.tex b/xdsm/Sellar_env.tex new file mode 100644 index 0000000..6a8aca6 --- /dev/null +++ b/xdsm/Sellar_env.tex @@ -0,0 +1,27 @@ + +% XDSM diagram created with pyXDSM 2.3.0. +\documentclass{article} +\usepackage{geometry} +\usepackage{amsfonts} +\usepackage{amsmath} +\usepackage{amssymb} +\usepackage{tikz} + +% Optional packages such as sfmath set through python interface +\usepackage{sfmath,sfmath} + +% Define the set of TikZ packages to be included in the architecture diagram document +\usetikzlibrary{arrows,chains,positioning,scopes,shapes.geometric,shapes.misc,shadows} + + +% Set the border around all of the architecture diagrams to be tight to the diagrams themselves +% (i.e. no longer need to tinker with page size parameters) +\usepackage[active,tightpage]{preview} +\PreviewEnvironment{tikzpicture} +\setlength{\PreviewBorder}{5pt} + +\begin{document} + +\input{"Sellar_env.tikz"} + +\end{document} diff --git a/xdsm/Sellar_env.tikz b/xdsm/Sellar_env.tikz new file mode 100644 index 0000000..30683da --- /dev/null +++ b/xdsm/Sellar_env.tikz @@ -0,0 +1,126 @@ + +%%% Preamble Requirements %%% +% \usepackage{geometry} +% \usepackage{amsfonts} +% \usepackage{amsmath} +% \usepackage{amssymb} +% \usepackage{tikz} + +% Optional packages such as sfmath set through python interface +% \usepackage{sfmath,sfmath} + +% \usetikzlibrary{arrows,chains,positioning,scopes,shapes.geometric,shapes.misc,shadows} + +%%% End Preamble Requirements %%% + +\input{"/home/dmsm/t.bellier/anaconda3/envs/LCA_Module/lib/python3.9/site-packages/pyxdsm/diagram_styles"} +\begin{tikzpicture} + +\matrix[MatrixSetup]{ +%Row 0 +\node [DataIO] (output_D1) {$x,z_1,z_2$};& +\node [DataIO] (output_D2) {$z_1,z_2$};& +\node [DataIO] (output_Obj) {$x,z_1$};& +& +& +& +& +\\ +%Row 1 +\node [Function] (D1) {$\begin{array}{c}\text{Discipline 1} \\ y_1 = z_{1}^{2}+z_2+x_1-0.2y_2\end{array}$};& +\node [DataInter] (D1-D2) {$y_1$};& +\node [DataInter] (D1-Obj) {$y_1$};& +\node [DataInter] (D1-C1) {$y_1$};& +& +\node [DataInter] (D1-Env) {$y_1$};& +& +\\ +%Row 2 +\node [DataInter] (D2-D1) {$y_2$};& +\node [Function] (D2) {$\begin{array}{c}\text{Discipline 2} \\ y_2=\sqrt{y_{1}}+z_1+z_2\end{array}$};& +\node [DataInter] (D2-Obj) {$y_2$};& +& +\node [DataInter] (D2-C2) {$y_2$};& +\node [DataInter] (D2-Env) {$y_2$};& +& +\\ +%Row 3 +& +& +\node [ImplicitFunction] (Obj) {$\begin{array}{c}\text{Objective} \\ f=x^{2}+z_1+y_1+e^{-y_2}\end{array}$};& +& +& +& +& +\node [DataIO] (right_output_Obj) {$f$};\\ +%Row 4 +& +& +& +\node [ImplicitFunction] (C1) {$\begin{array}{c}\text{Constraint 1} \\ g_1=3.16-y_1\end{array}$};& +& +& +& +\node [DataIO] (right_output_C1) {$g_1$};\\ +%Row 5 +& +& +& +& +\node [ImplicitFunction] (C2) {$\begin{array}{c}\text{Constraint 2} \\ g_2=y_2-24.0\end{array}$};& +& +& +\node [DataIO] (right_output_C2) {$g_2$};\\ +%Row 6 +& +& +& +& +& +\node [Metamodel] (Env) {$\text{LCA}$};& +& +\node [DataIO] (right_output_Env) {$GWP$};\\ +%Row 7 +& +& +& +& +& +& +& +\\ +}; + +% XDSM process chains + + +\begin{pgfonlayer}{data} +\path +% Horizontal edges +(D1) edge [DataLine] (D1-D2) +(D1) edge [DataLine] (D1-Obj) +(D1) edge [DataLine] (D1-C1) +(D2) edge [DataLine] (D2-D1) +(D2) edge [DataLine] (D2-Obj) +(D2) edge [DataLine] (D2-C2) +(D1) edge [DataLine] (D1-Env) +(D2) edge [DataLine] (D2-Env) +(Obj) edge [DataLine] (right_output_Obj) +(C1) edge [DataLine] (right_output_C1) +(C2) edge [DataLine] (right_output_C2) +(Env) edge [DataLine] (right_output_Env) +% Vertical edges +(D1-D2) edge [DataLine] (D2) +(D1-Obj) edge [DataLine] (Obj) +(D1-C1) edge [DataLine] (C1) +(D2-D1) edge [DataLine] (D1) +(D2-Obj) edge [DataLine] (Obj) +(D2-C2) edge [DataLine] (C2) +(D1-Env) edge [DataLine] (Env) +(D2-Env) edge [DataLine] (Env) +(D1) edge [DataLine] (output_D1) +(Obj) edge [DataLine] (output_Obj) +(D2) edge [DataLine] (output_D2); +\end{pgfonlayer} + +\end{tikzpicture} diff --git a/xdsm/Sellar_normal.tex b/xdsm/Sellar_normal.tex new file mode 100644 index 0000000..b735973 --- /dev/null +++ b/xdsm/Sellar_normal.tex @@ -0,0 +1,27 @@ + +% XDSM diagram created with pyXDSM 2.3.0. +\documentclass{article} +\usepackage{geometry} +\usepackage{amsfonts} +\usepackage{amsmath} +\usepackage{amssymb} +\usepackage{tikz} + +% Optional packages such as sfmath set through python interface +\usepackage{sfmath} + +% Define the set of TikZ packages to be included in the architecture diagram document +\usetikzlibrary{arrows,chains,positioning,scopes,shapes.geometric,shapes.misc,shadows} + + +% Set the border around all of the architecture diagrams to be tight to the diagrams themselves +% (i.e. no longer need to tinker with page size parameters) +\usepackage[active,tightpage]{preview} +\PreviewEnvironment{tikzpicture} +\setlength{\PreviewBorder}{5pt} + +\begin{document} + +\input{"Sellar_normal.tikz"} + +\end{document} diff --git a/xdsm/Sellar_normal.tikz b/xdsm/Sellar_normal.tikz new file mode 100644 index 0000000..47871c3 --- /dev/null +++ b/xdsm/Sellar_normal.tikz @@ -0,0 +1,105 @@ + +%%% Preamble Requirements %%% +% \usepackage{geometry} +% \usepackage{amsfonts} +% \usepackage{amsmath} +% \usepackage{amssymb} +% \usepackage{tikz} + +% Optional packages such as sfmath set through python interface +% \usepackage{sfmath} + +% \usetikzlibrary{arrows,chains,positioning,scopes,shapes.geometric,shapes.misc,shadows} + +%%% End Preamble Requirements %%% + +\input{"/home/dmsm/t.bellier/anaconda3/envs/LCA_Module/lib/python3.9/site-packages/pyxdsm/diagram_styles"} +\begin{tikzpicture} + +\matrix[MatrixSetup]{ +%Row 0 +\node [DataIO] (output_D1) {$x,z_1,z_2$};& +\node [DataIO] (output_D2) {$z_1,z_2$};& +\node [DataIO] (output_Obj) {$x,z_1$};& +& +& +& +\\ +%Row 1 +\node [Function] (D1) {$\begin{array}{c}\text{Discipline 1} \\ y_1 = z_{1}^{2}+z_2+x_1-0.2y_2\end{array}$};& +\node [DataInter] (D1-D2) {$y_1$};& +\node [DataInter] (D1-Obj) {$y_1$};& +\node [DataInter] (D1-C1) {$y_1$};& +& +& +\\ +%Row 2 +\node [DataInter] (D2-D1) {$y_2$};& +\node [Function] (D2) {$\begin{array}{c}\text{Discipline 2} \\ y_2=\sqrt{y_{1}}+z_1+z_2\end{array}$};& +\node [DataInter] (D2-Obj) {$y_2$};& +& +\node [DataInter] (D2-C2) {$y_2$};& +& +\\ +%Row 3 +& +& +\node [ImplicitFunction] (Obj) {$\begin{array}{c}\text{Objective} \\ f=x^{2}+z_1+y_1+e^{-y_2}\end{array}$};& +& +& +& +\node [DataIO] (right_output_Obj) {$f$};\\ +%Row 4 +& +& +& +\node [ImplicitFunction] (C1) {$\begin{array}{c}\text{Constraint 1} \\ g_1=3.16-y_1\end{array}$};& +& +& +\node [DataIO] (right_output_C1) {$g_1$};\\ +%Row 5 +& +& +& +& +\node [ImplicitFunction] (C2) {$\begin{array}{c}\text{Constraint 2} \\ g_2=y_2-24.0\end{array}$};& +& +\node [DataIO] (right_output_C2) {$g_2$};\\ +%Row 6 +& +& +& +& +& +& +\\ +}; + +% XDSM process chains + + +\begin{pgfonlayer}{data} +\path +% Horizontal edges +(D1) edge [DataLine] (D1-D2) +(D1) edge [DataLine] (D1-Obj) +(D1) edge [DataLine] (D1-C1) +(D2) edge [DataLine] (D2-D1) +(D2) edge [DataLine] (D2-Obj) +(D2) edge [DataLine] (D2-C2) +(Obj) edge [DataLine] (right_output_Obj) +(C1) edge [DataLine] (right_output_C1) +(C2) edge [DataLine] (right_output_C2) +% Vertical edges +(D1-D2) edge [DataLine] (D2) +(D1-Obj) edge [DataLine] (Obj) +(D1-C1) edge [DataLine] (C1) +(D2-D1) edge [DataLine] (D1) +(D2-Obj) edge [DataLine] (Obj) +(D2-C2) edge [DataLine] (C2) +(D1) edge [DataLine] (output_D1) +(Obj) edge [DataLine] (output_Obj) +(D2) edge [DataLine] (output_D2); +\end{pgfonlayer} + +\end{tikzpicture}