How to use multiple model parts
Using multiple model parts
The problem of handling complex geometries or domains characterized by multiple physical fields, is simplified by the usage of multiple model_parts. As a matter of fact, model_part is intended as a container for
that describe a given part of the model.
The fundamental idea is that most of the information, and in particular the degrees of freedom are stored on the Nodes. Elements and Conditions take care of describing the underlying mathematical structure. All of the informations on the "status" of the model, for example the current TIME or the DELTA_TIME are stored in the ProcessInfo. The Properties take care of keeping trace of the material properties.
Two main usage scenarios rise at this point:
SCENARIO 1 : two different formulations on one domain
This is the case for example of fluid flow + temperature. The two problems share the same volume (and the same discretization of the model) but two distinct problems have to be solved, namely the flow problem and the temperature one.
The basic observation in this context is that the two formulations share the same discretization of the domain, and in particular the same nodes. The important advantage is that any information stored at the nodes is immediately available to both the formulations. For example if the fluid solver computes VELOCITY the thermal solver will be able automatically to use this VELOCITY to convect the TEMPERATURE.
The point we would like to highlight here is how to define the two different domains:
let's suppose that we start by reading a fluid_model_part
and we would like to define a thermal_model_part
that shares the same nodes as the one before but is defined by an array of Elements and Conditions which use a different formulation. Let's also suppose for now that an appropriate list of ThermalElements and ThermalConditions is already created.
in order to fill the thermal_model_part we should perform in python the following operations:
thermal_model_part.Nodes = fluid_model_part.Nodes ##make the new model part to use the same nodes as the original model part! thermal_model_part.ProcessInfo = fluid_model_part.ProcessInfo ##this makes all of the time informations to coincide between the two model parts thermal_model_part.Properties = fluid_model_part.Properties ##assign all of the "Material properties"
all of the operations up to this point copy Pointers so ... any change in the fluid_model_part's Nodes, Properties and ProcessInfo will also affect the new thermal model part
thermal_model_part.Elements = ThermalElements thermal_model_part.Conditions = ThermalConditions
here we assign to the Elements of the thermal model part the list of elements we created somewhere.
In the practice this operation is made automatic by an utility in the MeshingApplication (which of course should be imported to have the option available)
the usage in this case would be (assuming fluid_model_part is the origin and thermal_model_part the destination)
modeler_util = ConnectivityPreserveModeler() modeler_util.GenerateModelPart(fluid_model_part,thermal_model_part,"ThermalElementName","ThermalConditionName")
where "ThermalElementName" is a string that contains the kratos name for the element to be used in filling the new model part.
Warning. Please, note that:
Please note that if the same nodes are shared between different model parts, CloneTimeStep should be called ONLY ONCE!. Calling it for every model_part is WRONG (and always was)
SCENARIO 2 : two different formulations on different parts of the domain
In the case that you do not want to create a copy of the whole model part (like in the example above), but instead need to create an empty model part, later on filled by sub-sets of the previously existing one (think of the "father" model part in FSI that contains all the nodes of the fluid and structure domain.. You wish to create two "sons" - "fluid part" and "structure part"), then after copying the necessary data (nodes, elements, etc) to the "sons", you need to set the process info of the new parts as:
Note: THAT you must use pGetProcessInfo and not GetProcessInfo. The latter one creates a copy, while the first and correct one "links" the pointer.