def create_evaluables(self): variables = self.dpb.create_variables().as_dict() possible_mat_names = get_expression_arg_names(self.obj_fun_term) materials = self.dpb.create_materials(possible_mat_names).as_dict() aux = self.dpb.create_evaluable(self.obj_fun_term, try_equations=False, var_dict=variables, **materials) self.of_equations, self.of_variables = aux possible_mat_names = get_expression_arg_names(self.sens_terms) materials = self.apb.create_materials(possible_mat_names).as_dict() aux = self.apb.create_evaluable(self.sens_terms, try_equations=False, var_dict=variables, **materials) self.ofg_equations, self.ofg_variables = aux
def create_evaluable(self, expression, try_equations=True, auto_init=False, preserve_caches=False, copy_materials=True, integrals=None, ebcs=None, epbcs=None, lcbcs=None, ts=None, functions=None, mode='eval', var_dict=None, extra_args=None, verbose=True, **kwargs): """ Create evaluable object (equations and corresponding variables) from the `expression` string. Convenience function calling :func:`create_evaluable() <sfepy.fem.evaluate.create_evaluable()>` with defaults provided by the ProblemDefinition instance `self`. The evaluable can be repeatedly evaluated by calling :func:`eval_equations() <sfepy.fem.evaluate.eval_equations()>`, e.g. for different values of variables. Parameters ---------- expression : str The expression to evaluate. try_equations : bool Try to get variables from `self.equations`. If this fails, variables can either be provided in `var_dict`, as keyword arguments, or are created automatically according to the expression. auto_init : bool Set values of all variables to all zeros. preserve_caches : bool If True, do not invalidate evaluate caches of variables. copy_materials : bool Work with a copy of `self.equations.materials` instead of reusing them. Safe but can be slow. integrals : Integrals instance, optional The integrals to be used. Automatically created as needed if not given. ebcs : Conditions instance, optional The essential (Dirichlet) boundary conditions for 'weak' mode. If not given, `self.ebcs` are used. epbcs : Conditions instance, optional The periodic boundary conditions for 'weak' mode. If not given, `self.epbcs` are used. lcbcs : Conditions instance, optional The linear combination boundary conditions for 'weak' mode. If not given, `self.lcbcs` are used. ts : TimeStepper instance, optional The time stepper. If not given, `self.ts` is used. functions : Functions instance, optional The user functions for boundary conditions, materials etc. If not given, `self.functions` are used. mode : one of 'eval', 'el_avg', 'qp', 'weak' The evaluation mode - 'weak' means the finite element assembling, 'qp' requests the values in quadrature points, 'el_avg' element averages and 'eval' means integration over each term region. var_dict : dict, optional The variables (dictionary of (variable name) : (Variable instance)) to be used in the expression. Use this if the name of a variable conflicts with one of the parameters of this method. extra_args : dict, optional Extra arguments to be passed to terms in the expression. verbose : bool If False, reduce verbosity. **kwargs : keyword arguments Additional variables can be passed as keyword arguments, see `var_dict`. Returns ------- equations : Equations instance The equations that can be evaluated. variables : Variables instance The corresponding variables. Set their values and use :func:`eval_equations() <sfepy.fem.evaluate.eval_equations()>`. Examples -------- `problem` is ProblemDefinition instance. >>> out = problem.create_evaluable('dq_state_in_volume_qp.i1.Omega(u)') >>> equations, variables = out `vec` is a vector of coefficients compatible with the field of 'u' - let's use all ones. >>> vec = nm.ones((variables['u'].n_dof,), dtype=nm.float64) >>> variables['u'].data_from_any(vec) >>> vec_qp = eval_equations(equations, variables, mode='qp') Try another vector: >>> vec = 3 * nm.ones((variables['u'].n_dof,), dtype=nm.float64) >>> variables['u'].data_from_any(vec) >>> vec_qp = eval_equations(equations, variables, mode='qp') """ from sfepy.fem.equations import get_expression_arg_names variables = get_default(var_dict, {}) if try_equations and self.equations is not None: # Make a copy, so that possible variable caches are preserved. for key, var in self.equations.variables.as_dict().iteritems(): if key in variables: continue var = var.copy(name=key) if not preserve_caches: var.clear_evaluate_cache() variables[key] = var elif var_dict is None: possible_var_names = get_expression_arg_names(expression) variables = self.create_variables(possible_var_names) materials = self.get_materials() if materials is not None: if copy_materials: materials = materials.semideep_copy() else: materials = Materials(objs=materials._objs) else: possible_mat_names = get_expression_arg_names(expression) materials = self.create_materials(possible_mat_names) _kwargs = copy(kwargs) for key, val in kwargs.iteritems(): if isinstance(val, Variable): if val.name != key: msg = 'inconsistent variable name! (%s == %s)' \ % (val.name, key) raise ValueError(msg) variables[val.name] = val _kwargs.pop(key) elif isinstance(val, Material): if val.name != key: msg = 'inconsistent material name! (%s == %s)' \ % (val.name, key) raise ValueError(msg) materials[val.name] = val _kwargs.pop(key) kwargs = _kwargs ebcs = get_default(ebcs, self.ebcs) epbcs = get_default(epbcs, self.epbcs) lcbcs = get_default(lcbcs, self.lcbcs) ts = get_default(ts, self.get_timestepper()) functions = get_default(functions, self.functions) integrals = get_default(integrals, self.get_integrals()) out = create_evaluable(expression, self.fields, materials, variables.itervalues(), integrals, ebcs=ebcs, epbcs=epbcs, lcbcs=lcbcs, ts=ts, functions=functions, auto_init=auto_init, mode=mode, extra_args=extra_args, verbose=verbose, kwargs=kwargs) if copy_materials: equations = out[0] equations.time_update_materials(self.ts, self, verbose=verbose) return out
def check_custom_sensitivity(self, term_desc, idsg, delta, dp_var_data, state_ap): pb = self.apb domain = pb.domain possible_mat_names = get_expression_arg_names(term_desc) materials = self.dpb.create_materials(possible_mat_names).as_dict() variables = self.ofg_equations.variables aux = self.dpb.create_evaluable(term_desc, try_equations=False, var_dict=variables, verbose=False, **materials) check0_equations, check0_variables = aux aux = self.dpb.create_evaluable(term_desc, try_equations=False, var_dict=variables, verbose=False, **materials) check1_equations, check1_variables = aux var_data = state_ap.get_parts() var_data.update(dp_var_data) check0_equations.set_data(var_data, ignore_unknown=True) check1_equations.set_data(var_data, ignore_unknown=True) dim = self.sp_boxes.dim n_mesh_nod = domain.shape.n_nod a_grad = [] d_grad = [] coors0 = domain.mesh.coors for nu in self.generate_mesh_velocity( (n_mesh_nod, dim), [idsg] ): check1_variables['Nu'].set_data(nu.ravel()) aux = eval_equations(check1_equations, check1_variables, term_mode=1) a_grad.append( aux ) coorsp = coors0 + delta * nu pb.set_mesh_coors( coorsp, update_fields=True ) valp = eval_equations(check0_equations, check0_variables, term_mode=0) coorsm = coors0 - delta * nu pb.set_mesh_coors( coorsm, update_fields=True ) valm = eval_equations(check0_equations, check0_variables, term_mode=0) d_grad.append( 0.5 * (valp - valm) / delta ) pb.set_mesh_coors( coors0, update_fields=True ) a_grad = nm.array( a_grad, nm.float64 ) d_grad = nm.array( d_grad, nm.float64 ) output( term_desc + ':' ) output( ' a: %.8e' % a_grad ) output( ' d: %.8e' % d_grad ) output( '-> ratio:', a_grad / d_grad ) pause()
def create_evaluable(self, expression, try_equations=True, auto_init=False, preserve_caches=False, copy_materials=True, integrals=None, ebcs=None, epbcs=None, lcbcs=None, ts=None, functions=None, mode='eval', var_dict=None, strip_variables=True, extra_args=None, verbose=True, **kwargs): """ Create evaluable object (equations and corresponding variables) from the `expression` string. Convenience function calling :func:`create_evaluable() <sfepy.fem.evaluate.create_evaluable()>` with defaults provided by the ProblemDefinition instance `self`. The evaluable can be repeatedly evaluated by calling :func:`eval_equations() <sfepy.fem.evaluate.eval_equations()>`, e.g. for different values of variables. Parameters ---------- expression : str The expression to evaluate. try_equations : bool Try to get variables from `self.equations`. If this fails, variables can either be provided in `var_dict`, as keyword arguments, or are created automatically according to the expression. auto_init : bool Set values of all variables to all zeros. preserve_caches : bool If True, do not invalidate evaluate caches of variables. copy_materials : bool Work with a copy of `self.equations.materials` instead of reusing them. Safe but can be slow. integrals : Integrals instance, optional The integrals to be used. Automatically created as needed if not given. ebcs : Conditions instance, optional The essential (Dirichlet) boundary conditions for 'weak' mode. If not given, `self.ebcs` are used. epbcs : Conditions instance, optional The periodic boundary conditions for 'weak' mode. If not given, `self.epbcs` are used. lcbcs : Conditions instance, optional The linear combination boundary conditions for 'weak' mode. If not given, `self.lcbcs` are used. ts : TimeStepper instance, optional The time stepper. If not given, `self.ts` is used. functions : Functions instance, optional The user functions for boundary conditions, materials etc. If not given, `self.functions` are used. mode : one of 'eval', 'el_avg', 'qp', 'weak' The evaluation mode - 'weak' means the finite element assembling, 'qp' requests the values in quadrature points, 'el_avg' element averages and 'eval' means integration over each term region. var_dict : dict, optional The variables (dictionary of (variable name) : (Variable instance)) to be used in the expression. Use this if the name of a variable conflicts with one of the parameters of this method. strip_variables : bool If False, the variables in `var_dict` or `kwargs` not present in the expression are added to the actual variables as a context. extra_args : dict, optional Extra arguments to be passed to terms in the expression. verbose : bool If False, reduce verbosity. **kwargs : keyword arguments Additional variables can be passed as keyword arguments, see `var_dict`. Returns ------- equations : Equations instance The equations that can be evaluated. variables : Variables instance The corresponding variables. Set their values and use :func:`eval_equations() <sfepy.fem.evaluate.eval_equations()>`. Examples -------- `problem` is ProblemDefinition instance. >>> out = problem.create_evaluable('dq_state_in_volume_qp.i1.Omega(u)') >>> equations, variables = out `vec` is a vector of coefficients compatible with the field of 'u' - let's use all ones. >>> vec = nm.ones((variables['u'].n_dof,), dtype=nm.float64) >>> variables['u'].set_data(vec) >>> vec_qp = eval_equations(equations, variables, mode='qp') Try another vector: >>> vec = 3 * nm.ones((variables['u'].n_dof,), dtype=nm.float64) >>> variables['u'].set_data(vec) >>> vec_qp = eval_equations(equations, variables, mode='qp') """ from sfepy.fem.equations import get_expression_arg_names variables = get_default(var_dict, {}) var_context = get_default(var_dict, {}) if try_equations and self.equations is not None: # Make a copy, so that possible variable caches are preserved. for key, var in self.equations.variables.as_dict().iteritems(): if key in variables: continue var = var.copy(name=key) if not preserve_caches: var.clear_evaluate_cache() variables[key] = var elif var_dict is None: possible_var_names = get_expression_arg_names(expression) variables = self.create_variables(possible_var_names) materials = self.get_materials() if materials is not None: if copy_materials: materials = materials.semideep_copy() else: materials = Materials(objs=materials._objs) else: possible_mat_names = get_expression_arg_names(expression) materials = self.create_materials(possible_mat_names) _kwargs = copy(kwargs) for key, val in kwargs.iteritems(): if isinstance(val, Variable): if val.name != key: msg = 'inconsistent variable name! (%s == %s)' \ % (val.name, key) raise ValueError(msg) var_context[val.name] = variables[val.name] = val _kwargs.pop(key) elif isinstance(val, Material): if val.name != key: msg = 'inconsistent material name! (%s == %s)' \ % (val.name, key) raise ValueError(msg) materials[val.name] = val _kwargs.pop(key) kwargs = _kwargs ebcs = get_default(ebcs, self.ebcs) epbcs = get_default(epbcs, self.epbcs) lcbcs = get_default(lcbcs, self.lcbcs) ts = get_default(ts, self.get_timestepper()) functions = get_default(functions, self.functions) integrals = get_default(integrals, self.get_integrals()) out = create_evaluable(expression, self.fields, materials, variables.itervalues(), integrals, ebcs=ebcs, epbcs=epbcs, lcbcs=lcbcs, ts=ts, functions=functions, auto_init=auto_init, mode=mode, extra_args=extra_args, verbose=verbose, kwargs=kwargs) if not strip_variables: variables = out[1] variables.extend([ var for var in var_context.itervalues() if var not in variables ]) equations = out[0] mode = 'update' if not copy_materials else 'normal' equations.time_update_materials(self.ts, mode=mode, problem=self, verbose=verbose) return out