Source code for flow360.component.flow360_params.flow360_output
"""Flow360 output parameters models"""from__future__importannotationsfromabcimportABCMetafromtypingimportList,Literal,Optional,Union,get_argsimportpydanticaspdfrompydanticimportconlistfrom..typesimportAxis,Coordinate,NonNegativeAndNegOneInt,PositiveAndNegOneIntfrom.flow360_fieldsimport(CommonFieldNames,CommonFieldNamesFull,IsoSurfaceFieldNames,IsoSurfaceFieldNamesFull,SliceFieldNames,SliceFieldNamesFull,SurfaceFieldNames,SurfaceFieldNamesFull,VolumeFieldNames,VolumeFieldNamesFull,get_field_values,to_short,)from.flow360_legacyimportLegacyModel,get_output_fieldsfrom.params_baseimport(Flow360BaseModel,Flow360SortableBaseModel,_self_named_property_validator,)from.unit_systemimportFlow360UnitSystem,LengthTypeOutputFormat=Literal["paraview","tecplot","both"]CommonFields=Literal[CommonFieldNames,CommonFieldNamesFull]SurfaceFields=Literal[SurfaceFieldNames,SurfaceFieldNamesFull]SliceFields=Literal[SliceFieldNames,SliceFieldNamesFull]VolumeFields=Literal[VolumeFieldNames,VolumeFieldNamesFull]IsoSurfaceFields=Literal[IsoSurfaceFieldNames,IsoSurfaceFieldNamesFull]CommonOutputFields=conlist(CommonFields,unique_items=True)SurfaceOutputFields=conlist(SurfaceFields,unique_items=True)SliceOutputFields=conlist(SliceFields,unique_items=True)VolumeOutputFields=conlist(VolumeFields,unique_items=True)IsoSurfaceOutputField=IsoSurfaceFieldsdef_filter_fields(fields,literal_filter):"""Take two literals, keep only arguments present in the filter"""values=get_field_values(literal_filter)fields[:]=[fieldforfieldinfieldsiffieldinvalues]def_distribute_shared_output_fields(solver_values:dict,item_names:str):shared_fields=solver_values.pop("output_fields")ifshared_fieldsisNone:returnshared_fields=[to_short(field)forfieldinshared_fields]ifsolver_values[item_names]isnotNone:fornameinsolver_values[item_names].names():item=solver_values[item_names][name]forfieldinshared_fields:ifitem.output_fieldsisNone:item.output_fields=[]iffieldnotinitem.output_fields:item.output_fields.append(field)
classAnimatedOutput(pd.BaseModel,metaclass=ABCMeta):""":class:`AnimatedOutput` class"""output_format:Optional[OutputFormat]=pd.Field(alias="outputFormat",default="paraview")animation_frequency:Optional[PositiveAndNegOneInt]=pd.Field(alias="animationFrequency",options=["Animated","Static"],default=-1)animation_frequency_offset:Optional[int]=pd.Field(alias="animationFrequencyOffset",default=0)# Temporarily disabled until solver-side support for new animation format is introduced""" animation_settings: Optional[AnimationSettings] = pd.Field(alias="animationSettings") # pylint: disable=unused-argument def to_solver(self, params, **kwargs) -> AnimatedOutput: # Convert animation settings (UI representation) to solver representation if self.animation_settings is not None: if self.animation_settings.frequency is not None: self.animation_frequency = self.animation_settings.frequency else: self.animation_frequency = -1 if self.animation_settings.frequency_offset is not None: self.animation_frequency_offset = self.animation_settings.frequency_offset else: self.animation_frequency_offset = 0 solver_animations = self.__class__( animation_frequency=self.animation_frequency, animation_frequency_offset=self.animation_frequency_offset, ) return solver_animations """classTimeAverageAnimatedOutput(AnimatedOutput,metaclass=ABCMeta):""":class:`TimeAverageAnimatedOutput` class"""compute_time_averages:Optional[bool]=pd.Field(alias="computeTimeAverages",default=False)animation_frequency_time_average:Optional[PositiveAndNegOneInt]=pd.Field(alias="animationFrequencyTimeAverage",options=["Animated","Static"],default=-1)animation_frequency_time_average_offset:Optional[int]=pd.Field(alias="animationFrequencyTimeAverageOffset",default=0)start_average_integration_step:Optional[NonNegativeAndNegOneInt]=pd.Field(alias="startAverageIntegrationStep",default=-1,options=["From step","No averaging"])# Temporarily disabled until solver-side support for new animation format is introduced""" animation_settings: Optional[AnimationSettingsExtended] = pd.Field(alias="animationSettings") # pylint: disable=unused-argument def to_solver(self, params, **kwargs) -> TimeAverageAnimatedOutput: if self.animation_settings is not None: if self.animation_settings.frequency is not None: self.animation_frequency = self.animation_settings.frequency else: self.animation_frequency = -1 if self.animation_settings.frequency_offset is not None: self.animation_frequency_offset = self.animation_settings.frequency_offset else: self.animation_frequency_offset = 0 if self.animation_settings.frequency_time_average is not None: self.animation_frequency_time_average = ( self.animation_settings.frequency_time_average ) else: self.animation_frequency_time_average = -1 if self.animation_settings.frequency_time_average_offset is not None: self.animation_frequency_time_average_offset = ( self.animation_settings.frequency_time_average_offset ) else: self.animation_frequency_time_average_offset = 0 solver_animations = self.__class__( animation_frequency=self.animation_frequency, animation_frequency_offset=self.animation_frequency_offset, ) return solver_animations"""classSurface(Flow360BaseModel):""":class:`Surface` class"""output_fields:Optional[SurfaceOutputFields]=pd.Field(alias="outputFields",displayed="Output fields",default=[])# pylint: disable=too-few-public-methodsclassConfig(Flow360BaseModel.Config):""":class: Model config to cull output field shorthands"""# pylint: disable=unused-argument@staticmethoddefschema_extra(schema,model):"""Remove output field shorthands from schema"""_filter_fields(schema["properties"]["outputFields"]["items"]["enum"],SurfaceFieldNamesFull)class_GenericSurfaceWrapper(Flow360BaseModel):""":class:`_GenericSurfaceWrapper` class"""v:Surface
[docs]@pd.root_validator(pre=True)defvalidate_surface(cls,values):""" root validator """return_self_named_property_validator(values,_GenericSurfaceWrapper,msg="is not any of supported surface types.")
[docs]classSurfaceOutput(Flow360BaseModel,TimeAverageAnimatedOutput):""":class:`SurfaceOutput` class"""write_single_file:Optional[bool]=pd.Field(alias="writeSingleFile",default=False)output_fields:Optional[SurfaceOutputFields]=pd.Field(alias="outputFields",default=[])surfaces:Optional[Surfaces]=pd.Field()# pylint: disable=too-few-public-methodsclassConfig(Flow360BaseModel.Config):""":class: Model config to cull output field shorthands"""# pylint: disable=unused-argument@staticmethoddefschema_extra(schema,model):"""Remove output field shorthands from schema"""_filter_fields(schema["properties"]["outputFields"]["items"]["enum"],SurfaceFieldNamesFull)# pylint: disable=arguments-differ
[docs]defto_solver(self,params,**kwargs)->SurfaceOutput:solver_model=super().to_solver(params,**kwargs)solver_values=solver_model.__dict__# Add boundaries that are not listed into `surfaces` and applying shared fields.boundary_names=[]forboundary_nameinparams.boundaries.names():boundary=params.boundaries[boundary_name]ifboundary.nameisnotNone:boundary_names.append(boundary.name)else:boundary_names.append(boundary_name)ifsolver_values["surfaces"]isNone:solver_values["surfaces"]=Surfaces()forboundary_nameinboundary_names:ifboundary_namenotinsolver_values["surfaces"].names():solver_values["surfaces"][boundary_name]=Surface()solver_values["surfaces"][boundary_name].output_fields=[]_distribute_shared_output_fields(solver_values,"surfaces")returnSurfaceOutput(**solver_values)
[docs]classSlice(Flow360BaseModel):""":class:`NamedSlice` class"""slice_normal:Axis=pd.Field(alias="sliceNormal")slice_origin:LengthType.Point=pd.Field(alias="sliceOrigin")output_fields:Optional[SliceOutputFields]=pd.Field(alias="outputFields",default=[])# pylint: disable=too-few-public-methodsclassConfig(Flow360BaseModel.Config):""":class: Model config to cull output field shorthands"""# pylint: disable=unused-argument@staticmethoddefschema_extra(schema,model):"""Remove output field shorthands from schema"""_filter_fields(schema["properties"]["outputFields"]["items"]["enum"],VolumeFieldNamesFull)# pylint: disable=arguments-differ
[docs]@pd.root_validator(pre=True)defvalidate_slice(cls,values):""" root validator """return_self_named_property_validator(values,_GenericSliceWrapper,msg="is not any of supported slice types.")
[docs]classSliceOutput(Flow360BaseModel,AnimatedOutput):""":class:`SliceOutput` class"""output_fields:Optional[SliceOutputFields]=pd.Field(alias="outputFields",default=[])slices:Slices=pd.Field()# pylint: disable=too-few-public-methodsclassConfig(Flow360BaseModel.Config):""":class: Model config to cull output field shorthands"""# pylint: disable=unused-argument@staticmethoddefschema_extra(schema,model):"""Remove output field shorthands from schema"""_filter_fields(schema["properties"]["outputFields"]["items"]["enum"],VolumeFieldNamesFull)# pylint: disable=arguments-differ
[docs]classVolumeOutput(Flow360BaseModel,TimeAverageAnimatedOutput):""":class:`VolumeOutput` class"""output_fields:Optional[VolumeOutputFields]=pd.Field(alias="outputFields",default=["primitiveVars","Cp","mut","Mach"])# pylint: disable=too-few-public-methodsclassConfig(Flow360BaseModel.Config):""":class: Model config to cull output field shorthands"""# pylint: disable=unused-argument@staticmethoddefschema_extra(schema,model):"""Remove output field shorthands from schema"""_filter_fields(schema["properties"]["outputFields"]["items"]["enum"],VolumeFieldNamesFull)# pylint: disable=arguments-differ
[docs]classSurfaceIntegralMonitor(MonitorBase):""":class:`SurfaceIntegralMonitor` class"""type:Literal["surfaceIntegral"]=pd.Field("surfaceIntegral",const=True)surfaces:List[str]=pd.Field()output_fields:Optional[CommonOutputFields]=pd.Field(alias="outputFields",default=[])# pylint: disable=too-few-public-methodsclassConfig(Flow360BaseModel.Config):""":class: Model config to cull output field shorthands"""# pylint: disable=unused-argument@staticmethoddefschema_extra(schema,model):"""Remove output field shorthands from schema"""_filter_fields(schema["properties"]["outputFields"]["items"]["enum"],CommonFieldNamesFull)# pylint: disable=arguments-differ
[docs]classProbeMonitor(MonitorBase):""":class:`ProbeMonitor` class"""type:Literal["probe"]=pd.Field("probe",const=True)monitor_locations:List[Coordinate]=pd.Field(alias="monitorLocations")output_fields:Optional[CommonOutputFields]=pd.Field(alias="outputFields",default=[])# pylint: disable=too-few-public-methodsclassConfig(Flow360BaseModel.Config):""":class: Model config to cull output field shorthands"""# pylint: disable=unused-argument@staticmethoddefschema_extra(schema,model):"""Remove output field shorthands from schema"""_filter_fields(schema["properties"]["outputFields"]["items"]["enum"],CommonFieldNamesFull)# pylint: disable=arguments-differ
[docs]@pd.root_validator(pre=True)defvalidate_monitor(cls,values):""" root validator """return_self_named_property_validator(values,_GenericMonitorWrapper,msg="is not any of supported monitor types.")
[docs]classMonitorOutput(Flow360BaseModel):""":class:`MonitorOutput` class"""monitors:Monitors=pd.Field()output_fields:Optional[CommonOutputFields]=pd.Field(alias="outputFields",default=[])# pylint: disable=too-few-public-methodsclassConfig(Flow360BaseModel.Config):""":class: Model config to cull output field shorthands"""# pylint: disable=unused-argument@staticmethoddefschema_extra(schema,model):"""Remove output field shorthands from schema"""_filter_fields(schema["properties"]["outputFields"]["items"]["enum"],CommonFieldNamesFull)# pylint: disable=arguments-differ
classIsoSurface(Flow360BaseModel):""":class:`IsoSurface` class"""surface_field:IsoSurfaceOutputField=pd.Field(alias="surfaceField")surface_field_magnitude:float=pd.Field(alias="surfaceFieldMagnitude")output_fields:Optional[CommonOutputFields]=pd.Field(alias="outputFields",default=[])# pylint: disable=too-few-public-methodsclassConfig(Flow360BaseModel.Config):""":class: Model config to cull output field shorthands"""# pylint: disable=unused-argument@staticmethoddefschema_extra(schema,model):"""Remove output field shorthands from schema"""_filter_fields(schema["properties"]["outputFields"]["items"]["enum"],CommonFieldNamesFull)_filter_fields(schema["properties"]["surfaceField"]["enum"],IsoSurfaceFieldNamesFull)# pylint: disable=arguments-differdefto_solver(self,params,**kwargs)->IsoSurface:solver_model=super().to_solver(params,**kwargs)solver_values=solver_model.__dict__fields=solver_values.pop("output_fields")fields=[to_short(field)forfieldinfields]returnIsoSurface(**solver_values,output_fields=fields)class_GenericIsoSurfaceWrapper(Flow360BaseModel):""":class:`_GenericIsoSurfaceWrapper` class"""v:IsoSurface
[docs]@pd.root_validator(pre=True)defvalidate_monitor(cls,values):""" root validator """return_self_named_property_validator(values,_GenericIsoSurfaceWrapper,msg="is not any of supported surface types.")
[docs]classAeroacousticOutput(Flow360BaseModel):""":class:`AeroacousticOutput` class for configuring output data about acoustic pressure signals Parameters ---------- observers : List[Coordinate] List of observer locations at which time history of acoustic pressure signal is stored in aeroacoustic output file. The observer locations can be outside the simulation domain, but cannot be inside the solid surfaces of the simulation domain. Returns ------- :class:`AeroacousticOutput` An instance of the component class AeroacousticOutput. Example ------- >>> aeroacoustics = AeroacousticOutput(observers=[(0, 0, 0), (1, 1, 1)]) """patch_type:Optional[str]=pd.Field("solid",const=True,alias="patchType")observers:List[Coordinate]=pd.Field()write_per_surface_output:Optional[bool]=pd.Field(False,alias="writePerSurfaceOutput")
classLegacyOutputFormat(pd.BaseModel,metaclass=ABCMeta):""":class: Base class for common output parameters"""Cp:Optional[bool]=pd.Field()grad_w:Optional[bool]=pd.Field(alias="gradW")k_omega:Optional[bool]=pd.Field(alias="kOmega")Mach:Optional[bool]=pd.Field(alias="Mach")mut:Optional[bool]=pd.Field()mut_ratio:Optional[bool]=pd.Field(alias="mutRatio")nu_hat:Optional[bool]=pd.Field(alias="nuHat")primitive_vars:Optional[bool]=pd.Field(alias="primitiveVars")q_criterion:Optional[bool]=pd.Field(alias="qcriterion")residual_navier_stokes:Optional[bool]=pd.Field(alias="residualNavierStokes")residual_transition:Optional[bool]=pd.Field(alias="residualTransition")residual_turbulence:Optional[bool]=pd.Field(alias="residualTurbulence")s:Optional[bool]=pd.Field()solution_navier_stokes:Optional[bool]=pd.Field(alias="solutionNavierStokes")solution_turbulence:Optional[bool]=pd.Field(alias="solutionTurbulence")solution_transition:Optional[bool]=pd.Field(alias="solutionTransition")T:Optional[bool]=pd.Field(alias="T")vorticity:Optional[bool]=pd.Field()wall_distance:Optional[bool]=pd.Field(alias="wallDistance")low_numerical_dissipation_sensor:Optional[bool]=pd.Field(alias="lowNumericalDissipationSensor")residual_heat_solver:Optional[bool]=pd.Field(alias="residualHeatSolver")low_mach_preconditioner_sensor:Optional[bool]=pd.Field(alias="lowMachPreconditionerSensor")# pylint: disable=too-many-ancestorsclassSurfaceOutputLegacy(SurfaceOutput,LegacyOutputFormat,LegacyModel):""":class:`SurfaceOutputLegacy` class"""wall_function_metric:Optional[bool]=pd.Field(alias="wallFunctionMetric")node_moments_per_unit_area:Optional[bool]=pd.Field(alias="nodeMomentsPerUnitArea")residual_sa:Optional[bool]=pd.Field(alias="residualSA")coarsen_iterations:Optional[int]=pd.Field(alias="coarsenIterations")Cf:Optional[bool]=pd.Field(alias="Cf")Cf_vec:Optional[bool]=pd.Field(alias="CfVec")Cf_normal:Optional[bool]=pd.Field(alias="CfNormal")Cf_tangent:Optional[bool]=pd.Field(alias="CfTangent")y_plus:Optional[bool]=pd.Field(alias="yPlus")wall_distance:Optional[bool]=pd.Field(alias="wallDistance")heat_flux:Optional[bool]=pd.Field(alias="heatFlux")node_forces_per_unit_area:Optional[bool]=pd.Field(alias="nodeForcesPerUnitArea")node_normals:Optional[bool]=pd.Field(alias="nodeNormals")velocity_relative:Optional[bool]=pd.Field(alias="VelocityRelative")defupdate_model(self)->Flow360BaseModel:fields=get_output_fields(self,[],allowed=get_field_values(CommonFieldNames)+get_field_values(SurfaceFieldNames),)ifself.output_fieldsisnotNone:fields+=self.output_fieldsmodel={"animationFrequency":self.animation_frequency,"animationFrequencyOffset":self.animation_frequency_offset,"animationFrequencyTimeAverage":self.animation_frequency_time_average,"animationFrequencyTimeAverageOffset":self.animation_frequency_time_average_offset,"computeTimeAverages":self.compute_time_averages,"outputFormat":self.output_format,"outputFields":fields,"startAverageIntegrationStep":self.start_average_integration_step,}returnSurfaceOutput.parse_obj(model)classSliceNamedLegacy(Flow360BaseModel):""":class:`SliceNamedLegacy` class"""slice_name:str=pd.Field(alias="sliceName")slice_normal:Axis=pd.Field(alias="sliceNormal")slice_origin:Coordinate=pd.Field(alias="sliceOrigin")output_fields:Optional[List[str]]=pd.Field([],alias="outputFields")classSliceOutputLegacy(SliceOutput,LegacyOutputFormat,LegacyModel):""":class:`SliceOutputLegacy` class"""coarsen_iterations:Optional[int]=pd.Field(alias="coarsenIterations")bet_metrics:Optional[bool]=pd.Field(alias="betMetrics")bet_metrics_per_disk:Optional[bool]=pd.Field(alias="betMetricsPerDisk")slices:Optional[Union[Slices,List[SliceNamedLegacy]]]=pd.Field({})def__init__(self,*args,**kwargs):withFlow360UnitSystem(verbose=False):super().__init__(*args,**kwargs)defupdate_model(self)->Flow360BaseModel:fields=get_output_fields(self,[],allowed=get_field_values(CommonFieldNames)+get_field_values(SliceFieldNames))ifself.output_fieldsisnotNone:fields+=self.output_fieldsmodel={"animationFrequency":self.animation_frequency,"animationFrequencyOffset":self.animation_frequency_offset,"outputFormat":self.output_format,"outputFields":fields,}if(isinstance(self.slices,List)andlen(self.slices)>0andisinstance(self.slices[0],SliceNamedLegacy)):slices={}fornamed_sliceinself.slices:slices[named_slice.slice_name]=Slice(slice_normal=named_slice.slice_normal,slice_origin=named_slice.slice_origin,output_fields=named_slice.output_fields,)model["slices"]=Slices(**slices)elifisinstance(self.slices,Slices):model["slices"]=self.slicesreturnSliceOutput.parse_obj(model)# pylint: disable=too-many-ancestorsclassVolumeOutputLegacy(VolumeOutput,LegacyOutputFormat,LegacyModel):""":class:`VolumeOutputLegacy` class"""write_single_file:Optional[bool]=pd.Field(alias="writeSingleFile")write_distributed_file:Optional[bool]=pd.Field(alias="writeDistributedFile")residual_components_sa:Optional[bool]=pd.Field(alias="residualComponentsSA")wall_distance_dir:Optional[bool]=pd.Field(alias="wallDistanceDir")velocity_relative:Optional[bool]=pd.Field(alias="VelocityRelative")debug_transition:Optional[bool]=pd.Field(alias="debugTransition")debug_turbulence:Optional[bool]=pd.Field(alias="debugTurbulence")debug_navier_stokes:Optional[bool]=pd.Field(alias="debugNavierStokes")bet_metrics:Optional[bool]=pd.Field(alias="betMetrics")bet_metrics_per_disk:Optional[bool]=pd.Field(alias="betMetricsPerDisk")defupdate_model(self)->Flow360BaseModel:fields=get_output_fields(self,["write_single_file","write_distributed_file"],allowed=get_field_values(CommonFieldNames)+get_field_values(VolumeFieldNames),)ifself.output_fieldsisnotNone:foriteminself.output_fields:ifitemnotinfields:fields.append(item)model={"animationFrequency":self.animation_frequency,"animationFrequencyOffset":self.animation_frequency_offset,"animationFrequencyTimeAverage":self.animation_frequency_time_average,"animationFrequencyTimeAverageOffset":self.animation_frequency_time_average_offset,"computeTimeAverages":self.compute_time_averages,"outputFormat":self.output_format,"outputFields":fields,"startAverageIntegrationStep":self.start_average_integration_step,}returnVolumeOutput.parse_obj(model)# Legacy models for Flow360 updater, do not exposeclassIsoSurfaceOutputLegacy(IsoSurfaceOutput,LegacyModel):""":class:`IsoSurfaceOutputLegacy` class"""iso_surfaces:Optional[IsoSurfaces]=pd.Field({},alias="isoSurfaces")defupdate_model(self):fields=get_output_fields(self,[],allowed=get_field_values(CommonFieldNames),)model={"animationFrequency":self.animation_frequency,"animationFrequencyOffset":self.animation_frequency_offset,"outputFormat":self.output_format,"isoSurfaces":self.iso_surfaces,"outputFields":fields,}returnIsoSurfaceOutput.parse_obj(model)