Merge branch 'feature/doubleMesh' into 'development'
Improvements to mesh and double mesh See merge request JorgeGonz/fpakc!13
This commit is contained in:
commit
439a45efbf
52 changed files with 13375 additions and 4956 deletions
|
|
@ -8,6 +8,16 @@
|
||||||
pages = {3--67},
|
pages = {3--67},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@article{higginson2020corrected,
|
||||||
|
title={A corrected method for Coulomb scattering in arbitrarily weighted particle-in-cell plasma simulations},
|
||||||
|
author={Higginson, Drew Pitney and Holod, Ihor and Link, Anthony},
|
||||||
|
journal={Journal of Computational Physics},
|
||||||
|
volume={413},
|
||||||
|
pages={109450},
|
||||||
|
year={2020},
|
||||||
|
publisher={Elsevier}
|
||||||
|
}
|
||||||
|
|
||||||
@Misc{gfortranURL,
|
@Misc{gfortranURL,
|
||||||
author = {GNU Project},
|
author = {GNU Project},
|
||||||
title = {gfortran - the GNU Fortran compiler},
|
title = {gfortran - the GNU Fortran compiler},
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -21,6 +21,10 @@
|
||||||
Author = {Jorge Gonzalez}
|
Author = {Jorge Gonzalez}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
% Allows breaking of URL in bibliography.
|
||||||
|
\setcounter{biburllcpenalty}{7000}
|
||||||
|
\setcounter{biburlucpenalty}{8000}
|
||||||
|
|
||||||
\makeglossaries
|
\makeglossaries
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
@ -31,6 +35,8 @@
|
||||||
\newacronym{cpu}{CPU}{Central Processing Unit}
|
\newacronym{cpu}{CPU}{Central Processing Unit}
|
||||||
\newacronym{json}{JSON}{JavaScript Object Notation}
|
\newacronym{json}{JSON}{JavaScript Object Notation}
|
||||||
\newacronym{io}{I/O}{input/output}
|
\newacronym{io}{I/O}{input/output}
|
||||||
|
\newacronym{mcc}{MCC}{Monte-Carlo Collisions}
|
||||||
|
\newacronym{cs}{CS}{Coulomb Scattering}
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
\newglossaryentry{openmp}{name={OpenMP},description={Shared-memory parallelization}}
|
\newglossaryentry{openmp}{name={OpenMP},description={Shared-memory parallelization}}
|
||||||
|
|
@ -60,7 +66,9 @@
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
\chapter{Introduction}
|
\chapter{Introduction}
|
||||||
\section{About fpakc}
|
\section{About fpakc}
|
||||||
The \Gls{fpakc} is a simulation tool that models species in plasmas (ions, electrons and neutrals) following the trajectories of macro-particles as they move and interact between them and the boundaries of the domain.
|
The \Gls{fpakc} is a simulation tool that models species in plasma (ions, electrons and neutrals) following the trajectories of macro-particles as they move and interact between them and the boundaries of the domain.
|
||||||
|
Particles properties are scattered into a finite element mesh in 1, 2 or three dimensions, with the possibility to choose different geometries.
|
||||||
|
The official repository can be found at: \url{https://gitlab.com/JorgeGonz/fpakc.git}.
|
||||||
The code is currently in very early steps of development and further improvements are expected very soon.
|
The code is currently in very early steps of development and further improvements are expected very soon.
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
@ -78,11 +86,11 @@
|
||||||
This ease the process of fixing bugs and improving the codes by a large team of developers.
|
This ease the process of fixing bugs and improving the codes by a large team of developers.
|
||||||
For more information, please refer to the \acrshort{fpakc} Coding Style document.
|
For more information, please refer to the \acrshort{fpakc} Coding Style document.
|
||||||
\item \acrshort{fpakc} requires to be ease to use.
|
\item \acrshort{fpakc} requires to be ease to use.
|
||||||
Input files are required to be in a \textit{human} format, meaning that the different options can be easily understander without constant reference to the user guide.
|
Input files are required to be in a \textit{human} format, meaning that the different options can be easily understood without constant reference to the user guide.
|
||||||
\acrshort{fpakc} is aimed to be used in a wide range of applications and by a variety of scientist: from very established ones to newcomers to the field and students.
|
\acrshort{fpakc} is aimed to be used in a wide range of applications and by a variety of scientist: from very established ones to newcomers to the field and also students.
|
||||||
\end{enumerate}
|
\end{enumerate}
|
||||||
|
|
||||||
These are foundation stones of the code and code development and should always be followed, at least for the releases in the official repository.
|
These are foundation stones of \acrshort{fpakc} and its development and should always be followed, at least for the releases in the official repository.
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
\section{How to collaborate}
|
\section{How to collaborate}
|
||||||
|
|
@ -92,22 +100,32 @@
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
\chapter{Operation Scheme}
|
\chapter{Operation Scheme}
|
||||||
\section{The Particle Method}
|
\section{The Particle Method}
|
||||||
\acrshort{fpakc} uses macro-particles to simulate the dynamics of different plasma species (mainly ions, electrons and neutrals).
|
\Gls{fpakc} uses macro-particles to simulate the dynamics of different plasma species (mainly ions, electrons and neutrals).
|
||||||
These macro-particles represent a large amount of real particles.
|
These macro-particles could represent a large amount of real particles.
|
||||||
For now own, macro-particles will be referred as just particles by abusing of language.
|
For now own, macro-particles will be referred as just particles by abusing of language.
|
||||||
In the evolution of these particles, external forces (as the electromagnetic field), interaction between particles (as collisions) and interaction with the boundaries of the domain are included.
|
During the initiation phase, the input and mesh file(s) are reading.
|
||||||
|
If an initial distribution for a species is specified in the input file, particles to match that distribution are loaded into the cells.
|
||||||
|
|
||||||
At each time step, particles are first pushed accounting for possible acceleration by external forces.
|
The general steps performed in each iteration are:
|
||||||
Then, the cell in which the particle ends up is located.
|
\begin{enumerate}
|
||||||
If a boundary is encountered, the interaction between the particle and the boundary is calculated.
|
\item Firstly, new particles are introduced into the domain as specified in the input file.
|
||||||
Next, collisions for the particles in each cell are carried on.
|
\item Particles are then pushed accounting for possible acceleration by external forces.
|
||||||
|
During this process, if a particle changes cell it is found using the connectivity between elements.
|
||||||
|
If a particle encounters a boundary instead a new cell, the interaction between the boundary and the wall is computed.
|
||||||
|
A particle may abandon the computational domain and is no longer accounted for.
|
||||||
|
\item Next, collisions for the particles inside each cell are carried out.
|
||||||
This may include different collision processes for each particle.
|
This may include different collision processes for each particle.
|
||||||
Finally, the particles properties are scattered into the mesh nodes.
|
Monte-Carlo collisions (elastic, ionization, charge-exchange$\ldots$) can be carried out in a specific mesh, to better adjust to the cell size required, similar to the mean-free path.
|
||||||
|
Although not yet implemented, Coulomb scattering will always be performed in the mesh used for scattering, which cell size should be in the order of the Debye length.
|
||||||
|
\item A new array containing all particles inside the numerical domain is obtained.
|
||||||
|
\item Finally, particle properties are scattered among the mesh nodes.
|
||||||
These properties are density, momentum and the stress tensor.
|
These properties are density, momentum and the stress tensor.
|
||||||
Non-dimensional units are used for this, but output files are converted into dimensional units.
|
\item If requested, the electromagnetic field is computed.
|
||||||
If requested, the electromagnetic field is computed.
|
\item If the number of iteration requires writing output files, it is done after all steps for the particles is completed.
|
||||||
|
\end{enumerate}
|
||||||
|
|
||||||
More in depth explanation of the different steps are given in the following sections.
|
\Gls{fpakc} has the capability to configure all the behavior of the simulation via the input file.
|
||||||
|
Parameters as injection, the kind of pusher used for each species, boundary conditions or collisions are user-input parameters and will be described in Chap.~\ref{ch:input_file}.
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
\section{Injection of new particles}
|
\section{Injection of new particles}
|
||||||
|
|
@ -122,43 +140,86 @@
|
||||||
Particles are pushed in the selected domain.
|
Particles are pushed in the selected domain.
|
||||||
Velocity and position are updated according to the old particle values and the external forces.
|
Velocity and position are updated according to the old particle values and the external forces.
|
||||||
All the push routines for the different geometries can be found in \lstinline|moduleSolver|.
|
All the push routines for the different geometries can be found in \lstinline|moduleSolver|.
|
||||||
|
The pushers included in \Gls{fpakc} are:
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
\begin{itemize}
|
||||||
\subsection{3D Cartesian pusher}
|
\item 3D Cartesian pusher.
|
||||||
Moving particles in a simple 3D Cartesian space.
|
Moving particles in a simple 3D Cartesian space.
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
\item 2D Cylindrical.
|
||||||
\subsection{2D Cylindrical}
|
|
||||||
When a 2D cylindrical geometry is used ($z$, $r$), a Boris solver\cite{boris1970relativistic} is used to move particles accounting for the effect of the symmetry axis.
|
When a 2D cylindrical geometry is used ($z$, $r$), a Boris solver\cite{boris1970relativistic} is used to move particles accounting for the effect of the symmetry axis.
|
||||||
This pusher removes the issue with particles going to infinite velocity when $r \rightarrow 0$ by pushing the particles in Cartesian space and then converting it to $r-z$ geometry.
|
This pusher removes the issue with particles going to infinite velocity when $r \rightarrow 0$ by pushing the particles in Cartesian space and then converting it to $r-z$ geometry.
|
||||||
Velocity in the $\theta$ direction is updated for collision processes, although the dynamic in the angular direction is assumed as symmetric.
|
Velocity in the $\theta$ direction is updated for collision processes, although the dynamic in the angular direction is assumed as symmetric.
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
\item 2D Cartesian pusher.
|
||||||
\subsection{2D Cartesian pusher}
|
|
||||||
Moving particles in a simple 2D Cartesian space.
|
Moving particles in a simple 2D Cartesian space.
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
\item 1D Radial pusher.
|
||||||
\subsection{1D Radial pusher}
|
|
||||||
Same implementation as 2D cylindrical pusher but direction $z$ is ignored.
|
Same implementation as 2D cylindrical pusher but direction $z$ is ignored.
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
\item 1D Cartesian pusher.
|
||||||
\subsection{1D Cartesian pusher}
|
|
||||||
Moving particles in a simple 1D Cartesian space. Same implementation as in 2D Cartesian but $y$ direction is ignored.
|
Moving particles in a simple 1D Cartesian space. Same implementation as in 2D Cartesian but $y$ direction is ignored.
|
||||||
|
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
\section{Find new cell}
|
\section{Find new cell}
|
||||||
Once the position and velocity of the particle are updated, the new cell that contains the particle is searched.
|
Once the position and velocity of the particle are updated, the new cell that contains the particle is searched.
|
||||||
This is done by a neighbor search, starting from the previous cell containing the particle.
|
This is done by a neighbor search, starting from the previous cell containing the particle.
|
||||||
In the process of finding the new cell, it is possible that a particle encounters a boundary.
|
In the process of finding the new cell, it is possible that a particle encounters a boundary.
|
||||||
When the particle interacts with the boundary, the particle may continue its life in the simulation (reflected) or might be eliminated from it (absorbed).
|
When the particle interacts with the boundary, the particle may continue its life in the simulation or might be eliminated from it.
|
||||||
Once that the new cell is found or that the particle life has been terminated, the pushing is complete.
|
Once that the new cell is found or that the particle life has been terminated, the pushing is complete.
|
||||||
|
If a secondary mesh is used for the Monte-Carlo Collision method, the new cell in that mesh in which the particle reside is also found by the same method, although no interaction with the boundaries is accounted for this step.
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
\section{Variable Weighting Scheme\label{sec:weightingScheme}}
|
\section{Variable Weighting Scheme\label{sec:weightingScheme}}
|
||||||
One of the issues in particle simulations, specially for axial-symmetrical cases, is that due to the disparate volume of cells, specially close to the axis, the statistics in some cells is usually poor.
|
One of the issues in particle simulations, specially for axial-symmetrical cases, is that due to the disparate volume of cells, specially close to the axis, the statistics in some cells is usually poor.
|
||||||
To try to fix that, the possibility to include a Variable Weighting Scheme in the simulations is available in \Gls{fpakc}.
|
To try to fix that, the possibility to include a Variable Weighting Scheme in the simulations is available in \Gls{fpakc}.
|
||||||
This schemes detect when a particle change cells and modify its weight accordingly.
|
These schemes detect when a particle change cells and modify its weight accordingly.
|
||||||
To avoid particles having a larger weight than the rest, particle can be split in multiple particles if weight become too large.
|
To avoid particles having a larger weight than the rest, particle can be split in multiple particles if weight become too large.
|
||||||
|
The use of a Variable Weighting Scheme is defined by the user in the input file.
|
||||||
|
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
\section{Interaction between species}\label{ssec:collisions}
|
||||||
|
For each cell, interaction among the particles in it are carried out.
|
||||||
|
\Gls{fpakc} distinguish between two types of interactions: \acrfull{mcc} and \acrfull{cs}.
|
||||||
|
\acrshort{mcc} refers to the process in which two particles interact in short range.
|
||||||
|
These processes include, but are not limited to: elastic collisions, ionization/recombination, charge-exchange, excitation/de-excitation\ldots
|
||||||
|
A secondary mesh, with cell sizes in the range of the mean-free path, can be used for this type of collisions.
|
||||||
|
\acrshort{cs} refers to the large range interaction that a charged species suffer do to the charge of other particles.
|
||||||
|
The interactions between the different species is defined by the user.
|
||||||
|
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
\subsection{\acrlong{mcc}}
|
||||||
|
For each cell the maximum number of collisions between particle is computed.
|
||||||
|
For each collision, a random pair of particles is chosen.
|
||||||
|
A loop over all possible collisions for the pair of particles chosen is performed.
|
||||||
|
If a random number is above the probability of collision for that specific type, the collision take place.
|
||||||
|
If not, the next type for the particle pair is checked.
|
||||||
|
|
||||||
|
Below are described the type of collision process implemented in \acrshort{fpakc}:
|
||||||
|
\begin{itemize}
|
||||||
|
\item Elastic.
|
||||||
|
In this type of collision, particles exchange energy due to hard-sphere model.
|
||||||
|
Total energy is conserved.
|
||||||
|
Resulting velocity directions are chosen from Maxwellian distribution functions.
|
||||||
|
This interaction is useful for short-range collisions as neutral-neutral and charged-neutral elastic collisions.
|
||||||
|
|
||||||
|
\item Charge Exchange.
|
||||||
|
When an ion interacts with a neutral particle, an electron is exchanged between the two particles with no exchange of energy.
|
||||||
|
This is called a resonant charge-exchange.
|
||||||
|
|
||||||
|
\item Electron Impact Ionization.
|
||||||
|
When the relative energy between a neutral and an electron is above the ionization threshold, there is a probability that the neutral particle will become ionized.
|
||||||
|
This ionization emits and additional electron
|
||||||
|
|
||||||
|
\item Recombination.
|
||||||
|
When an electron and an ion interact, there is a possibility for them to be recombined into a neutral particle.
|
||||||
|
The photon emitted by this process is not modeled yet.
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\subsection{\acrlong{cs}}
|
||||||
|
Although not yet implement, a first approach will be soon implemented using Ref.~\cite{higginson2020corrected} as a guideline.
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
\section{Reset of particle array}
|
\section{Reset of particle array}
|
||||||
|
|
@ -167,41 +228,6 @@
|
||||||
In this section, particles are assigned to the list of particles inside each individual cell.
|
In this section, particles are assigned to the list of particles inside each individual cell.
|
||||||
Unfortunately, this is done right now without parallelisation and is very CPU consuming.
|
Unfortunately, this is done right now without parallelisation and is very CPU consuming.
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
\section{Interaction between species}\label{ssec:collisions}
|
|
||||||
For each cell, interaction among the particles in it are carried out.
|
|
||||||
The type of interaction between the different particles is defined by the user.
|
|
||||||
In general, the maximum number of interaction in a cell is computed.
|
|
||||||
For each collision, a pair of particles is selected.
|
|
||||||
A loop over all possible collisions for the pair of particles is performed.
|
|
||||||
If a random number generated is above the probability of collision for the type divided by the maximum one, the collision take place.
|
|
||||||
|
|
||||||
Collisions can change the velocity of the particles involved (elastic), create new particles (ionization-recombination) or change the type of particle (charge-exchange).
|
|
||||||
|
|
||||||
Below are described the type of collision process implemented between species.
|
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
\subsection{Elastic collision}
|
|
||||||
In this type of collision, particles exchange energy due to hard-sphere model.
|
|
||||||
Total energy is conserved.
|
|
||||||
Resulting velocity directions are chosen from Maxwellian distribution functions.
|
|
||||||
This interaction is useful for short-range collisions as neutral-neutral and charged-neutral elastic collisions.
|
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
\subsection{Charge Exchange}
|
|
||||||
When an ion interacts with a neutral particle, an electron is exchanged between the two particles with no exchange of energy.
|
|
||||||
This is called a resonant charge-exchange.
|
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
\subsection{Electron Impact Ionization}
|
|
||||||
When the relative energy between a neutral and an electron is above the ionization threshold, there is a probability that the neutral particle will become ionized.
|
|
||||||
This ionization emits and additional electron
|
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
\subsection{Recombination}
|
|
||||||
When an electron and an ion interact, there is a possibility for them to be recombined into a neutral particle.
|
|
||||||
The photon emitted by this process is not modeled yet.
|
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
\section{Scattering}
|
\section{Scattering}
|
||||||
The properties of each particle are deposited in the nodes from the containing cell.
|
The properties of each particle are deposited in the nodes from the containing cell.
|
||||||
|
|
@ -358,7 +384,10 @@ make
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
\item \textbf{meshType}: Character.
|
\item \textbf{meshType}: Character.
|
||||||
Format of mesh file.
|
Format of mesh file.
|
||||||
Currently, only the value \textbf{gmsh} is accepted, which makes reference to \Gls{gmsh} v2.0 output format.
|
Accepted formats are:
|
||||||
|
\begin{itemize}
|
||||||
|
\item \textbf{gmsh2}: \Gls{gmsh} file format in version 2.0.
|
||||||
|
\end{itemize}
|
||||||
\item \textbf{meshFile}: Character.
|
\item \textbf{meshFile}: Character.
|
||||||
Mesh filename.
|
Mesh filename.
|
||||||
This file is searched in the path \textbf{output.path} and must contain the file extension.
|
This file is searched in the path \textbf{output.path} and must contain the file extension.
|
||||||
|
|
@ -617,9 +646,14 @@ make
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
\item \textbf{folderCollisions}: Character.
|
\item \textbf{folderCollisions}: Character.
|
||||||
Indicates the path to in which the cross section tables are allocated.
|
Indicates the path to in which the cross section tables are allocated.
|
||||||
|
\item \textbf{meshCollisions}: Character.
|
||||||
|
Determines a specific mesh for \acrshort{mcc} processes.
|
||||||
|
The file needs to be located in the folder \textbf{output.folder}.
|
||||||
|
If this value is not present, the mesh defined in \textbf{geometry.meshFile} is used for \acrshort{mcc}.
|
||||||
|
The format of this mesh needs to be the same as the one defined in \textbf{geometry.meshType}.
|
||||||
\item \textbf{collisions}: Object.
|
\item \textbf{collisions}: Object.
|
||||||
Array.
|
Array.
|
||||||
Contains the different binary collisions.
|
Contains the different short range interactions (\acrshort{mcc}).
|
||||||
Multiple collision types can be defined for each pair of species.
|
Multiple collision types can be defined for each pair of species.
|
||||||
Each object in the array is defined by:
|
Each object in the array is defined by:
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
|
|
@ -662,21 +696,22 @@ make
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
\chapter{Example runs\label{ch:exampleRuns}}
|
\chapter{Example runs\label{ch:exampleRuns}}
|
||||||
\section{1D Cathode}
|
\section{1D Emissive Cathode (1D\_Cathode)}
|
||||||
Emission from a 1D cathond in both, cartesian and radial coordinates.
|
Emission from a 1D cathond in both, cartesian and radial coordinates.
|
||||||
Both cases insert the same amount of electrons from the minimum coordinate and have the same boundary conditions for particles and the electrostatic field.
|
Both cases insert the same amount of electrons from the minimum coordinate and have the same boundary conditions for particles and the electrostatic field.
|
||||||
This case is useful to ilustrate hoy \acrshort{fpakc} can deal with different geometries by just modifiying some parameters in the input file.
|
This case is useful to ilustrate hoy \acrshort{fpakc} can deal with different geometries by just modifiying some parameters in the input file.
|
||||||
The same mesh file (\lstinline|mesh.msh|) is used for both cases.
|
The same mesh file (\lstinline|mesh.msh|) is used for both cases.
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
\section{ALPHIE Grid system}
|
\section{ALPHIE Grid system (ALPHIE\_Grid)}
|
||||||
Two-dimensional axialsymmetry case to study the counterflow of electrons and Argon ions going trhough the ALPHIE grid system.
|
Two-dimensional axialsymmetry case to study the counterflow of electrons and Argon ions going trhough the ALPHIE grid system.
|
||||||
A \lstinline|mesh.geo| file is provided to easily modify the parameters of the grid system and generate a new mesh with \Gls{gmsh}.
|
A \lstinline|mesh.geo| file is provided to easily modify the parameters of the grid system and generate a new mesh with \Gls{gmsh}.
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
\section{Flow around cylinder}
|
\section{Flow around cylinder (cylFlow)}
|
||||||
Simple case of neutral Argon flow around a cylinder in a 2D axialsymmetry geometry.
|
Simple case of neutral Argon flow around a cylinder in a 2D axialsymmetry geometry.
|
||||||
Elastic collisions between argon particles are included as default.
|
Elastic collisions between argon particles are included.
|
||||||
|
Two cases are presented here: one in which the same mesh (meshSingle.msh) for scattering and collisions is used (input.json) and a second one (inputDualMesh.json) in which a mesh is used for scattering (mesh.msh) and a second one is used only for collisions (meshColl.msh).
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
\printglossaries
|
\printglossaries
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
},
|
},
|
||||||
"geometry": {
|
"geometry": {
|
||||||
"type": "1DCart",
|
"type": "1DCart",
|
||||||
"meshType": "gmsh",
|
"meshType": "gmsh2",
|
||||||
"meshFile": "mesh.msh"
|
"meshFile": "mesh.msh"
|
||||||
},
|
},
|
||||||
"species": [
|
"species": [
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
},
|
},
|
||||||
"geometry": {
|
"geometry": {
|
||||||
"type": "1DRad",
|
"type": "1DRad",
|
||||||
"meshType": "gmsh",
|
"meshType": "gmsh2",
|
||||||
"meshFile": "mesh.msh"
|
"meshFile": "mesh.msh"
|
||||||
},
|
},
|
||||||
"species": [
|
"species": [
|
||||||
|
|
|
||||||
76
runs/ALPHIE_Grid/inputBaseCase.json
Normal file
76
runs/ALPHIE_Grid/inputBaseCase.json
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
{
|
||||||
|
"output": {
|
||||||
|
"path": "./runs/ALPHIE_Grid/",
|
||||||
|
"triggerOutput": 500,
|
||||||
|
"cpuTime": false,
|
||||||
|
"numColl": false,
|
||||||
|
"EMField": true,
|
||||||
|
"folder": "base_case"
|
||||||
|
},
|
||||||
|
"geometry": {
|
||||||
|
"type": "2DCyl",
|
||||||
|
"meshType": "gmsh2",
|
||||||
|
"meshFile": "mesh.msh"
|
||||||
|
},
|
||||||
|
"species": [
|
||||||
|
{"name": "Argon+", "type": "charged", "mass": 6.633e-26, "charge": 1.0, "weight": 1.0e1},
|
||||||
|
{"name": "Electron", "type": "charged", "mass": 9.109e-31, "charge":-1.0, "weight": 1.0e2}
|
||||||
|
],
|
||||||
|
"boundary": [
|
||||||
|
{"name": "Ionization Chanber", "physicalSurface": 1, "bTypes": [
|
||||||
|
{"type": "transparent"},
|
||||||
|
{"type": "transparent"}
|
||||||
|
]},
|
||||||
|
{"name": "Vacuum Chamber", "physicalSurface": 2, "bTypes": [
|
||||||
|
{"type": "transparent"},
|
||||||
|
{"type": "transparent"}
|
||||||
|
]},
|
||||||
|
{"name": "Exterior", "physicalSurface": 3, "bTypes": [
|
||||||
|
{"type": "reflection"},
|
||||||
|
{"type": "reflection"}
|
||||||
|
]},
|
||||||
|
{"name": "Grid Extraction", "physicalSurface": 4, "bTypes": [
|
||||||
|
{"type": "absorption"},
|
||||||
|
{"type": "absorption"}
|
||||||
|
]},
|
||||||
|
{"name": "Grid Acceleration", "physicalSurface": 5, "bTypes": [
|
||||||
|
{"type": "absorption"},
|
||||||
|
{"type": "absorption"}
|
||||||
|
]},
|
||||||
|
{"name": "Axis", "physicalSurface": 6, "bTypes": [
|
||||||
|
{"type": "axis"},
|
||||||
|
{"type": "axis"}
|
||||||
|
]}
|
||||||
|
],
|
||||||
|
"boundaryEM": [
|
||||||
|
{"name": "Extraction Grid", "type": "dirichlet", "potential": -150.0, "physicalSurface": 4},
|
||||||
|
{"name": "Acceleration Grid", "type": "dirichlet", "potential": -600.0, "physicalSurface": 5},
|
||||||
|
{"name": "Ionization Chamber", "type": "dirichlet", "potential": 0.0, "physicalSurface": 1}
|
||||||
|
],
|
||||||
|
"inject": [
|
||||||
|
{"name": "Ionization Argon+", "species": "Argon+", "flow": 27.0e-6, "units": "A", "v": 322.0, "T": [ 500.0, 500.0, 500.0],
|
||||||
|
"velDist": ["Maxwellian", "Maxwellian", "Maxwellian"], "n": [ 1, 0, 0], "physicalSurface": 1},
|
||||||
|
{"name": "Ionization Electron", "species": "Electron", "flow": 27.0e-6, "units": "A", "v": 87000.0, "T": [ 500.0, 500.0, 500.0],
|
||||||
|
"velDist": ["Maxwellian", "Maxwellian", "Maxwellian"], "n": [ 1, 0, 0], "physicalSurface": 1},
|
||||||
|
{"name": "Cathode Electron", "species": "Electron", "flow": 9.0e-5, "units": "A", "v": 87000.0, "T": [2500.0, 2500.0, 2500.0],
|
||||||
|
"velDist": ["Maxwellian", "Maxwellian", "Maxwellian"], "n": [-1, 0, 0], "physicalSurface": 2}
|
||||||
|
],
|
||||||
|
"reference": {
|
||||||
|
"density": 1.0e16,
|
||||||
|
"mass": 9.109e-31,
|
||||||
|
"temperature": 2500.0,
|
||||||
|
"radius": 1.88e-10
|
||||||
|
},
|
||||||
|
"case": {
|
||||||
|
"tau": [1.0e-9, 1.0e-11],
|
||||||
|
"time": 1.0e-6,
|
||||||
|
"pusher": ["2DCylCharged", "2DCylCharged"],
|
||||||
|
"WeightingScheme": "Volume",
|
||||||
|
"EMSolver": "Electrostatic"
|
||||||
|
},
|
||||||
|
"parallel": {
|
||||||
|
"OpenMP":{
|
||||||
|
"nThreads": 24
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
73
runs/ALPHIE_Grid/inputIonization_0.10mA.json
Normal file
73
runs/ALPHIE_Grid/inputIonization_0.10mA.json
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
{
|
||||||
|
"output": {
|
||||||
|
"path": "./runs/ALPHIE_Grid/",
|
||||||
|
"triggerOutput": 500,
|
||||||
|
"cpuTime": false,
|
||||||
|
"numColl": false,
|
||||||
|
"EMField": true,
|
||||||
|
"folder": "ionization_0.10mA"
|
||||||
|
},
|
||||||
|
"geometry": {
|
||||||
|
"type": "2DCyl",
|
||||||
|
"meshType": "gmsh2",
|
||||||
|
"meshFile": "mesh.msh"
|
||||||
|
},
|
||||||
|
"species": [
|
||||||
|
{"name": "Argon+", "type": "charged", "mass": 6.633e-26, "charge": 1.0, "weight": 1.0e1},
|
||||||
|
{"name": "Electron", "type": "charged", "mass": 9.109e-31, "charge":-1.0, "weight": 1.0e2}
|
||||||
|
],
|
||||||
|
"boundary": [
|
||||||
|
{"name": "Ionization Chanber", "physicalSurface": 1, "bTypes": [
|
||||||
|
{"type": "transparent"},
|
||||||
|
{"type": "ionization", "neutral": {"ion": "Argon+", "mass": 6.633e-26, "density": 1.0e17, "velocity": [323, 0, 0], "temperature": 300},
|
||||||
|
"effectiveTime": 5.0e-6,"energyThreshold": 15.76, "crossSection": "./data/collisions/IO_e-Ar.dat"}
|
||||||
|
]},
|
||||||
|
{"name": "Vacuum Chamber", "physicalSurface": 2, "bTypes": [
|
||||||
|
{"type": "transparent"},
|
||||||
|
{"type": "transparent"}
|
||||||
|
]},
|
||||||
|
{"name": "Exterior", "physicalSurface": 3, "bTypes": [
|
||||||
|
{"type": "reflection"},
|
||||||
|
{"type": "reflection"}
|
||||||
|
]},
|
||||||
|
{"name": "Grid Extraction", "physicalSurface": 4, "bTypes": [
|
||||||
|
{"type": "absorption"},
|
||||||
|
{"type": "absorption"}
|
||||||
|
]},
|
||||||
|
{"name": "Grid Acceleration", "physicalSurface": 5, "bTypes": [
|
||||||
|
{"type": "absorption"},
|
||||||
|
{"type": "absorption"}
|
||||||
|
]},
|
||||||
|
{"name": "Axis", "physicalSurface": 6, "bTypes": [
|
||||||
|
{"type": "axis"},
|
||||||
|
{"type": "axis"}
|
||||||
|
]}
|
||||||
|
],
|
||||||
|
"boundaryEM": [
|
||||||
|
{"name": "Extraction Grid", "type": "dirichlet", "potential": -150.0, "physicalSurface": 4},
|
||||||
|
{"name": "Acceleration Grid", "type": "dirichlet", "potential": -600.0, "physicalSurface": 5},
|
||||||
|
{"name": "Ionization Chamber", "type": "dirichlet", "potential": 0.0, "physicalSurface": 1}
|
||||||
|
],
|
||||||
|
"inject": [
|
||||||
|
{"name": "Cathode Electron", "species": "Electron", "flow": 1.0e-4, "units": "A", "v": 87000.0, "T": [2500.0, 2500.0, 2500.0],
|
||||||
|
"velDist": ["Maxwellian", "Maxwellian", "Maxwellian"], "n": [-1, 0, 0], "physicalSurface": 2}
|
||||||
|
],
|
||||||
|
"reference": {
|
||||||
|
"density": 1.0e16,
|
||||||
|
"mass": 9.109e-31,
|
||||||
|
"temperature": 2500.0,
|
||||||
|
"radius": 1.88e-10
|
||||||
|
},
|
||||||
|
"case": {
|
||||||
|
"tau": [1.0e-9, 1.0e-11],
|
||||||
|
"time": 1.0e-6,
|
||||||
|
"pusher": ["2DCylCharged", "2DCylCharged"],
|
||||||
|
"WeightingScheme": "Volume",
|
||||||
|
"EMSolver": "Electrostatic"
|
||||||
|
},
|
||||||
|
"parallel": {
|
||||||
|
"OpenMP":{
|
||||||
|
"nThreads": 24
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,12 +3,12 @@
|
||||||
"path": "./runs/Argon_Expansion/",
|
"path": "./runs/Argon_Expansion/",
|
||||||
"triggerOutput": 10,
|
"triggerOutput": 10,
|
||||||
"cpuTime": false,
|
"cpuTime": false,
|
||||||
"numColl": false,
|
"numColl": true,
|
||||||
"folder": "CX_case"
|
"folder": "CX_case"
|
||||||
},
|
},
|
||||||
"geometry": {
|
"geometry": {
|
||||||
"type": "2DCyl",
|
"type": "2DCyl",
|
||||||
"meshType": "gmsh",
|
"meshType": "gmsh2",
|
||||||
"meshFile": "mesh.msh"
|
"meshFile": "mesh.msh"
|
||||||
},
|
},
|
||||||
"species": [
|
"species": [
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
},
|
},
|
||||||
"geometry": {
|
"geometry": {
|
||||||
"type": "2DCyl",
|
"type": "2DCyl",
|
||||||
"meshType": "gmsh",
|
"meshType": "gmsh2",
|
||||||
"meshFile": "mesh.msh"
|
"meshFile": "mesh.msh"
|
||||||
},
|
},
|
||||||
"species": [
|
"species": [
|
||||||
|
|
|
||||||
55
runs/Argon_Expansion/nocoll_case.json
Normal file
55
runs/Argon_Expansion/nocoll_case.json
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
{
|
||||||
|
"output": {
|
||||||
|
"path": "./runs/Argon_Expansion/",
|
||||||
|
"triggerOutput": 10,
|
||||||
|
"cpuTime": false,
|
||||||
|
"numColl": false,
|
||||||
|
"folder": "Nocoll_case"
|
||||||
|
},
|
||||||
|
"geometry": {
|
||||||
|
"type": "2DCyl",
|
||||||
|
"meshType": "gmsh2",
|
||||||
|
"meshFile": "mesh.msh"
|
||||||
|
},
|
||||||
|
"species": [
|
||||||
|
{"name": "Argon", "type": "neutral", "mass": 6.633e-26, "weight": 1.0e8, "ion": "Argon+"},
|
||||||
|
{"name": "Argon+", "type": "charged", "mass": 6.633e-26, "weight": 1.0e8, "charge": 1.0, "neutral": "Argon"}
|
||||||
|
],
|
||||||
|
"boundary": [
|
||||||
|
{"name": "Injection", "physicalSurface": 1, "bTypes": [
|
||||||
|
{"type": "transparent"},
|
||||||
|
{"type": "transparent"}
|
||||||
|
]},
|
||||||
|
{"name": "Exterior", "physicalSurface": 2, "bTypes": [
|
||||||
|
{"type": "transparent"},
|
||||||
|
{"type": "transparent"}
|
||||||
|
]},
|
||||||
|
{"name": "Axis", "physicalSurface": 3, "bTypes": [
|
||||||
|
{"type": "axis"},
|
||||||
|
{"type": "axis"}
|
||||||
|
]}
|
||||||
|
],
|
||||||
|
"inject": [
|
||||||
|
{"name": "Exhausts Ar", "species": "Argon", "flow": 0.7, "units": "sccm", "v": 300.0, "T": [300.0, 300.0, 300.0],
|
||||||
|
"velDist": ["Maxwellian", "Maxwellian", "Maxwellian"], "n": [1, 0, 0], "physicalSurface": 1},
|
||||||
|
{"name": "Exhausts Ar+", "species": "Argon+", "flow": 0.3, "units": "sccm", "v": 40000.0, "T": [300.0, 300.0, 300.0],
|
||||||
|
"velDist": ["Maxwellian", "Maxwellian", "Maxwellian"], "n": [1, 0, 0], "physicalSurface": 1}
|
||||||
|
],
|
||||||
|
"reference": {
|
||||||
|
"density": 1.0e19,
|
||||||
|
"mass": 6.633e-26,
|
||||||
|
"temperature": 300.0,
|
||||||
|
"radius": 1.88e-10
|
||||||
|
},
|
||||||
|
"case": {
|
||||||
|
"tau": [1.0e-6, 1.0e-6],
|
||||||
|
"time": 4.0e-3,
|
||||||
|
"pusher": ["2DCylNeutral", "2DCylNeutral"],
|
||||||
|
"WeightingScheme": "Volume"
|
||||||
|
},
|
||||||
|
"parallel": {
|
||||||
|
"OpenMP":{
|
||||||
|
"nThreads": 24
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,12 +3,12 @@
|
||||||
"path": "./runs/cylFlow/",
|
"path": "./runs/cylFlow/",
|
||||||
"triggerOutput": 10,
|
"triggerOutput": 10,
|
||||||
"cpuTime": true,
|
"cpuTime": true,
|
||||||
"numColl": false
|
"numColl": true
|
||||||
},
|
},
|
||||||
"geometry": {
|
"geometry": {
|
||||||
"type": "2DCyl",
|
"type": "2DCyl",
|
||||||
"meshType": "gmsh",
|
"meshType": "gmsh2",
|
||||||
"meshFile": "mesh.msh"
|
"meshFile": "meshSingle.msh"
|
||||||
},
|
},
|
||||||
"species": [
|
"species": [
|
||||||
{"name": "Argon", "type": "neutral", "mass": 6.633e-26, "weight": 5.0e8}
|
{"name": "Argon", "type": "neutral", "mass": 6.633e-26, "weight": 5.0e8}
|
||||||
|
|
@ -57,7 +57,7 @@
|
||||||
},
|
},
|
||||||
"parallel": {
|
"parallel": {
|
||||||
"OpenMP":{
|
"OpenMP":{
|
||||||
"nThreads": 8
|
"nThreads": 24
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
64
runs/cylFlow/inputDualMesh.json
Normal file
64
runs/cylFlow/inputDualMesh.json
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
{
|
||||||
|
"output": {
|
||||||
|
"path": "./runs/cylFlow/",
|
||||||
|
"triggerOutput": 10,
|
||||||
|
"cpuTime": true,
|
||||||
|
"numColl": true
|
||||||
|
},
|
||||||
|
"geometry": {
|
||||||
|
"type": "2DCyl",
|
||||||
|
"meshType": "gmsh2",
|
||||||
|
"meshFile": "mesh.msh"
|
||||||
|
},
|
||||||
|
"species": [
|
||||||
|
{"name": "Argon", "type": "neutral", "mass": 6.633e-26, "weight": 5.0e8}
|
||||||
|
],
|
||||||
|
"boundary": [
|
||||||
|
{"name": "Injection", "physicalSurface": 1, "bTypes": [
|
||||||
|
{"type": "transparent"}
|
||||||
|
]},
|
||||||
|
{"name": "Chamber Walls", "physicalSurface": 2, "bTypes": [
|
||||||
|
{"type": "reflection"}
|
||||||
|
]},
|
||||||
|
{"name": "Exterior", "physicalSurface": 3, "bTypes": [
|
||||||
|
{"type": "transparent"}
|
||||||
|
]},
|
||||||
|
{"name": "Cylinder Walls", "physicalSurface": 4, "bTypes": [
|
||||||
|
{"type": "reflection"}
|
||||||
|
]},
|
||||||
|
{"name": "Axis", "physicalSurface": 5, "bTypes": [
|
||||||
|
{"type": "axis"}
|
||||||
|
]}
|
||||||
|
],
|
||||||
|
"inject": [
|
||||||
|
{"name": "Nozzle", "species": "Argon", "flow": 10.0, "units": "sccm", "v": 300.0, "T": [300.0, 300.0, 300.0],
|
||||||
|
"velDist": ["Maxwellian", "Maxwellian", "Maxwellian"], "n": [1, 0, 0], "physicalSurface": 1}
|
||||||
|
],
|
||||||
|
"reference": {
|
||||||
|
"density": 1.0e20,
|
||||||
|
"mass": 6.633e-26,
|
||||||
|
"temperature": 300.0,
|
||||||
|
"radius": 1.88e-10
|
||||||
|
},
|
||||||
|
"case": {
|
||||||
|
"tau": [5.0e-7],
|
||||||
|
"time": 1.0e-3,
|
||||||
|
"pusher": ["2DCylNeutral"],
|
||||||
|
"WeightingScheme": "Volume"
|
||||||
|
},
|
||||||
|
"interactions": {
|
||||||
|
"folderCollisions": "./data/collisions/",
|
||||||
|
"meshCollisions": "meshColl.msh",
|
||||||
|
"collisions": [
|
||||||
|
{"species_i": "Argon", "species_j": "Argon",
|
||||||
|
"cTypes": [
|
||||||
|
{"type": "elastic", "crossSection": "EL_Ar-Ar.dat"}
|
||||||
|
]}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"parallel": {
|
||||||
|
"OpenMP":{
|
||||||
|
"nThreads": 24
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -62,10 +62,13 @@ Physical Surface(4) = {4};
|
||||||
Physical Surface(5) = {5};
|
Physical Surface(5) = {5};
|
||||||
|
|
||||||
Transfinite Line {12, 2, 4, 6} = cyl_h/Lcell + 1 Using Progression 1;
|
Transfinite Line {12, 2, 4, 6} = cyl_h/Lcell + 1 Using Progression 1;
|
||||||
Transfinite Line {1, 13, 10} = cyl_s/Lcell + 1 Using Progression 1;
|
Transfinite Line {10} = cyl_s/Lcell + 1 Using Progression 1;
|
||||||
Transfinite Line {11, 16, 15, 7} = (dom_h - cyl_h)/Lcell + 1 Using Progression 1;
|
Transfinite Line {1, 13} = cyl_s/Lcell + 1 Using Progression 0.95;
|
||||||
|
Transfinite Line {11, 7} = (dom_h - cyl_h)/Lcell + 1 Using Progression 1;
|
||||||
|
Transfinite Line {16,-15} = (dom_h - cyl_h)/Lcell + 1 Using Progression 0.95;
|
||||||
Transfinite Line {3, 9} = cyl_l/Lcell + 1 Using Progression 1;
|
Transfinite Line {3, 9} = cyl_l/Lcell + 1 Using Progression 1;
|
||||||
Transfinite Line {5, 14, 8} = (dom_l - cyl_e)/Lcell + 1 Using Progression 1;
|
Transfinite Line {8} = (dom_l - cyl_e)/Lcell + 1 Using Progression 1;
|
||||||
|
Transfinite Line {-5, -14} = (dom_l - cyl_e)/Lcell + 1 Using Progression 0.95;
|
||||||
|
|
||||||
Transfinite Surface{1};
|
Transfinite Surface{1};
|
||||||
Recombine Surface {1};
|
Recombine Surface {1};
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
73
runs/cylFlow/meshColl.geo
Normal file
73
runs/cylFlow/meshColl.geo
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
cl__1 = 1;
|
||||||
|
cyl_h = 0.005;
|
||||||
|
cyl_l = 0.02;
|
||||||
|
cyl_s = 0.03;
|
||||||
|
cyl_e = cyl_s + cyl_l;
|
||||||
|
dom_h = 0.03;
|
||||||
|
dom_l = 0.07;
|
||||||
|
|
||||||
|
Lcell = 0.001;
|
||||||
|
|
||||||
|
Point(1) = {0, 0, 0, cl__1};
|
||||||
|
Point(2) = {cyl_s, 0, 0, cl__1};
|
||||||
|
Point(3) = {cyl_s, cyl_h, 0, cl__1};
|
||||||
|
Point(4) = {cyl_e, cyl_h, 0, cl__1};
|
||||||
|
Point(5) = {cyl_e, 0, 0, cl__1};
|
||||||
|
Point(6) = {dom_l, 0, 0, cl__1};
|
||||||
|
Point(7) = {dom_l, cyl_h, 0, cl__1};
|
||||||
|
Point(8) = {dom_l, dom_h, 0, cl__1};
|
||||||
|
Point(9) = {cyl_e, dom_h, 0, cl__1};
|
||||||
|
Point(10) = {cyl_s, dom_h, 0, cl__1};
|
||||||
|
Point(11) = {0, dom_h, 0, cl__1};
|
||||||
|
Point(12) = {0, cyl_h, 0, cl__1};
|
||||||
|
|
||||||
|
Line(1) = {1, 2};
|
||||||
|
Line(2) = {2, 3};
|
||||||
|
Line(3) = {3, 4};
|
||||||
|
Line(4) = {4, 5};
|
||||||
|
Line(5) = {5, 6};
|
||||||
|
Line(6) = {6, 7};
|
||||||
|
Line(7) = {7, 8};
|
||||||
|
Line(8) = {8, 9};
|
||||||
|
Line(9) = {9, 10};
|
||||||
|
Line(10) = {10, 11};
|
||||||
|
Line(11) = {11, 12};
|
||||||
|
Line(12) = {12, 1};
|
||||||
|
Line(13) = {12, 3};
|
||||||
|
Line(14) = {4, 7};
|
||||||
|
Line(15) = {4, 9};
|
||||||
|
Line(16) = {10, 3};
|
||||||
|
|
||||||
|
Line Loop(1) = {1, 2, -13, 12};
|
||||||
|
Plane Surface(1) = {1};
|
||||||
|
Line Loop(2) = {13, -16, 10, 11};
|
||||||
|
Plane Surface(2) = {2};
|
||||||
|
Line Loop(3) = {3, 15, 9, 16};
|
||||||
|
Plane Surface(3) = {3};
|
||||||
|
Line Loop(4) = {5, 6, -14, 4};
|
||||||
|
Plane Surface(4) = {4};
|
||||||
|
Line Loop(5) = {14, 7, 8, -15};
|
||||||
|
Plane Surface(5) = {5};
|
||||||
|
|
||||||
|
Physical Surface(1) = {1};
|
||||||
|
Physical Surface(2) = {2};
|
||||||
|
Physical Surface(3) = {3};
|
||||||
|
Physical Surface(4) = {4};
|
||||||
|
Physical Surface(5) = {5};
|
||||||
|
|
||||||
|
Transfinite Line {12, 2, 4, 6} = cyl_h/Lcell + 1 Using Progression 1;
|
||||||
|
Transfinite Line {1, 13, 10} = cyl_s/Lcell + 1 Using Progression 1;
|
||||||
|
Transfinite Line {11, 16, 15, 7} = (dom_h - cyl_h)/Lcell + 1 Using Progression 1;
|
||||||
|
Transfinite Line {3, 9} = cyl_l/Lcell + 1 Using Progression 1;
|
||||||
|
Transfinite Line {5, 14, 8} = (dom_l - cyl_e)/Lcell + 1 Using Progression 1;
|
||||||
|
|
||||||
|
Transfinite Surface{1};
|
||||||
|
Recombine Surface {1};
|
||||||
|
Transfinite Surface{2};
|
||||||
|
Recombine Surface {2};
|
||||||
|
Transfinite Surface{3};
|
||||||
|
Recombine Surface {3};
|
||||||
|
Transfinite Surface{4};
|
||||||
|
Recombine Surface {4};
|
||||||
|
Transfinite Surface{5};
|
||||||
|
Recombine Surface {5};
|
||||||
3974
runs/cylFlow/meshColl.msh
Normal file
3974
runs/cylFlow/meshColl.msh
Normal file
File diff suppressed because it is too large
Load diff
79
runs/cylFlow/meshSingle.geo
Normal file
79
runs/cylFlow/meshSingle.geo
Normal file
|
|
@ -0,0 +1,79 @@
|
||||||
|
cl__1 = 1;
|
||||||
|
cyl_h = 0.005;
|
||||||
|
cyl_l = 0.02;
|
||||||
|
cyl_s = 0.03;
|
||||||
|
cyl_e = cyl_s + cyl_l;
|
||||||
|
dom_h = 0.03;
|
||||||
|
dom_l = 0.07;
|
||||||
|
|
||||||
|
Lcell = 0.001;
|
||||||
|
|
||||||
|
Point(1) = {0, 0, 0, cl__1};
|
||||||
|
Point(2) = {cyl_s, 0, 0, cl__1};
|
||||||
|
Point(3) = {cyl_s, cyl_h, 0, cl__1};
|
||||||
|
Point(4) = {cyl_e, cyl_h, 0, cl__1};
|
||||||
|
Point(5) = {cyl_e, 0, 0, cl__1};
|
||||||
|
Point(6) = {dom_l, 0, 0, cl__1};
|
||||||
|
Point(7) = {dom_l, cyl_h, 0, cl__1};
|
||||||
|
Point(8) = {dom_l, dom_h, 0, cl__1};
|
||||||
|
Point(9) = {cyl_e, dom_h, 0, cl__1};
|
||||||
|
Point(10) = {cyl_s, dom_h, 0, cl__1};
|
||||||
|
Point(11) = {0, dom_h, 0, cl__1};
|
||||||
|
Point(12) = {0, cyl_h, 0, cl__1};
|
||||||
|
|
||||||
|
Line(1) = {1, 2};
|
||||||
|
Line(2) = {2, 3};
|
||||||
|
Line(3) = {3, 4};
|
||||||
|
Line(4) = {4, 5};
|
||||||
|
Line(5) = {5, 6};
|
||||||
|
Line(6) = {6, 7};
|
||||||
|
Line(7) = {7, 8};
|
||||||
|
Line(8) = {8, 9};
|
||||||
|
Line(9) = {9, 10};
|
||||||
|
Line(10) = {10, 11};
|
||||||
|
Line(11) = {11, 12};
|
||||||
|
Line(12) = {12, 1};
|
||||||
|
Line(13) = {12, 3};
|
||||||
|
Line(14) = {4, 7};
|
||||||
|
Line(15) = {4, 9};
|
||||||
|
Line(16) = {10, 3};
|
||||||
|
|
||||||
|
Line Loop(1) = {1, 2, -13, 12};
|
||||||
|
Plane Surface(1) = {1};
|
||||||
|
Line Loop(2) = {13, -16, 10, 11};
|
||||||
|
Plane Surface(2) = {2};
|
||||||
|
Line Loop(3) = {3, 15, 9, 16};
|
||||||
|
Plane Surface(3) = {3};
|
||||||
|
Line Loop(4) = {5, 6, -14, 4};
|
||||||
|
Plane Surface(4) = {4};
|
||||||
|
Line Loop(5) = {14, 7, 8, -15};
|
||||||
|
Plane Surface(5) = {5};
|
||||||
|
|
||||||
|
Physical Line(1) = {12, 11};
|
||||||
|
Physical Line(2) = {10, 9, 8};
|
||||||
|
Physical Line(3) = {7, 6};
|
||||||
|
Physical Line(4) = {2, 3, 4};
|
||||||
|
Physical Line(5) = {1, 5};
|
||||||
|
|
||||||
|
Physical Surface(1) = {1};
|
||||||
|
Physical Surface(2) = {2};
|
||||||
|
Physical Surface(3) = {3};
|
||||||
|
Physical Surface(4) = {4};
|
||||||
|
Physical Surface(5) = {5};
|
||||||
|
|
||||||
|
Transfinite Line {12, 2, 4, 6} = cyl_h/Lcell + 1 Using Progression 1;
|
||||||
|
Transfinite Line {1, 13, 10} = cyl_s/Lcell + 1 Using Progression 1;
|
||||||
|
Transfinite Line {11, 16, 15, 7} = (dom_h - cyl_h)/Lcell + 1 Using Progression 1;
|
||||||
|
Transfinite Line {3, 9} = cyl_l/Lcell + 1 Using Progression 1;
|
||||||
|
Transfinite Line {5, 14, 8} = (dom_l - cyl_e)/Lcell + 1 Using Progression 1;
|
||||||
|
|
||||||
|
Transfinite Surface{1};
|
||||||
|
Recombine Surface {1};
|
||||||
|
Transfinite Surface{2};
|
||||||
|
Recombine Surface {2};
|
||||||
|
Transfinite Surface{3};
|
||||||
|
Recombine Surface {3};
|
||||||
|
Transfinite Surface{4};
|
||||||
|
Recombine Surface {4};
|
||||||
|
Transfinite Surface{5};
|
||||||
|
Recombine Surface {5};
|
||||||
4182
runs/cylFlow/meshSingle.msh
Normal file
4182
runs/cylFlow/meshSingle.msh
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -4,6 +4,7 @@ PROGRAM fpakc
|
||||||
USE moduleErrors
|
USE moduleErrors
|
||||||
USE moduleInject
|
USE moduleInject
|
||||||
USE moduleSolver
|
USE moduleSolver
|
||||||
|
USE moduleMesh
|
||||||
USE moduleCompTime
|
USE moduleCompTime
|
||||||
USE moduleCaseParam
|
USE moduleCaseParam
|
||||||
USE OMP_LIB
|
USE OMP_LIB
|
||||||
|
|
@ -67,11 +68,20 @@ PROGRAM fpakc
|
||||||
tColl = omp_get_wtime()
|
tColl = omp_get_wtime()
|
||||||
!$OMP END SINGLE
|
!$OMP END SINGLE
|
||||||
|
|
||||||
CALL doCollisions()
|
IF (ASSOCIATED(meshForMCC)) CALL meshForMCC%doCollisions()
|
||||||
|
|
||||||
!$OMP SINGLE
|
!$OMP SINGLE
|
||||||
tColl = omp_get_wtime() - tColl
|
tColl = omp_get_wtime() - tColl
|
||||||
|
|
||||||
|
!Coulomb scattering
|
||||||
|
tCoul = omp_get_wTime()
|
||||||
|
!$OMP END SINGLE
|
||||||
|
|
||||||
|
IF (ASSOCIATED(mesh%doCoulomb)) CALL mesh%doCoulomb()
|
||||||
|
|
||||||
|
!$OMP SINGLE
|
||||||
|
tCoul = omp_get_wTime() - tCoul
|
||||||
|
|
||||||
!Reset particles
|
!Reset particles
|
||||||
tReset = omp_get_wtime()
|
tReset = omp_get_wtime()
|
||||||
!$OMP END SINGLE
|
!$OMP END SINGLE
|
||||||
|
|
|
||||||
11
src/makefile
11
src/makefile
|
|
@ -4,11 +4,12 @@ OBJECTS = $(OBJDIR)/moduleMesh.o $(OBJDIR)/moduleMeshBoundary.o $(OBJDIR)/module
|
||||||
$(OBJDIR)/moduleBoundary.o $(OBJDIR)/moduleCaseParam.o $(OBJDIR)/moduleRefParam.o \
|
$(OBJDIR)/moduleBoundary.o $(OBJDIR)/moduleCaseParam.o $(OBJDIR)/moduleRefParam.o \
|
||||||
$(OBJDIR)/moduleCollisions.o $(OBJDIR)/moduleTable.o $(OBJDIR)/moduleParallel.o \
|
$(OBJDIR)/moduleCollisions.o $(OBJDIR)/moduleTable.o $(OBJDIR)/moduleParallel.o \
|
||||||
$(OBJDIR)/moduleEM.o $(OBJDIR)/moduleRandom.o $(OBJDIR)/moduleMath.o \
|
$(OBJDIR)/moduleEM.o $(OBJDIR)/moduleRandom.o $(OBJDIR)/moduleMath.o \
|
||||||
$(OBJDIR)/moduleMesh3DCart.o $(OBJDIR)/moduleMesh3DCartRead.o \
|
$(OBJDIR)/moduleMeshInputGmsh2.o $(OBJDIR)/moduleMeshOutputGmsh2.o \
|
||||||
$(OBJDIR)/moduleMesh2DCyl.o $(OBJDIR)/moduleMesh2DCylRead.o \
|
$(OBJDIR)/moduleMesh3DCart.o \
|
||||||
$(OBJDIR)/moduleMesh2DCart.o $(OBJDIR)/moduleMesh2DCartRead.o \
|
$(OBJDIR)/moduleMesh2DCyl.o \
|
||||||
$(OBJDIR)/moduleMesh1DCart.o $(OBJDIR)/moduleMesh1DCartRead.o \
|
$(OBJDIR)/moduleMesh2DCart.o \
|
||||||
$(OBJDIR)/moduleMesh1DRad.o $(OBJDIR)/moduleMesh1DRadRead.o
|
$(OBJDIR)/moduleMesh1DRad.o \
|
||||||
|
$(OBJDIR)/moduleMesh1DCart.o
|
||||||
|
|
||||||
all: $(OUTPUT)
|
all: $(OUTPUT)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
all: moduleMesh1DCart.o moduleMesh1DCartRead.o
|
all: moduleMesh1DCart.o
|
||||||
|
|
||||||
moduleMesh1DCart.o: moduleMesh1DCart.f90
|
moduleMesh1DCart.o: moduleMesh1DCart.f90
|
||||||
$(FC) $(FCFLAGS) -c $(subst .o,.f90,$@) -o $(OBJDIR)/$@
|
$(FC) $(FCFLAGS) -c $(subst .o,.f90,$@) -o $(OBJDIR)/$@
|
||||||
|
|
||||||
moduleMesh1DCartRead.o: moduleMesh1DCart.o moduleMesh1DCartRead.f90
|
|
||||||
$(FC) $(FCFLAGS) -c $(subst .o,.f90,$@) -o $(OBJDIR)/$@
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ MODULE moduleMesh1DCart
|
||||||
!Connectivity to nodes
|
!Connectivity to nodes
|
||||||
CLASS(meshNode), POINTER:: n1 => NULL(), n2 => NULL()
|
CLASS(meshNode), POINTER:: n1 => NULL(), n2 => NULL()
|
||||||
!Connectivity to adjacent elements
|
!Connectivity to adjacent elements
|
||||||
CLASS(*), POINTER:: e1 => NULL(), e2 => NULL()
|
CLASS(meshElement), POINTER:: e1 => NULL(), e2 => NULL()
|
||||||
REAL(8):: arNodes(1:2)
|
REAL(8):: arNodes(1:2)
|
||||||
CONTAINS
|
CONTAINS
|
||||||
PROCEDURE, PASS:: init => initVol1DCartSegm
|
PROCEDURE, PASS:: init => initVol1DCartSegm
|
||||||
|
|
@ -198,18 +198,19 @@ MODULE moduleMesh1DCart
|
||||||
!VOLUME FUNCTIONS
|
!VOLUME FUNCTIONS
|
||||||
!SEGMENT FUNCTIONS
|
!SEGMENT FUNCTIONS
|
||||||
!Init segment element
|
!Init segment element
|
||||||
SUBROUTINE initVol1DCartSegm(self, n, p)
|
SUBROUTINE initVol1DCartSegm(self, n, p, nodes)
|
||||||
USE moduleRefParam
|
USE moduleRefParam
|
||||||
IMPLICIT NONE
|
IMPLICIT NONE
|
||||||
|
|
||||||
CLASS(meshVol1DCartSegm), INTENT(out):: self
|
CLASS(meshVol1DCartSegm), INTENT(out):: self
|
||||||
INTEGER, INTENT(in):: n
|
INTEGER, INTENT(in):: n
|
||||||
INTEGER, INTENT(in):: p(:)
|
INTEGER, INTENT(in):: p(:)
|
||||||
|
TYPE(meshNodeCont), INTENT(in), TARGET:: nodes(:)
|
||||||
REAL(8), DIMENSION(1:3):: r1, r2
|
REAL(8), DIMENSION(1:3):: r1, r2
|
||||||
|
|
||||||
self%n = n
|
self%n = n
|
||||||
self%n1 => mesh%nodes(p(1))%obj
|
self%n1 => nodes(p(1))%obj
|
||||||
self%n2 => mesh%nodes(p(2))%obj
|
self%n2 => nodes(p(2))%obj
|
||||||
!Get element coordinates
|
!Get element coordinates
|
||||||
r1 = self%n1%getCoordinates()
|
r1 = self%n1%getCoordinates()
|
||||||
r2 = self%n2%getCoordinates()
|
r2 = self%n2%getCoordinates()
|
||||||
|
|
@ -308,25 +309,25 @@ MODULE moduleMesh1DCart
|
||||||
END SUBROUTINE partialDerSegm
|
END SUBROUTINE partialDerSegm
|
||||||
|
|
||||||
!Computes local stiffness matrix
|
!Computes local stiffness matrix
|
||||||
FUNCTION elemKSegm(self) RESULT(ke)
|
PURE FUNCTION elemKSegm(self) RESULT(localK)
|
||||||
IMPLICIT NONE
|
IMPLICIT NONE
|
||||||
|
|
||||||
CLASS(meshVol1DCartSegm), INTENT(in):: self
|
CLASS(meshVol1DCartSegm), INTENT(in):: self
|
||||||
REAL(8):: ke(1:2,1:2)
|
REAL(8), ALLOCATABLE:: localK(:,:)
|
||||||
REAL(8):: Xii(1:3)
|
REAL(8):: Xii(1:3)
|
||||||
REAL(8):: dPsi(1:1, 1:2)
|
REAL(8):: dPsi(1:1, 1:2)
|
||||||
REAL(8):: invJ(1), detJ
|
REAL(8):: invJ(1), detJ
|
||||||
INTEGER:: l
|
INTEGER:: l
|
||||||
|
|
||||||
ke = 0.D0
|
ALLOCATE(localK(1:2,1:2))
|
||||||
|
localK = 0.D0
|
||||||
Xii = 0.D0
|
Xii = 0.D0
|
||||||
|
|
||||||
DO l = 1, 3
|
DO l = 1, 3
|
||||||
xii(1) = corSeg(l)
|
xii(1) = corSeg(l)
|
||||||
dPsi = self%dPsi(Xii)
|
dPsi = self%dPsi(Xii)
|
||||||
detJ = self%detJac(Xii, dPsi)
|
detJ = self%detJac(Xii, dPsi)
|
||||||
invJ = self%invJac(Xii, dPsi)
|
invJ = self%invJac(Xii, dPsi)
|
||||||
ke = ke + MATMUL(RESHAPE(MATMUL(invJ,dPsi), (/ 2, 1/)), &
|
localK = localK + MATMUL(RESHAPE(MATMUL(invJ,dPsi), (/ 2, 1/)), &
|
||||||
RESHAPE(MATMUL(invJ,dPsi), (/ 1, 2/)))* &
|
RESHAPE(MATMUL(invJ,dPsi), (/ 1, 2/)))* &
|
||||||
wSeg(l)/detJ
|
wSeg(l)/detJ
|
||||||
|
|
||||||
|
|
@ -395,12 +396,12 @@ MODULE moduleMesh1DCart
|
||||||
w_p = self%weight(part%xi)
|
w_p = self%weight(part%xi)
|
||||||
tensorS = outerProduct(part%v, part%v)
|
tensorS = outerProduct(part%v, part%v)
|
||||||
|
|
||||||
vertex => self%n1%output(part%sp)
|
vertex => self%n1%output(part%species%n)
|
||||||
vertex%den = vertex%den + part%weight*w_p(1)
|
vertex%den = vertex%den + part%weight*w_p(1)
|
||||||
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(1)*part%v(:)
|
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(1)*part%v(:)
|
||||||
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(1)*tensorS
|
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(1)*tensorS
|
||||||
|
|
||||||
vertex => self%n2%output(part%sp)
|
vertex => self%n2%output(part%species%n)
|
||||||
vertex%den = vertex%den + part%weight*w_p(2)
|
vertex%den = vertex%den + part%weight*w_p(2)
|
||||||
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(2)*part%v(:)
|
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(2)*part%v(:)
|
||||||
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(2)*tensorS
|
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(2)*tensorS
|
||||||
|
|
@ -459,7 +460,7 @@ MODULE moduleMesh1DCart
|
||||||
|
|
||||||
CLASS(meshVol1DCartSegm), INTENT(in):: self
|
CLASS(meshVol1DCartSegm), INTENT(in):: self
|
||||||
REAL(8), INTENT(in):: xi(1:3)
|
REAL(8), INTENT(in):: xi(1:3)
|
||||||
CLASS(*), POINTER, INTENT(out):: nextElement
|
CLASS(meshElement), POINTER, INTENT(out):: nextElement
|
||||||
|
|
||||||
NULLIFY(nextElement)
|
NULLIFY(nextElement)
|
||||||
IF (xi(1) < -1.D0) THEN
|
IF (xi(1) < -1.D0) THEN
|
||||||
|
|
@ -522,6 +523,121 @@ MODULE moduleMesh1DCart
|
||||||
|
|
||||||
END FUNCTION invJ1DCart
|
END FUNCTION invJ1DCart
|
||||||
|
|
||||||
|
SUBROUTINE connectMesh1DCart(self)
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
CLASS(meshGeneric), INTENT(inout):: self
|
||||||
|
INTEGER:: e, et
|
||||||
|
|
||||||
|
DO e = 1, self%numVols
|
||||||
|
!Connect Vol-Vol
|
||||||
|
DO et = 1, self%numVols
|
||||||
|
IF (e /= et) THEN
|
||||||
|
CALL connectVolVol(self%vols(e)%obj, self%vols(et)%obj)
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END DO
|
||||||
|
|
||||||
|
SELECT TYPE(self)
|
||||||
|
TYPE IS(meshParticles)
|
||||||
|
!Connect Vol-Edge
|
||||||
|
DO et = 1, self%numEdges
|
||||||
|
CALL connectVolEdge(self%vols(e)%obj, self%edges(et)%obj)
|
||||||
|
|
||||||
|
END DO
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
END DO
|
||||||
|
|
||||||
|
END SUBROUTINE connectMesh1DCart
|
||||||
|
|
||||||
|
SUBROUTINE connectVolVol(elemA, elemB)
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
CLASS(meshVol), INTENT(inout):: elemA
|
||||||
|
CLASS(meshVol), INTENT(inout):: elemB
|
||||||
|
|
||||||
|
SELECT TYPE(elemA)
|
||||||
|
TYPE IS(meshVol1DCartSegm)
|
||||||
|
SELECT TYPE(elemB)
|
||||||
|
TYPE IS(meshVol1DCartSegm)
|
||||||
|
CALL connectSegmSegm(elemA, elemB)
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
END SUBROUTINE connectVolVol
|
||||||
|
|
||||||
|
SUBROUTINE connectSegmSegm(elemA, elemB)
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
CLASS(meshVol1DCartSegm), INTENT(inout), TARGET:: elemA
|
||||||
|
CLASS(meshVol1DCartSegm), INTENT(inout), TARGET:: elemB
|
||||||
|
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e1) .AND. &
|
||||||
|
elemA%n2%n == elemB%n1%n) THEN
|
||||||
|
elemA%e1 => elemB
|
||||||
|
elemB%e2 => elemA
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e2) .AND. &
|
||||||
|
elemA%n1%n == elemB%n2%n) THEN
|
||||||
|
|
||||||
|
elemA%e2 => elemB
|
||||||
|
elemB%e1 => elemA
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END SUBROUTINE connectSegmSegm
|
||||||
|
|
||||||
|
SUBROUTINE connectVolEdge(elemA, elemB)
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
CLASS(meshVol), INTENT(inout):: elemA
|
||||||
|
CLASS(meshEdge), INTENT(inout):: elemB
|
||||||
|
|
||||||
|
SELECT TYPE(elemA)
|
||||||
|
TYPE IS (meshVol1DCartSegm)
|
||||||
|
SELECT TYPE(elemB)
|
||||||
|
CLASS IS(meshEdge1DCart)
|
||||||
|
CALL connectSegmEdge(elemA, elemB)
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
END SUBROUTINE connectVolEdge
|
||||||
|
|
||||||
|
SUBROUTINE connectSegmEdge(elemA, elemB)
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
CLASS(meshVol1DCartSegm), INTENT(inout), TARGET:: elemA
|
||||||
|
CLASS(meshEdge1DCart), INTENT(inout), TARGET:: elemB
|
||||||
|
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e1) .AND. &
|
||||||
|
elemA%n2%n == elemB%n1%n) THEN
|
||||||
|
|
||||||
|
elemA%e1 => elemB
|
||||||
|
elemB%e2 => elemA
|
||||||
|
|
||||||
|
!Revers the normal to point inside the domain
|
||||||
|
elemB%normal = - elemB%normal
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e2) .AND. &
|
||||||
|
elemA%n1%n == elemB%n1%n) THEN
|
||||||
|
|
||||||
|
elemA%e2 => elemB
|
||||||
|
elemB%e1 => elemA
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END SUBROUTINE connectSegmEdge
|
||||||
|
|
||||||
END MODULE moduleMesh1DCart
|
END MODULE moduleMesh1DCart
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,264 +0,0 @@
|
||||||
MODULE moduleMesh1DCartRead
|
|
||||||
USE moduleMesh
|
|
||||||
USE moduleMesh1DCart
|
|
||||||
|
|
||||||
!TODO: make this abstract to allow different mesh formats
|
|
||||||
TYPE, EXTENDS(meshGeneric):: mesh1DCartGeneric
|
|
||||||
CONTAINS
|
|
||||||
PROCEDURE, PASS:: init => init1DCartMesh
|
|
||||||
PROCEDURE, PASS:: readMesh => readMesh1DCart
|
|
||||||
|
|
||||||
END TYPE
|
|
||||||
|
|
||||||
INTERFACE connected
|
|
||||||
MODULE PROCEDURE connectedVolVol, connectedVolEdge
|
|
||||||
|
|
||||||
END INTERFACE connected
|
|
||||||
|
|
||||||
CONTAINS
|
|
||||||
!Init 1D mesh
|
|
||||||
SUBROUTINE init1DCartMesh(self, meshFormat)
|
|
||||||
USE moduleMesh
|
|
||||||
USE moduleErrors
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
CLASS(mesh1DCartGeneric), INTENT(out):: self
|
|
||||||
CHARACTER(:), ALLOCATABLE, INTENT(in):: meshFormat
|
|
||||||
|
|
||||||
SELECT CASE(meshFormat)
|
|
||||||
CASE ("gmsh")
|
|
||||||
self%printOutput => printOutputGmsh
|
|
||||||
self%printColl => printCollGmsh
|
|
||||||
self%printEM => printEMGmsh
|
|
||||||
|
|
||||||
CASE DEFAULT
|
|
||||||
CALL criticalError("Mesh type " // meshFormat // " not supported.", "init1DCart")
|
|
||||||
|
|
||||||
END SELECT
|
|
||||||
|
|
||||||
END SUBROUTINE init1DCartMesh
|
|
||||||
|
|
||||||
!Reads 1D mesh
|
|
||||||
SUBROUTINE readMesh1DCart(self, filename)
|
|
||||||
USE moduleBoundary
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
CLASS(mesh1DCartGeneric), INTENT(inout):: self
|
|
||||||
CHARACTER(:), ALLOCATABLE, INTENT(in):: filename
|
|
||||||
REAL(8):: x
|
|
||||||
INTEGER:: p(1:2)
|
|
||||||
INTEGER:: e, et, n, eTemp, elemType, bt
|
|
||||||
INTEGER:: totalNumElem
|
|
||||||
INTEGER:: boundaryType
|
|
||||||
|
|
||||||
!Open file mesh
|
|
||||||
OPEN(10, FILE=TRIM(filename))
|
|
||||||
!Skip header
|
|
||||||
READ(10, *)
|
|
||||||
READ(10, *)
|
|
||||||
READ(10, *)
|
|
||||||
READ(10, *)
|
|
||||||
!Read number of nodes
|
|
||||||
READ(10, *) self%numNodes
|
|
||||||
!Allocate required matrices and vectors
|
|
||||||
ALLOCATE(self%nodes(1:self%numNodes))
|
|
||||||
ALLOCATE(self%K(1:self%numNodes, 1:self%numNodes))
|
|
||||||
ALLOCATE(self%IPIV(1:self%numNodes, 1:self%numNodes))
|
|
||||||
self%K = 0.D0
|
|
||||||
self%IPIV = 0
|
|
||||||
!Read nodes coordinates. Only relevant for x
|
|
||||||
DO e = 1, self%numNodes
|
|
||||||
READ(10, *) n, x
|
|
||||||
ALLOCATE(meshNode1DCart:: self%nodes(n)%obj)
|
|
||||||
CALL self%nodes(n)%obj%init(n, (/ x, 0.D0, 0.D0 /))
|
|
||||||
|
|
||||||
END DO
|
|
||||||
!Skips comments
|
|
||||||
READ(10, *)
|
|
||||||
READ(10, *)
|
|
||||||
!Reads the total number of elements (edges+vol)
|
|
||||||
READ(10, *) totalNumElem
|
|
||||||
self%numEdges = 0
|
|
||||||
DO e = 1, totalNumElem
|
|
||||||
READ(10, *) eTemp, elemType
|
|
||||||
IF (elemType == 15) THEN !15 is physical node in GMSH
|
|
||||||
self%numEdges = e
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END DO
|
|
||||||
|
|
||||||
!Substract the number of edges to the total number of elements
|
|
||||||
!to obtain the number of volume elements
|
|
||||||
self%numVols = totalNumelem - self%numEdges
|
|
||||||
!Allocates arrays
|
|
||||||
ALLOCATE(self%edges(1:self%numEdges))
|
|
||||||
ALLOCATE(self%vols(1:self%numVols))
|
|
||||||
|
|
||||||
!Go back to the beginning of reading elements
|
|
||||||
DO e = 1, totalNumelem
|
|
||||||
BACKSPACE(10)
|
|
||||||
|
|
||||||
END DO
|
|
||||||
|
|
||||||
!Reads edges
|
|
||||||
DO e = 1, self%numEdges
|
|
||||||
READ(10, *) n, elemType, eTemp, boundaryType, eTemp, p(1)
|
|
||||||
!Associate boundary condition
|
|
||||||
bt = getBoundaryId(boundaryType)
|
|
||||||
|
|
||||||
ALLOCATE(meshEdge1DCart:: self%edges(e)%obj)
|
|
||||||
|
|
||||||
CALL self%edges(e)%obj%init(n, p(1:1), bt, boundaryType)
|
|
||||||
|
|
||||||
END DO
|
|
||||||
|
|
||||||
!Read and initialize volumes
|
|
||||||
DO e = 1, self%numVols
|
|
||||||
READ(10, *) n, elemType, eTemp, eTemp, eTemp, p(1:2)
|
|
||||||
ALLOCATE(meshVol1DCartSegm:: self%vols(e)%obj)
|
|
||||||
CALL self%vols(e)%obj%init(n - self%numEdges, p(1:2))
|
|
||||||
|
|
||||||
END DO
|
|
||||||
|
|
||||||
CLOSE(10)
|
|
||||||
|
|
||||||
!Build connectivity between elements
|
|
||||||
DO e = 1, self%numVols
|
|
||||||
!Connectivity between volumes
|
|
||||||
DO et = 1, self%numVols
|
|
||||||
IF (e /= et) THEN
|
|
||||||
CALL connected(self%vols(e)%obj, self%vols(et)%obj)
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END DO
|
|
||||||
|
|
||||||
!Connectivity betwen vols and edges
|
|
||||||
DO et = 1, self%numEdges
|
|
||||||
CALL connected(self%vols(e)%obj, self%edges(et)%obj)
|
|
||||||
|
|
||||||
END DO
|
|
||||||
|
|
||||||
!Constructs the global K matrix
|
|
||||||
CALL constructGlobalK(self%K, self%vols(e)%obj)
|
|
||||||
|
|
||||||
END DO
|
|
||||||
|
|
||||||
END SUBROUTINE readMesh1DCart
|
|
||||||
|
|
||||||
SUBROUTINE connectedVolVol(elemA, elemB)
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
CLASS(meshVol), INTENT(inout):: elemA
|
|
||||||
CLASS(meshVol), INTENT(inout):: elemB
|
|
||||||
|
|
||||||
SELECT TYPE(elemA)
|
|
||||||
TYPE IS(meshVol1DCartSegm)
|
|
||||||
SELECT TYPE(elemB)
|
|
||||||
TYPE IS(meshVol1DCartSegm)
|
|
||||||
CALL connectedSegmSegm(elemA, elemB)
|
|
||||||
|
|
||||||
END SELECT
|
|
||||||
|
|
||||||
END SELECT
|
|
||||||
|
|
||||||
END SUBROUTINE connectedVolVol
|
|
||||||
|
|
||||||
SUBROUTINE connectedSegmSegm(elemA, elemB)
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
CLASS(meshVol1DCartSegm), INTENT(inout), TARGET:: elemA
|
|
||||||
CLASS(meshVol1DCartSegm), INTENT(inout), TARGET:: elemB
|
|
||||||
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e1) .AND. &
|
|
||||||
elemA%n2%n == elemB%n1%n) THEN
|
|
||||||
elemA%e1 => elemB
|
|
||||||
elemB%e2 => elemA
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e2) .AND. &
|
|
||||||
elemA%n1%n == elemB%n2%n) THEN
|
|
||||||
|
|
||||||
elemA%e2 => elemB
|
|
||||||
elemB%e1 => elemA
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END SUBROUTINE connectedSegmSegm
|
|
||||||
|
|
||||||
SUBROUTINE connectedVolEdge(elemA, elemB)
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
CLASS(meshVol), INTENT(inout):: elemA
|
|
||||||
CLASS(meshEdge), INTENT(inout):: elemB
|
|
||||||
|
|
||||||
SELECT TYPE(elemA)
|
|
||||||
TYPE IS (meshVol1DCartSegm)
|
|
||||||
SELECT TYPE(elemB)
|
|
||||||
CLASS IS(meshEdge1DCart)
|
|
||||||
CALL connectedSegmEdge(elemA, elemB)
|
|
||||||
|
|
||||||
END SELECT
|
|
||||||
|
|
||||||
END SELECT
|
|
||||||
|
|
||||||
END SUBROUTINE connectedVolEdge
|
|
||||||
|
|
||||||
SUBROUTINE connectedSegmEdge(elemA, elemB)
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
CLASS(meshVol1DCartSegm), INTENT(inout), TARGET:: elemA
|
|
||||||
CLASS(meshEdge1DCart), INTENT(inout), TARGET:: elemB
|
|
||||||
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e1) .AND. &
|
|
||||||
elemA%n2%n == elemB%n1%n) THEN
|
|
||||||
|
|
||||||
elemA%e1 => elemB
|
|
||||||
elemB%e2 => elemA
|
|
||||||
|
|
||||||
!Revers the normal to point inside the domain
|
|
||||||
elemB%normal = - elemB%normal
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e2) .AND. &
|
|
||||||
elemA%n1%n == elemB%n1%n) THEN
|
|
||||||
|
|
||||||
elemA%e2 => elemB
|
|
||||||
elemB%e1 => elemA
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END SUBROUTINE connectedSegmEdge
|
|
||||||
|
|
||||||
SUBROUTINE constructGlobalK(K, elem)
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
REAL(8), INTENT(inout):: K(1:,1:)
|
|
||||||
CLASS(meshVol), INTENT(in):: elem
|
|
||||||
REAL(8):: localK(1:2,1:2)
|
|
||||||
INTEGER:: i, j
|
|
||||||
INTEGER:: n(1:2)
|
|
||||||
|
|
||||||
SELECT TYPE(elem)
|
|
||||||
TYPE IS(meshVol1DCartSegm)
|
|
||||||
localK = elem%elemK()
|
|
||||||
n = (/ elem%n1%n, elem%n2%n /)
|
|
||||||
|
|
||||||
CLASS DEFAULT
|
|
||||||
n = 0
|
|
||||||
localK = 0.D0
|
|
||||||
|
|
||||||
END SELECT
|
|
||||||
|
|
||||||
DO i = 1, 2
|
|
||||||
DO j = 1, 2
|
|
||||||
K(n(i), n(j)) = K(n(i), n(j)) + localK(i, j)
|
|
||||||
END DO
|
|
||||||
END DO
|
|
||||||
|
|
||||||
END SUBROUTINE constructGlobalK
|
|
||||||
|
|
||||||
END MODULE moduleMesh1DCartRead
|
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
all: moduleMesh1DRad.o moduleMesh1DRadRead.o
|
all: moduleMesh1DRad.o
|
||||||
|
|
||||||
moduleMesh1DRad.o: moduleMesh1DRad.f90
|
moduleMesh1DRad.o: moduleMesh1DRad.f90
|
||||||
$(FC) $(FCFLAGS) -c $(subst .o,.f90,$@) -o $(OBJDIR)/$@
|
$(FC) $(FCFLAGS) -c $(subst .o,.f90,$@) -o $(OBJDIR)/$@
|
||||||
|
|
||||||
moduleMesh1DRadRead.o: moduleMesh1DRad.o moduleMesh1DRadRead.f90
|
|
||||||
$(FC) $(FCFLAGS) -c $(subst .o,.f90,$@) -o $(OBJDIR)/$@
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ MODULE moduleMesh1DRad
|
||||||
!Connectivity to nodes
|
!Connectivity to nodes
|
||||||
CLASS(meshNode), POINTER:: n1 => NULL(), n2 => NULL()
|
CLASS(meshNode), POINTER:: n1 => NULL(), n2 => NULL()
|
||||||
!Connectivity to adjacent elements
|
!Connectivity to adjacent elements
|
||||||
CLASS(*), POINTER:: e1 => NULL(), e2 => NULL()
|
CLASS(meshElement), POINTER:: e1 => NULL(), e2 => NULL()
|
||||||
REAL(8):: arNodes(1:2)
|
REAL(8):: arNodes(1:2)
|
||||||
CONTAINS
|
CONTAINS
|
||||||
PROCEDURE, PASS:: init => initVol1DRadSegm
|
PROCEDURE, PASS:: init => initVol1DRadSegm
|
||||||
|
|
@ -200,18 +200,19 @@ MODULE moduleMesh1DRad
|
||||||
!VOLUME FUNCTIONS
|
!VOLUME FUNCTIONS
|
||||||
!SEGMENT FUNCTIONS
|
!SEGMENT FUNCTIONS
|
||||||
!Init segment element
|
!Init segment element
|
||||||
SUBROUTINE initVol1DRadSegm(self, n, p)
|
SUBROUTINE initVol1DRadSegm(self, n, p, nodes)
|
||||||
USE moduleRefParam
|
USE moduleRefParam
|
||||||
IMPLICIT NONE
|
IMPLICIT NONE
|
||||||
|
|
||||||
CLASS(meshVol1DRadSegm), INTENT(out):: self
|
CLASS(meshVol1DRadSegm), INTENT(out):: self
|
||||||
INTEGER, INTENT(in):: n
|
INTEGER, INTENT(in):: n
|
||||||
INTEGER, INTENT(in):: p(:)
|
INTEGER, INTENT(in):: p(:)
|
||||||
|
TYPE(meshNodeCont), INTENT(in), TARGET:: nodes(:)
|
||||||
REAL(8), DIMENSION(1:3):: r1, r2
|
REAL(8), DIMENSION(1:3):: r1, r2
|
||||||
|
|
||||||
self%n = n
|
self%n = n
|
||||||
self%n1 => mesh%nodes(p(1))%obj
|
self%n1 => nodes(p(1))%obj
|
||||||
self%n2 => mesh%nodes(p(2))%obj
|
self%n2 => nodes(p(2))%obj
|
||||||
!Get element coordinates
|
!Get element coordinates
|
||||||
r1 = self%n1%getCoordinates()
|
r1 = self%n1%getCoordinates()
|
||||||
r2 = self%n2%getCoordinates()
|
r2 = self%n2%getCoordinates()
|
||||||
|
|
@ -312,19 +313,20 @@ MODULE moduleMesh1DRad
|
||||||
END SUBROUTINE partialDerRad
|
END SUBROUTINE partialDerRad
|
||||||
|
|
||||||
!Computes local stiffness matrix
|
!Computes local stiffness matrix
|
||||||
PURE FUNCTION elemKRad(self) RESULT(ke)
|
PURE FUNCTION elemKRad(self) RESULT(localK)
|
||||||
USE moduleConstParam, ONLY: PI2
|
USE moduleConstParam, ONLY: PI2
|
||||||
IMPLICIT NONE
|
IMPLICIT NONE
|
||||||
|
|
||||||
CLASS(meshVol1DRadSegm), INTENT(in):: self
|
CLASS(meshVol1DRadSegm), INTENT(in):: self
|
||||||
REAL(8):: ke(1:2,1:2)
|
REAL(8), ALLOCATABLE:: localK(:,:)
|
||||||
REAL(8):: Xii(1:3)
|
REAL(8):: Xii(1:3)
|
||||||
REAL(8):: dPsi(1:1, 1:2)
|
REAL(8):: dPsi(1:1, 1:2)
|
||||||
REAL(8):: invJ(1), detJ
|
REAL(8):: invJ(1), detJ
|
||||||
REAL(8):: r, fPsi(1:2)
|
REAL(8):: r, fPsi(1:2)
|
||||||
INTEGER:: l
|
INTEGER:: l
|
||||||
|
|
||||||
ke = 0.D0
|
ALLOCATE(localK(1:2, 1:2))
|
||||||
|
localK = 0.D0
|
||||||
Xii = 0.D0
|
Xii = 0.D0
|
||||||
DO l = 1, 3
|
DO l = 1, 3
|
||||||
xii(1) = corSeg(l)
|
xii(1) = corSeg(l)
|
||||||
|
|
@ -333,13 +335,13 @@ MODULE moduleMesh1DRad
|
||||||
invJ = self%invJac(Xii, dPsi)
|
invJ = self%invJac(Xii, dPsi)
|
||||||
fPsi = self%fPsi(Xii)
|
fPsi = self%fPsi(Xii)
|
||||||
r = DOT_PRODUCT(fPsi, self%r)
|
r = DOT_PRODUCT(fPsi, self%r)
|
||||||
ke = ke + MATMUL(RESHAPE(MATMUL(invJ,dPsi), (/ 2, 1/)), &
|
localK = localK + MATMUL(RESHAPE(MATMUL(invJ,dPsi), (/ 2, 1/)), &
|
||||||
RESHAPE(MATMUL(invJ,dPsi), (/ 1, 2/)))* &
|
RESHAPE(MATMUL(invJ,dPsi), (/ 1, 2/)))* &
|
||||||
r*wSeg(l)/detJ
|
r*wSeg(l)/detJ
|
||||||
|
|
||||||
END DO
|
END DO
|
||||||
|
|
||||||
ke = ke*PI2
|
localK = localK*PI2
|
||||||
|
|
||||||
END FUNCTION elemKRad
|
END FUNCTION elemKRad
|
||||||
|
|
||||||
|
|
@ -406,12 +408,12 @@ MODULE moduleMesh1DRad
|
||||||
w_p = self%weight(part%xi)
|
w_p = self%weight(part%xi)
|
||||||
tensorS = outerProduct(part%v, part%v)
|
tensorS = outerProduct(part%v, part%v)
|
||||||
|
|
||||||
vertex => self%n1%output(part%sp)
|
vertex => self%n1%output(part%species%n)
|
||||||
vertex%den = vertex%den + part%weight*w_p(1)
|
vertex%den = vertex%den + part%weight*w_p(1)
|
||||||
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(1)*part%v(:)
|
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(1)*part%v(:)
|
||||||
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(1)*tensorS
|
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(1)*tensorS
|
||||||
|
|
||||||
vertex => self%n2%output(part%sp)
|
vertex => self%n2%output(part%species%n)
|
||||||
vertex%den = vertex%den + part%weight*w_p(2)
|
vertex%den = vertex%den + part%weight*w_p(2)
|
||||||
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(2)*part%v(:)
|
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(2)*part%v(:)
|
||||||
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(2)*tensorS
|
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(2)*tensorS
|
||||||
|
|
@ -470,7 +472,7 @@ MODULE moduleMesh1DRad
|
||||||
|
|
||||||
CLASS(meshVol1DRadSegm), INTENT(in):: self
|
CLASS(meshVol1DRadSegm), INTENT(in):: self
|
||||||
REAL(8), INTENT(in):: xi(1:3)
|
REAL(8), INTENT(in):: xi(1:3)
|
||||||
CLASS(*), POINTER, INTENT(out):: nextElement
|
CLASS(meshElement), POINTER, INTENT(out):: nextElement
|
||||||
|
|
||||||
NULLIFY(nextElement)
|
NULLIFY(nextElement)
|
||||||
IF (xi(1) < -1.D0) THEN
|
IF (xi(1) < -1.D0) THEN
|
||||||
|
|
@ -532,5 +534,121 @@ MODULE moduleMesh1DRad
|
||||||
|
|
||||||
END FUNCTION invJ1DRad
|
END FUNCTION invJ1DRad
|
||||||
|
|
||||||
|
SUBROUTINE connectMesh1DRad(self)
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
CLASS(meshGeneric), INTENT(inout):: self
|
||||||
|
INTEGER:: e, et
|
||||||
|
|
||||||
|
DO e = 1, self%numVols
|
||||||
|
!Connect Vol-Vol
|
||||||
|
DO et = 1, self%numVols
|
||||||
|
IF (e /= et) THEN
|
||||||
|
CALL connectVolVol(self%vols(e)%obj, self%vols(et)%obj)
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END DO
|
||||||
|
|
||||||
|
SELECT TYPE(self)
|
||||||
|
TYPE IS(meshParticles)
|
||||||
|
!Connect Vol-Edge
|
||||||
|
DO et = 1, self%numEdges
|
||||||
|
CALL connectVolEdge(self%vols(e)%obj, self%edges(et)%obj)
|
||||||
|
|
||||||
|
END DO
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
END DO
|
||||||
|
|
||||||
|
END SUBROUTINE connectMesh1DRad
|
||||||
|
|
||||||
|
SUBROUTINE connectVolVol(elemA, elemB)
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
CLASS(meshVol), INTENT(inout):: elemA
|
||||||
|
CLASS(meshVol), INTENT(inout):: elemB
|
||||||
|
|
||||||
|
SELECT TYPE(elemA)
|
||||||
|
TYPE IS(meshVol1DRadSegm)
|
||||||
|
SELECT TYPE(elemB)
|
||||||
|
TYPE IS(meshVol1DRadSegm)
|
||||||
|
CALL connectSegmSegm(elemA, elemB)
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
END SUBROUTINE connectVolVol
|
||||||
|
|
||||||
|
SUBROUTINE connectSegmSegm(elemA, elemB)
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
CLASS(meshVol1DRadSegm), INTENT(inout), TARGET:: elemA
|
||||||
|
CLASS(meshVol1DRadSegm), INTENT(inout), TARGET:: elemB
|
||||||
|
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e1) .AND. &
|
||||||
|
elemA%n2%n == elemB%n1%n) THEN
|
||||||
|
elemA%e1 => elemB
|
||||||
|
elemB%e2 => elemA
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e2) .AND. &
|
||||||
|
elemA%n1%n == elemB%n2%n) THEN
|
||||||
|
|
||||||
|
elemA%e2 => elemB
|
||||||
|
elemB%e1 => elemA
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END SUBROUTINE connectSegmSegm
|
||||||
|
|
||||||
|
SUBROUTINE connectVolEdge(elemA, elemB)
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
CLASS(meshVol), INTENT(inout):: elemA
|
||||||
|
CLASS(meshEdge), INTENT(inout):: elemB
|
||||||
|
|
||||||
|
SELECT TYPE(elemA)
|
||||||
|
TYPE IS (meshVol1DRadSegm)
|
||||||
|
SELECT TYPE(elemB)
|
||||||
|
CLASS IS(meshEdge1DRad)
|
||||||
|
CALL connectSegmEdge(elemA, elemB)
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
END SUBROUTINE connectVolEdge
|
||||||
|
|
||||||
|
SUBROUTINE connectSegmEdge(elemA, elemB)
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
CLASS(meshVol1DRadSegm), INTENT(inout), TARGET:: elemA
|
||||||
|
CLASS(meshEdge1DRad), INTENT(inout), TARGET:: elemB
|
||||||
|
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e1) .AND. &
|
||||||
|
elemA%n2%n == elemB%n1%n) THEN
|
||||||
|
|
||||||
|
elemA%e1 => elemB
|
||||||
|
elemB%e2 => elemA
|
||||||
|
|
||||||
|
!Revers the normal to point inside the domain
|
||||||
|
elemB%normal = - elemB%normal
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e2) .AND. &
|
||||||
|
elemA%n1%n == elemB%n1%n) THEN
|
||||||
|
|
||||||
|
elemA%e2 => elemB
|
||||||
|
elemB%e1 => elemA
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END SUBROUTINE connectSegmEdge
|
||||||
|
|
||||||
END MODULE moduleMesh1DRad
|
END MODULE moduleMesh1DRad
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,264 +0,0 @@
|
||||||
MODULE moduleMesh1DRadRead
|
|
||||||
USE moduleMesh
|
|
||||||
USE moduleMesh1DRad
|
|
||||||
|
|
||||||
!TODO: make this abstract to allow different mesh formats
|
|
||||||
TYPE, EXTENDS(meshGeneric):: mesh1DRadGeneric
|
|
||||||
CONTAINS
|
|
||||||
PROCEDURE, PASS:: init => init1DRadMesh
|
|
||||||
PROCEDURE, PASS:: readMesh => readMesh1DRad
|
|
||||||
|
|
||||||
END TYPE
|
|
||||||
|
|
||||||
INTERFACE connected
|
|
||||||
MODULE PROCEDURE connectedVolVol, connectedVolEdge
|
|
||||||
|
|
||||||
END INTERFACE connected
|
|
||||||
|
|
||||||
CONTAINS
|
|
||||||
!Init 1D mesh
|
|
||||||
SUBROUTINE init1DRadMesh(self, meshFormat)
|
|
||||||
USE moduleMesh
|
|
||||||
USE moduleErrors
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
CLASS(mesh1DRadGeneric), INTENT(out):: self
|
|
||||||
CHARACTER(:), ALLOCATABLE, INTENT(in):: meshFormat
|
|
||||||
|
|
||||||
SELECT CASE(meshFormat)
|
|
||||||
CASE ("gmsh")
|
|
||||||
self%printOutput => printOutputGmsh
|
|
||||||
self%printColl => printCollGmsh
|
|
||||||
self%printEM => printEMGmsh
|
|
||||||
|
|
||||||
CASE DEFAULT
|
|
||||||
CALL criticalError("Mesh type " // meshFormat // " not supported.", "init1DRad")
|
|
||||||
|
|
||||||
END SELECT
|
|
||||||
|
|
||||||
END SUBROUTINE init1DRadMesh
|
|
||||||
|
|
||||||
!Reads 1D mesh
|
|
||||||
SUBROUTINE readMesh1DRad(self, filename)
|
|
||||||
USE moduleBoundary
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
CLASS(mesh1DRadGeneric), INTENT(inout):: self
|
|
||||||
CHARACTER(:), ALLOCATABLE, INTENT(in):: filename
|
|
||||||
REAL(8):: x
|
|
||||||
INTEGER:: p(1:2)
|
|
||||||
INTEGER:: e, et, n, eTemp, elemType, bt
|
|
||||||
INTEGER:: totalNumElem
|
|
||||||
INTEGER:: boundaryType
|
|
||||||
|
|
||||||
!Open file mesh
|
|
||||||
OPEN(10, FILE=TRIM(filename))
|
|
||||||
!Skip header
|
|
||||||
READ(10, *)
|
|
||||||
READ(10, *)
|
|
||||||
READ(10, *)
|
|
||||||
READ(10, *)
|
|
||||||
!Read number of nodes
|
|
||||||
READ(10, *) self%numNodes
|
|
||||||
!Allocate required matrices and vectors
|
|
||||||
ALLOCATE(self%nodes(1:self%numNodes))
|
|
||||||
ALLOCATE(self%K(1:self%numNodes, 1:self%numNodes))
|
|
||||||
ALLOCATE(self%IPIV(1:self%numNodes, 1:self%numNodes))
|
|
||||||
self%K = 0.D0
|
|
||||||
self%IPIV = 0
|
|
||||||
!Read nodes coordinates. Only relevant for x
|
|
||||||
DO e = 1, self%numNodes
|
|
||||||
READ(10, *) n, x
|
|
||||||
ALLOCATE(meshNode1DRad:: self%nodes(n)%obj)
|
|
||||||
CALL self%nodes(n)%obj%init(n, (/ x, 0.D0, 0.D0 /))
|
|
||||||
|
|
||||||
END DO
|
|
||||||
!Skips comments
|
|
||||||
READ(10, *)
|
|
||||||
READ(10, *)
|
|
||||||
!Reads the total number of elements (edges+vol)
|
|
||||||
READ(10, *) totalNumElem
|
|
||||||
self%numEdges = 0
|
|
||||||
DO e = 1, totalNumElem
|
|
||||||
READ(10, *) eTemp, elemType
|
|
||||||
IF (elemType == 15) THEN !15 is physical node in GMSH
|
|
||||||
self%numEdges = e
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END DO
|
|
||||||
|
|
||||||
!Substract the number of edges to the total number of elements
|
|
||||||
!to obtain the number of volume elements
|
|
||||||
self%numVols = totalNumelem - self%numEdges
|
|
||||||
!Allocates arrays
|
|
||||||
ALLOCATE(self%edges(1:self%numEdges))
|
|
||||||
ALLOCATE(self%vols(1:self%numVols))
|
|
||||||
|
|
||||||
!Go back to the beginning of reading elements
|
|
||||||
DO e = 1, totalNumelem
|
|
||||||
BACKSPACE(10)
|
|
||||||
|
|
||||||
END DO
|
|
||||||
|
|
||||||
!Reads edges
|
|
||||||
DO e = 1, self%numEdges
|
|
||||||
READ(10, *) n, elemType, eTemp, boundaryType, eTemp, p(1)
|
|
||||||
!Associate boundary condition
|
|
||||||
bt = getBoundaryId(boundaryType)
|
|
||||||
|
|
||||||
ALLOCATE(meshEdge1DRad:: self%edges(e)%obj)
|
|
||||||
|
|
||||||
CALL self%edges(e)%obj%init(n, p(1:1), bt, boundaryType)
|
|
||||||
|
|
||||||
END DO
|
|
||||||
|
|
||||||
!Read and initialize volumes
|
|
||||||
DO e = 1, self%numVols
|
|
||||||
READ(10, *) n, elemType, eTemp, eTemp, eTemp, p(1:2)
|
|
||||||
ALLOCATE(meshVol1DRadSegm:: self%vols(e)%obj)
|
|
||||||
CALL self%vols(e)%obj%init(n - self%numEdges, p(1:2))
|
|
||||||
|
|
||||||
END DO
|
|
||||||
|
|
||||||
CLOSE(10)
|
|
||||||
|
|
||||||
!Build connectivity between elements
|
|
||||||
DO e = 1, self%numVols
|
|
||||||
!Connectivity between volumes
|
|
||||||
DO et = 1, self%numVols
|
|
||||||
IF (e /= et) THEN
|
|
||||||
CALL connected(self%vols(e)%obj, self%vols(et)%obj)
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END DO
|
|
||||||
|
|
||||||
!Connectivity betwen vols and edges
|
|
||||||
DO et = 1, self%numEdges
|
|
||||||
CALL connected(self%vols(e)%obj, self%edges(et)%obj)
|
|
||||||
|
|
||||||
END DO
|
|
||||||
|
|
||||||
!Constructs the global K matrix
|
|
||||||
CALL constructGlobalK(self%K, self%vols(e)%obj)
|
|
||||||
|
|
||||||
END DO
|
|
||||||
|
|
||||||
END SUBROUTINE readMesh1DRad
|
|
||||||
|
|
||||||
SUBROUTINE connectedVolVol(elemA, elemB)
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
CLASS(meshVol), INTENT(inout):: elemA
|
|
||||||
CLASS(meshVol), INTENT(inout):: elemB
|
|
||||||
|
|
||||||
SELECT TYPE(elemA)
|
|
||||||
TYPE IS(meshVol1DRadSegm)
|
|
||||||
SELECT TYPE(elemB)
|
|
||||||
TYPE IS(meshVol1DRadSegm)
|
|
||||||
CALL connectedSegmSegm(elemA, elemB)
|
|
||||||
|
|
||||||
END SELECT
|
|
||||||
|
|
||||||
END SELECT
|
|
||||||
|
|
||||||
END SUBROUTINE connectedVolVol
|
|
||||||
|
|
||||||
SUBROUTINE connectedSegmSegm(elemA, elemB)
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
CLASS(meshVol1DRadSegm), INTENT(inout), TARGET:: elemA
|
|
||||||
CLASS(meshVol1DRadSegm), INTENT(inout), TARGET:: elemB
|
|
||||||
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e1) .AND. &
|
|
||||||
elemA%n2%n == elemB%n1%n) THEN
|
|
||||||
elemA%e1 => elemB
|
|
||||||
elemB%e2 => elemA
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e2) .AND. &
|
|
||||||
elemA%n1%n == elemB%n2%n) THEN
|
|
||||||
|
|
||||||
elemA%e2 => elemB
|
|
||||||
elemB%e1 => elemA
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END SUBROUTINE connectedSegmSegm
|
|
||||||
|
|
||||||
SUBROUTINE connectedVolEdge(elemA, elemB)
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
CLASS(meshVol), INTENT(inout):: elemA
|
|
||||||
CLASS(meshEdge), INTENT(inout):: elemB
|
|
||||||
|
|
||||||
SELECT TYPE(elemA)
|
|
||||||
TYPE IS (meshVol1DRadSegm)
|
|
||||||
SELECT TYPE(elemB)
|
|
||||||
CLASS IS(meshEdge1DRad)
|
|
||||||
CALL connectedSegmEdge(elemA, elemB)
|
|
||||||
|
|
||||||
END SELECT
|
|
||||||
|
|
||||||
END SELECT
|
|
||||||
|
|
||||||
END SUBROUTINE connectedVolEdge
|
|
||||||
|
|
||||||
SUBROUTINE connectedSegmEdge(elemA, elemB)
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
CLASS(meshVol1DRadSegm), INTENT(inout), TARGET:: elemA
|
|
||||||
CLASS(meshEdge1DRad), INTENT(inout), TARGET:: elemB
|
|
||||||
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e1) .AND. &
|
|
||||||
elemA%n2%n == elemB%n1%n) THEN
|
|
||||||
|
|
||||||
elemA%e1 => elemB
|
|
||||||
elemB%e2 => elemA
|
|
||||||
|
|
||||||
!Revers the normal to point inside the domain
|
|
||||||
elemB%normal = - elemB%normal
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e2) .AND. &
|
|
||||||
elemA%n1%n == elemB%n1%n) THEN
|
|
||||||
|
|
||||||
elemA%e2 => elemB
|
|
||||||
elemB%e1 => elemA
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END SUBROUTINE connectedSegmEdge
|
|
||||||
|
|
||||||
SUBROUTINE constructGlobalK(K, elem)
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
REAL(8), INTENT(inout):: K(1:,1:)
|
|
||||||
CLASS(meshVol), INTENT(in):: elem
|
|
||||||
REAL(8):: localK(1:2,1:2)
|
|
||||||
INTEGER:: i, j
|
|
||||||
INTEGER:: n(1:2)
|
|
||||||
|
|
||||||
SELECT TYPE(elem)
|
|
||||||
TYPE IS(meshVol1DRadSegm)
|
|
||||||
localK = elem%elemK()
|
|
||||||
n = (/ elem%n1%n, elem%n2%n /)
|
|
||||||
|
|
||||||
CLASS DEFAULT
|
|
||||||
n = 0
|
|
||||||
localK = 0.D0
|
|
||||||
|
|
||||||
END SELECT
|
|
||||||
|
|
||||||
DO i = 1, 2
|
|
||||||
DO j = 1, 2
|
|
||||||
K(n(i), n(j)) = K(n(i), n(j)) + localK(i, j)
|
|
||||||
END DO
|
|
||||||
END DO
|
|
||||||
|
|
||||||
END SUBROUTINE constructGlobalK
|
|
||||||
|
|
||||||
END MODULE moduleMesh1DRadRead
|
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
all : moduleMesh2DCart.o moduleMesh2DCartRead.o
|
all : moduleMesh2DCart.o
|
||||||
|
|
||||||
moduleMesh2DCart.o: moduleMesh2DCart.f90
|
moduleMesh2DCart.o: moduleMesh2DCart.f90
|
||||||
$(FC) $(FCFLAGS) -c $(subst .o,.f90,$@) -o $(OBJDIR)/$@
|
$(FC) $(FCFLAGS) -c $(subst .o,.f90,$@) -o $(OBJDIR)/$@
|
||||||
|
|
||||||
moduleMesh2DCartRead.o: moduleMesh2DCart.o moduleMesh2DCartRead.f90
|
|
||||||
$(FC) $(FCFLAGS) -c $(subst .o,.f90,$@) -o $(OBJDIR)/$@
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ MODULE moduleMesh2DCart
|
||||||
!Connectivity to nodes
|
!Connectivity to nodes
|
||||||
CLASS(meshNode), POINTER:: n1 => NULL(), n2 => NULL(), n3 => NULL(), n4 => NULL()
|
CLASS(meshNode), POINTER:: n1 => NULL(), n2 => NULL(), n3 => NULL(), n4 => NULL()
|
||||||
!Connectivity to adjacent elements
|
!Connectivity to adjacent elements
|
||||||
CLASS(*), POINTER:: e1 => NULL(), e2 => NULL(), e3 => NULL(), e4 => NULL()
|
CLASS(meshElement), POINTER:: e1 => NULL(), e2 => NULL(), e3 => NULL(), e4 => NULL()
|
||||||
REAL(8):: arNodes(1:4) = 0.D0
|
REAL(8):: arNodes(1:4) = 0.D0
|
||||||
CONTAINS
|
CONTAINS
|
||||||
PROCEDURE, PASS:: init => initVolQuad2DCart
|
PROCEDURE, PASS:: init => initVolQuad2DCart
|
||||||
|
|
@ -107,7 +107,7 @@ MODULE moduleMesh2DCart
|
||||||
!Connectivity to nodes
|
!Connectivity to nodes
|
||||||
CLASS(meshNode), POINTER:: n1 => NULL(), n2 => NULL(), n3 => NULL()
|
CLASS(meshNode), POINTER:: n1 => NULL(), n2 => NULL(), n3 => NULL()
|
||||||
!Connectivity to adjacent elements
|
!Connectivity to adjacent elements
|
||||||
CLASS(*), POINTER:: e1 => NULL(), e2 => NULL(), e3 => NULL()
|
CLASS(meshElement), POINTER:: e1 => NULL(), e2 => NULL(), e3 => NULL()
|
||||||
REAL(8):: arNodes(1:3) = 0.D0
|
REAL(8):: arNodes(1:3) = 0.D0
|
||||||
|
|
||||||
CONTAINS
|
CONTAINS
|
||||||
|
|
@ -283,20 +283,21 @@ MODULE moduleMesh2DCart
|
||||||
!VOLUME FUNCTIONS
|
!VOLUME FUNCTIONS
|
||||||
!QUAD FUNCTIONS
|
!QUAD FUNCTIONS
|
||||||
!Inits quadrilateral element
|
!Inits quadrilateral element
|
||||||
SUBROUTINE initVolQuad2DCart(self, n, p)
|
SUBROUTINE initVolQuad2DCart(self, n, p, nodes)
|
||||||
USE moduleRefParam
|
USE moduleRefParam
|
||||||
IMPLICIT NONE
|
IMPLICIT NONE
|
||||||
|
|
||||||
CLASS(meshVol2DCartQuad), INTENT(out):: self
|
CLASS(meshVol2DCartQuad), INTENT(out):: self
|
||||||
INTEGER, INTENT(in):: n
|
INTEGER, INTENT(in):: n
|
||||||
INTEGER, INTENT(in):: p(:)
|
INTEGER, INTENT(in):: p(:)
|
||||||
|
TYPE(meshNodeCont), INTENT(in), TARGET:: nodes(:)
|
||||||
REAL(8), DIMENSION(1:3):: r1, r2, r3, r4
|
REAL(8), DIMENSION(1:3):: r1, r2, r3, r4
|
||||||
|
|
||||||
self%n = n
|
self%n = n
|
||||||
self%n1 => mesh%nodes(p(1))%obj
|
self%n1 => nodes(p(1))%obj
|
||||||
self%n2 => mesh%nodes(p(2))%obj
|
self%n2 => nodes(p(2))%obj
|
||||||
self%n3 => mesh%nodes(p(3))%obj
|
self%n3 => nodes(p(3))%obj
|
||||||
self%n4 => mesh%nodes(p(4))%obj
|
self%n4 => nodes(p(4))%obj
|
||||||
!Get element coordinates
|
!Get element coordinates
|
||||||
r1 = self%n1%getCoordinates()
|
r1 = self%n1%getCoordinates()
|
||||||
r2 = self%n2%getCoordinates()
|
r2 = self%n2%getCoordinates()
|
||||||
|
|
@ -414,17 +415,18 @@ MODULE moduleMesh2DCart
|
||||||
END SUBROUTINE partialDerQuad
|
END SUBROUTINE partialDerQuad
|
||||||
|
|
||||||
!Computes element local stiffness matrix
|
!Computes element local stiffness matrix
|
||||||
PURE FUNCTION elemKQuad(self) RESULT(ke)
|
PURE FUNCTION elemKQuad(self) RESULT(localK)
|
||||||
IMPLICIT NONE
|
IMPLICIT NONE
|
||||||
|
|
||||||
CLASS(meshVol2DCartQuad), INTENT(in):: self
|
CLASS(meshVol2DCartQuad), INTENT(in):: self
|
||||||
|
REAL(8), ALLOCATABLE:: localK(:,:)
|
||||||
REAL(8):: xi(1:3)
|
REAL(8):: xi(1:3)
|
||||||
REAL(8):: fPsi(1:4), dPsi(1:2,1:4)
|
REAL(8):: fPsi(1:4), dPsi(1:2,1:4)
|
||||||
REAL(8):: ke(1:4,1:4)
|
|
||||||
REAL(8):: invJ(1:2,1:2), detJ
|
REAL(8):: invJ(1:2,1:2), detJ
|
||||||
INTEGER:: l, m
|
INTEGER:: l, m
|
||||||
|
|
||||||
ke=0.D0
|
ALLOCATE(localK(1:4, 1:4))
|
||||||
|
localK=0.D0
|
||||||
xi=0.D0
|
xi=0.D0
|
||||||
!Start 2D Gauss Quad Integral
|
!Start 2D Gauss Quad Integral
|
||||||
DO l=1, 3
|
DO l=1, 3
|
||||||
|
|
@ -436,7 +438,7 @@ MODULE moduleMesh2DCart
|
||||||
fPsi = self%fPsi(xi)
|
fPsi = self%fPsi(xi)
|
||||||
detJ = self%detJac(xi,dPsi)
|
detJ = self%detJac(xi,dPsi)
|
||||||
invJ = self%invJac(xi,dPsi)
|
invJ = self%invJac(xi,dPsi)
|
||||||
ke = ke + MATMUL(TRANSPOSE(MATMUL(invJ,dPsi)),MATMUL(invJ,dPsi))*wQuad(l)*wQuad(m)/detJ
|
localK = localK + MATMUL(TRANSPOSE(MATMUL(invJ,dPsi)),MATMUL(invJ,dPsi))*wQuad(l)*wQuad(m)/detJ
|
||||||
|
|
||||||
END DO
|
END DO
|
||||||
END DO
|
END DO
|
||||||
|
|
@ -510,22 +512,22 @@ MODULE moduleMesh2DCart
|
||||||
w_p = self%weight(part%xi)
|
w_p = self%weight(part%xi)
|
||||||
tensorS = outerProduct(part%v, part%v)
|
tensorS = outerProduct(part%v, part%v)
|
||||||
|
|
||||||
vertex => self%n1%output(part%sp)
|
vertex => self%n1%output(part%species%n)
|
||||||
vertex%den = vertex%den + part%weight*w_p(1)
|
vertex%den = vertex%den + part%weight*w_p(1)
|
||||||
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(1)*part%v(:)
|
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(1)*part%v(:)
|
||||||
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(1)*tensorS
|
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(1)*tensorS
|
||||||
|
|
||||||
vertex => self%n2%output(part%sp)
|
vertex => self%n2%output(part%species%n)
|
||||||
vertex%den = vertex%den + part%weight*w_p(2)
|
vertex%den = vertex%den + part%weight*w_p(2)
|
||||||
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(2)*part%v(:)
|
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(2)*part%v(:)
|
||||||
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(2)*tensorS
|
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(2)*tensorS
|
||||||
|
|
||||||
vertex => self%n3%output(part%sp)
|
vertex => self%n3%output(part%species%n)
|
||||||
vertex%den = vertex%den + part%weight*w_p(3)
|
vertex%den = vertex%den + part%weight*w_p(3)
|
||||||
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(3)*part%v(:)
|
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(3)*part%v(:)
|
||||||
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(3)*tensorS
|
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(3)*tensorS
|
||||||
|
|
||||||
vertex => self%n4%output(part%sp)
|
vertex => self%n4%output(part%species%n)
|
||||||
vertex%den = vertex%den + part%weight*w_p(4)
|
vertex%den = vertex%den + part%weight*w_p(4)
|
||||||
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(4)*part%v(:)
|
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(4)*part%v(:)
|
||||||
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(4)*tensorS
|
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(4)*tensorS
|
||||||
|
|
@ -607,7 +609,7 @@ MODULE moduleMesh2DCart
|
||||||
|
|
||||||
CLASS(meshVol2DCartQuad), INTENT(in):: self
|
CLASS(meshVol2DCartQuad), INTENT(in):: self
|
||||||
REAL(8), INTENT(in):: xi(1:3)
|
REAL(8), INTENT(in):: xi(1:3)
|
||||||
CLASS(*), POINTER, INTENT(out):: nextElement
|
CLASS(meshElement), POINTER, INTENT(out):: nextElement
|
||||||
REAL(8):: xiArray(1:4)
|
REAL(8):: xiArray(1:4)
|
||||||
INTEGER:: nextInt
|
INTEGER:: nextInt
|
||||||
|
|
||||||
|
|
@ -630,23 +632,23 @@ MODULE moduleMesh2DCart
|
||||||
|
|
||||||
!TRIA ELEMENT
|
!TRIA ELEMENT
|
||||||
!Init tria element
|
!Init tria element
|
||||||
SUBROUTINE initVolTria2DCart(self, n, p)
|
SUBROUTINE initVolTria2DCart(self, n, p, nodes)
|
||||||
USE moduleRefParam
|
USE moduleRefParam
|
||||||
IMPLICIT NONE
|
IMPLICIT NONE
|
||||||
|
|
||||||
CLASS(meshVol2DCartTria), INTENT(out):: self
|
CLASS(meshVol2DCartTria), INTENT(out):: self
|
||||||
INTEGER, INTENT(in):: n
|
INTEGER, INTENT(in):: n
|
||||||
INTEGER, INTENT(in):: p(:)
|
INTEGER, INTENT(in):: p(:)
|
||||||
|
TYPE(meshNodeCont), INTENT(in), TARGET:: nodes(:)
|
||||||
REAL(8), DIMENSION(1:3):: r1, r2, r3
|
REAL(8), DIMENSION(1:3):: r1, r2, r3
|
||||||
REAL(8):: A
|
|
||||||
|
|
||||||
!Assign node index
|
!Assign node index
|
||||||
self%n = n
|
self%n = n
|
||||||
|
|
||||||
!Assign nodes to element
|
!Assign nodes to element
|
||||||
self%n1 => mesh%nodes(p(1))%obj
|
self%n1 => nodes(p(1))%obj
|
||||||
self%n2 => mesh%nodes(p(2))%obj
|
self%n2 => nodes(p(2))%obj
|
||||||
self%n3 => mesh%nodes(p(3))%obj
|
self%n3 => nodes(p(3))%obj
|
||||||
!Get element coordinates
|
!Get element coordinates
|
||||||
r1 = self%n1%getCoordinates()
|
r1 = self%n1%getCoordinates()
|
||||||
r2 = self%n2%getCoordinates()
|
r2 = self%n2%getCoordinates()
|
||||||
|
|
@ -777,17 +779,18 @@ MODULE moduleMesh2DCart
|
||||||
END SUBROUTINE partialDerTria
|
END SUBROUTINE partialDerTria
|
||||||
|
|
||||||
!Computes element local stiffness matrix
|
!Computes element local stiffness matrix
|
||||||
PURE FUNCTION elemKTria(self) RESULT(ke)
|
PURE FUNCTION elemKTria(self) RESULT(localK)
|
||||||
IMPLICIT NONE
|
IMPLICIT NONE
|
||||||
|
|
||||||
CLASS(meshVol2DCartTria), INTENT(in):: self
|
CLASS(meshVol2DCartTria), INTENT(in):: self
|
||||||
|
REAL(8), ALLOCATABLE:: localK(:,:)
|
||||||
REAL(8):: xi(1:3)
|
REAL(8):: xi(1:3)
|
||||||
REAL(8):: fPsi(1:3), dPsi(1:2,1:3)
|
REAL(8):: fPsi(1:3), dPsi(1:2,1:3)
|
||||||
REAL(8):: ke(1:3,1:3)
|
|
||||||
REAL(8):: invJ(1:2,1:2), detJ
|
REAL(8):: invJ(1:2,1:2), detJ
|
||||||
INTEGER:: l
|
INTEGER:: l
|
||||||
|
|
||||||
ke=0.D0
|
ALLOCATE(localK(1:4, 1:4))
|
||||||
|
localK=0.D0
|
||||||
xi=0.D0
|
xi=0.D0
|
||||||
!Start 2D Gauss Quad Integral
|
!Start 2D Gauss Quad Integral
|
||||||
DO l=1, 4
|
DO l=1, 4
|
||||||
|
|
@ -797,7 +800,7 @@ MODULE moduleMesh2DCart
|
||||||
detJ = self%detJac(xi,dPsi)
|
detJ = self%detJac(xi,dPsi)
|
||||||
invJ = self%invJac(xi,dPsi)
|
invJ = self%invJac(xi,dPsi)
|
||||||
fPsi = self%fPsi(xi)
|
fPsi = self%fPsi(xi)
|
||||||
ke = ke + MATMUL(TRANSPOSE(MATMUL(invJ,dPsi)),MATMUL(invJ,dPsi))*wTria(l)/detJ
|
localK = localK + MATMUL(TRANSPOSE(MATMUL(invJ,dPsi)),MATMUL(invJ,dPsi))*wTria(l)/detJ
|
||||||
|
|
||||||
END DO
|
END DO
|
||||||
|
|
||||||
|
|
@ -869,17 +872,17 @@ MODULE moduleMesh2DCart
|
||||||
w_p = self%weight(part%xi)
|
w_p = self%weight(part%xi)
|
||||||
tensorS = outerProduct(part%v, part%v)
|
tensorS = outerProduct(part%v, part%v)
|
||||||
|
|
||||||
vertex => self%n1%output(part%sp)
|
vertex => self%n1%output(part%species%n)
|
||||||
vertex%den = vertex%den + part%weight*w_p(1)
|
vertex%den = vertex%den + part%weight*w_p(1)
|
||||||
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(1)*part%v(:)
|
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(1)*part%v(:)
|
||||||
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(1)*tensorS
|
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(1)*tensorS
|
||||||
|
|
||||||
vertex => self%n2%output(part%sp)
|
vertex => self%n2%output(part%species%n)
|
||||||
vertex%den = vertex%den + part%weight*w_p(2)
|
vertex%den = vertex%den + part%weight*w_p(2)
|
||||||
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(2)*part%v(:)
|
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(2)*part%v(:)
|
||||||
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(2)*tensorS
|
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(2)*tensorS
|
||||||
|
|
||||||
vertex => self%n3%output(part%sp)
|
vertex => self%n3%output(part%species%n)
|
||||||
vertex%den = vertex%den + part%weight*w_p(3)
|
vertex%den = vertex%den + part%weight*w_p(3)
|
||||||
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(3)*part%v(:)
|
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(3)*part%v(:)
|
||||||
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(3)*tensorS
|
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(3)*tensorS
|
||||||
|
|
@ -950,7 +953,7 @@ MODULE moduleMesh2DCart
|
||||||
|
|
||||||
CLASS(meshVol2DCartTria), INTENT(in):: self
|
CLASS(meshVol2DCartTria), INTENT(in):: self
|
||||||
REAL(8), INTENT(in):: xi(1:3)
|
REAL(8), INTENT(in):: xi(1:3)
|
||||||
CLASS(*), POINTER, INTENT(out):: nextElement
|
CLASS(meshElement), POINTER, INTENT(out):: nextElement
|
||||||
REAL(8):: xiArray(1:3)
|
REAL(8):: xiArray(1:3)
|
||||||
INTEGER:: nextInt
|
INTEGER:: nextInt
|
||||||
|
|
||||||
|
|
@ -1018,4 +1021,453 @@ MODULE moduleMesh2DCart
|
||||||
|
|
||||||
END FUNCTION invJ2DCart
|
END FUNCTION invJ2DCart
|
||||||
|
|
||||||
|
SUBROUTINE connectMesh2DCart(self)
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
CLASS(meshGeneric), INTENT(inout):: self
|
||||||
|
INTEGER:: e, et
|
||||||
|
|
||||||
|
DO e = 1, self%numVols
|
||||||
|
!Connect Vol-Vol
|
||||||
|
DO et = 1, self%numVols
|
||||||
|
IF (e /= et) THEN
|
||||||
|
CALL connectVolVol(self%vols(e)%obj, self%vols(et)%obj)
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END DO
|
||||||
|
|
||||||
|
SELECT TYPE(self)
|
||||||
|
TYPE IS(meshParticles)
|
||||||
|
!Connect Vol-Edge
|
||||||
|
DO et = 1, self%numEdges
|
||||||
|
CALL connectVolEdge(self%vols(e)%obj, self%edges(et)%obj)
|
||||||
|
|
||||||
|
END DO
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
END DO
|
||||||
|
|
||||||
|
END SUBROUTINE connectMesh2DCart
|
||||||
|
|
||||||
|
!Selects type of elements to build connection
|
||||||
|
SUBROUTINE connectVolVol(elemA, elemB)
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
CLASS(meshVol), INTENT(inout):: elemA
|
||||||
|
CLASS(meshVol), INTENT(inout):: elemB
|
||||||
|
|
||||||
|
SELECT TYPE(elemA)
|
||||||
|
TYPE IS(meshVol2DCartQuad)
|
||||||
|
!Element A is a quadrilateral
|
||||||
|
SELECT TYPE(elemB)
|
||||||
|
TYPE IS(meshVol2DCartQuad)
|
||||||
|
!Element B is a quadrilateral
|
||||||
|
CALL connectQuadQuad(elemA, elemB)
|
||||||
|
|
||||||
|
TYPE IS(meshVol2DCartTria)
|
||||||
|
!Element B is a triangle
|
||||||
|
CALL connectQuadTria(elemA, elemB)
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
TYPE IS(meshVol2DCartTria)
|
||||||
|
!Element A is a Triangle
|
||||||
|
SELECT TYPE(elemB)
|
||||||
|
TYPE IS(meshVol2DCartQuad)
|
||||||
|
!Element B is a quadrilateral
|
||||||
|
CALL connectQuadTria(elemB, elemA)
|
||||||
|
|
||||||
|
TYPE IS(meshVol2DCartTria)
|
||||||
|
!Element B is a triangle
|
||||||
|
CALL connectTriaTria(elemA, elemB)
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
END SUBROUTINE connectVolVol
|
||||||
|
|
||||||
|
SUBROUTINE connectVolEdge(elemA, elemB)
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
CLASS(meshVol), INTENT(inout):: elemA
|
||||||
|
CLASS(meshEdge), INTENT(inout):: elemB
|
||||||
|
|
||||||
|
SELECT TYPE(elemB)
|
||||||
|
CLASS IS(meshEdge2DCart)
|
||||||
|
SELECT TYPE(elemA)
|
||||||
|
TYPE IS(meshVol2DCartQuad)
|
||||||
|
!Element A is a quadrilateral
|
||||||
|
CALL connectQuadEdge(elemA, elemB)
|
||||||
|
|
||||||
|
TYPE IS(meshVol2DCartTria)
|
||||||
|
!Element A is a triangle
|
||||||
|
CALL connectTriaEdge(elemA, elemB)
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
END SUBROUTINE connectVolEdge
|
||||||
|
|
||||||
|
SUBROUTINE connectQuadQuad(elemA, elemB)
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
CLASS(meshVol2DCartQuad), INTENT(inout), TARGET:: elemA
|
||||||
|
CLASS(meshVol2DCartQuad), INTENT(inout), TARGET:: elemB
|
||||||
|
|
||||||
|
!Check direction 1
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e1) .AND. &
|
||||||
|
elemA%n1%n == elemB%n4%n .AND. &
|
||||||
|
elemA%n2%n == elemB%n3%n) THEN
|
||||||
|
elemA%e1 => elemB
|
||||||
|
elemB%e3 => elemA
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
!Check direction 2
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e2) .AND. &
|
||||||
|
elemA%n2%n == elemB%n1%n .AND. &
|
||||||
|
elemA%n3%n == elemB%n4%n) THEN
|
||||||
|
elemA%e2 => elemB
|
||||||
|
elemB%e4 => elemA
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
!Check direction 3
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e3) .AND. &
|
||||||
|
elemA%n3%n == elemB%n2%n .AND. &
|
||||||
|
elemA%n4%n == elemB%n1%n) THEN
|
||||||
|
elemA%e3 => elemB
|
||||||
|
elemB%e1 => elemA
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
!Check direction 4
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e4) .AND. &
|
||||||
|
elemA%n4%n == elemB%n3%n .AND. &
|
||||||
|
elemA%n1%n == elemB%n2%n) THEN
|
||||||
|
elemA%e4 => elemB
|
||||||
|
elemB%e2 => elemA
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END SUBROUTINE connectQuadQuad
|
||||||
|
|
||||||
|
SUBROUTINE connectQuadTria(elemA, elemB)
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
CLASS(meshVol2DCartQuad), INTENT(inout), TARGET:: elemA
|
||||||
|
CLASS(meshVol2DCartTria), INTENT(inout), TARGET:: elemB
|
||||||
|
|
||||||
|
!Check direction 1
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e1)) THEN
|
||||||
|
IF (elemA%n1%n == elemB%n1%n .AND. &
|
||||||
|
elemA%n2%n == elemB%n3%n) THEN
|
||||||
|
elemA%e1 => elemB
|
||||||
|
elemB%e3 => elemA
|
||||||
|
|
||||||
|
ELSEIF (elemA%n1%n == elemB%n3%n .AND. &
|
||||||
|
elemA%n2%n == elemB%n2%n) THEN
|
||||||
|
elemA%e1 => elemB
|
||||||
|
elemB%e2 => elemA
|
||||||
|
|
||||||
|
ELSEIF (elemA%n1%n == elemB%n2%n .AND. &
|
||||||
|
elemA%n2%n == elemB%n1%n) THEN
|
||||||
|
elemA%e1 => elemB
|
||||||
|
elemB%e1 => elemA
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
!Check direction 2
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e2)) THEN
|
||||||
|
IF (elemA%n2%n == elemB%n1%n .AND. &
|
||||||
|
elemA%n3%n == elemB%n3%n) THEN
|
||||||
|
elemA%e2 => elemB
|
||||||
|
elemB%e3 => elemA
|
||||||
|
|
||||||
|
ELSEIF (elemA%n2%n == elemB%n3%n .AND. &
|
||||||
|
elemA%n3%n == elemB%n2%n) THEN
|
||||||
|
elemA%e2 => elemB
|
||||||
|
elemB%e2 => elemA
|
||||||
|
|
||||||
|
ELSEIF (elemA%n2%n == elemB%n2%n .AND. &
|
||||||
|
elemA%n3%n == elemB%n1%n) THEN
|
||||||
|
elemA%e2 => elemB
|
||||||
|
elemB%e1 => elemA
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
!Check direction 3
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e3)) THEN
|
||||||
|
IF (elemA%n3%n == elemB%n1%n .AND. &
|
||||||
|
elemA%n4%n == elemB%n3%n) THEN
|
||||||
|
elemA%e3 => elemB
|
||||||
|
elemB%e3 => elemA
|
||||||
|
|
||||||
|
ELSEIF (elemA%n3%n == elemB%n3%n .AND. &
|
||||||
|
elemA%n4%n == elemB%n2%n) THEN
|
||||||
|
elemA%e3 => elemB
|
||||||
|
elemB%e2 => elemA
|
||||||
|
|
||||||
|
ELSEIF (elemA%n3%n == elemB%n2%n .AND. &
|
||||||
|
elemA%n4%n == elemB%n1%n) THEN
|
||||||
|
elemA%e3 => elemB
|
||||||
|
elemB%e1 => elemA
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
!Check direction 4
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e4)) THEN
|
||||||
|
IF (elemA%n4%n == elemB%n1%n .AND. &
|
||||||
|
elemA%n1%n == elemB%n3%n) THEN
|
||||||
|
elemA%e4 => elemB
|
||||||
|
elemB%e3 => elemA
|
||||||
|
|
||||||
|
ELSEIF (elemA%n4%n == elemB%n3%n .AND. &
|
||||||
|
elemA%n1%n == elemB%n2%n) THEN
|
||||||
|
elemA%e4 => elemB
|
||||||
|
elemB%e2 => elemA
|
||||||
|
|
||||||
|
ELSEIF (elemA%n4%n == elemB%n2%n .AND. &
|
||||||
|
elemA%n1%n == elemB%n1%n) THEN
|
||||||
|
elemA%e4 => elemB
|
||||||
|
elemB%e1 => elemA
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END SUBROUTINE connectQuadTria
|
||||||
|
|
||||||
|
SUBROUTINE connectTriaTria(elemA, elemB)
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
CLASS(meshVol2DCartTria), INTENT(inout), TARGET:: elemA
|
||||||
|
CLASS(meshVol2DCartTria), INTENT(inout), TARGET:: elemB
|
||||||
|
|
||||||
|
!Check direction 1
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e1)) THEN
|
||||||
|
IF (elemA%n1%n == elemB%n1%n .AND. &
|
||||||
|
elemA%n2%n == elemB%n3%n) THEN
|
||||||
|
elemA%e1 => elemB
|
||||||
|
elemB%e3 => elemA
|
||||||
|
|
||||||
|
ELSEIF (elemA%n1%n == elemB%n2%n .AND. &
|
||||||
|
elemA%n2%n == elemB%n1%n) THEN
|
||||||
|
elemA%e1 => elemB
|
||||||
|
elemB%e1 => elemA
|
||||||
|
|
||||||
|
ELSEIF (elemA%n1%n == elemB%n3%n .AND. &
|
||||||
|
elemA%n2%n == elemB%n2%n) THEN
|
||||||
|
elemA%e1 => elemB
|
||||||
|
elemB%e2 => elemA
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
!Check direction 2
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e2)) THEN
|
||||||
|
IF (elemA%n2%n == elemB%n1%n .AND. &
|
||||||
|
elemA%n3%n == elemB%n3%n) THEN
|
||||||
|
elemA%e2 => elemB
|
||||||
|
elemB%e3 => elemA
|
||||||
|
|
||||||
|
ELSEIF (elemA%n2%n == elemB%n2%n .AND. &
|
||||||
|
elemA%n3%n == elemB%n1%n) THEN
|
||||||
|
elemA%e2 => elemB
|
||||||
|
elemB%e1 => elemA
|
||||||
|
|
||||||
|
ELSEIF (elemA%n2%n == elemB%n3%n .AND. &
|
||||||
|
elemA%n3%n == elemB%n2%n) THEN
|
||||||
|
elemA%e2 => elemB
|
||||||
|
elemB%e2 => elemA
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
!Check direction 3
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e3)) THEN
|
||||||
|
IF (elemA%n3%n == elemB%n1%n .AND. &
|
||||||
|
elemA%n1%n == elemB%n3%n) THEN
|
||||||
|
elemA%e3 => elemB
|
||||||
|
elemB%e3 => elemA
|
||||||
|
|
||||||
|
ELSEIF (elemA%n3%n == elemB%n2%n .AND. &
|
||||||
|
elemA%n1%n == elemB%n1%n) THEN
|
||||||
|
elemA%e3 => elemB
|
||||||
|
elemB%e1 => elemA
|
||||||
|
|
||||||
|
ELSEIF (elemA%n3%n == elemB%n3%n .AND. &
|
||||||
|
elemA%n1%n == elemB%n2%n) THEN
|
||||||
|
elemA%e3 => elemB
|
||||||
|
elemB%e2 => elemA
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END SUBROUTINE connectTriaTria
|
||||||
|
|
||||||
|
SUBROUTINE connectQuadEdge(elemA, elemB)
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
CLASS(meshVol2DCartQuad), INTENT(inout), TARGET:: elemA
|
||||||
|
CLASS(meshEdge2DCart), INTENT(inout), TARGET:: elemB
|
||||||
|
|
||||||
|
!Check direction 1
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e1)) THEN
|
||||||
|
IF (elemA%n1%n == elemB%n1%n .AND. &
|
||||||
|
elemA%n2%n == elemB%n2%n) THEN
|
||||||
|
elemA%e1 => elemB
|
||||||
|
elemB%e1 => elemA
|
||||||
|
|
||||||
|
ELSEIF (elemA%n1%n == elemB%n2%n .AND. &
|
||||||
|
elemA%n2%n == elemB%n1%n) THEN
|
||||||
|
elemA%e1 => elemB
|
||||||
|
elemB%e2 => elemA
|
||||||
|
|
||||||
|
!Revers the normal to point inside the domain
|
||||||
|
elemB%normal = - elemB%normal
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
!Check direction 2
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e2)) THEN
|
||||||
|
IF (elemA%n2%n == elemB%n1%n .AND. &
|
||||||
|
elemA%n3%n == elemB%n2%n) THEN
|
||||||
|
elemA%e2 => elemB
|
||||||
|
elemB%e1 => elemA
|
||||||
|
|
||||||
|
ELSEIF (elemA%n2%n == elemB%n2%n .AND. &
|
||||||
|
elemA%n3%n == elemB%n1%n) THEN
|
||||||
|
elemA%e2 => elemB
|
||||||
|
elemB%e2 => elemA
|
||||||
|
|
||||||
|
!Revers the normal to point inside the domain
|
||||||
|
elemB%normal = - elemB%normal
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
!Check direction 3
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e3)) THEN
|
||||||
|
IF (elemA%n3%n == elemB%n1%n .AND. &
|
||||||
|
elemA%n4%n == elemB%n2%n) THEN
|
||||||
|
elemA%e3 => elemB
|
||||||
|
elemB%e1 => elemA
|
||||||
|
|
||||||
|
ELSEIF (elemA%n3%n == elemB%n2%n .AND. &
|
||||||
|
elemA%n4%n == elemB%n1%n) THEN
|
||||||
|
elemA%e3 => elemB
|
||||||
|
elemB%e2 => elemA
|
||||||
|
|
||||||
|
!Revers the normal to point inside the domain
|
||||||
|
elemB%normal = - elemB%normal
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
!Check direction 4
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e4)) THEN
|
||||||
|
IF (elemA%n4%n == elemB%n1%n .AND. &
|
||||||
|
elemA%n1%n == elemB%n2%n) THEN
|
||||||
|
elemA%e4 => elemB
|
||||||
|
elemB%e1 => elemA
|
||||||
|
|
||||||
|
ELSEIF (elemA%n4%n == elemB%n2%n .AND. &
|
||||||
|
elemA%n1%n == elemB%n1%n) THEN
|
||||||
|
elemA%e4 => elemB
|
||||||
|
elemB%e2 => elemA
|
||||||
|
|
||||||
|
!Revers the normal to point inside the domain
|
||||||
|
elemB%normal = - elemB%normal
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END SUBROUTINE connectQuadEdge
|
||||||
|
|
||||||
|
SUBROUTINE connectTriaEdge(elemA, elemB)
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
CLASS(meshVol2DCartTria), INTENT(inout), TARGET:: elemA
|
||||||
|
CLASS(meshEdge2DCart), INTENT(inout), TARGET:: elemB
|
||||||
|
|
||||||
|
!Check direction 1
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e1)) THEN
|
||||||
|
IF (elemA%n1%n == elemB%n1%n .AND. &
|
||||||
|
elemA%n2%n == elemB%n2%n) THEN
|
||||||
|
elemA%e1 => elemB
|
||||||
|
elemB%e1 => elemA
|
||||||
|
|
||||||
|
ELSEIF (elemA%n1%n == elemB%n2%n .AND. &
|
||||||
|
elemA%n2%n == elemB%n1%n) THEN
|
||||||
|
elemA%e1 => elemB
|
||||||
|
elemB%e2 => elemA
|
||||||
|
|
||||||
|
!Revers the normal to point inside the domain
|
||||||
|
elemB%normal = - elemB%normal
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
!Check direction 2
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e2)) THEN
|
||||||
|
IF (elemA%n2%n == elemB%n1%n .AND. &
|
||||||
|
elemA%n3%n == elemB%n2%n) THEN
|
||||||
|
elemA%e2 => elemB
|
||||||
|
elemB%e1 => elemA
|
||||||
|
|
||||||
|
ELSEIF (elemA%n2%n == elemB%n2%n .AND. &
|
||||||
|
elemA%n3%n == elemB%n1%n) THEN
|
||||||
|
elemA%e2 => elemB
|
||||||
|
elemB%e2 => elemA
|
||||||
|
|
||||||
|
!Revers the normal to point inside the domain
|
||||||
|
elemB%normal = - elemB%normal
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
!Check direction 3
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e3)) THEN
|
||||||
|
IF (elemA%n3%n == elemB%n1%n .AND. &
|
||||||
|
elemA%n1%n == elemB%n2%n) THEN
|
||||||
|
elemA%e3 => elemB
|
||||||
|
elemB%e1 => elemA
|
||||||
|
|
||||||
|
ELSEIF (elemA%n3%n == elemB%n2%n .AND. &
|
||||||
|
elemA%n1%n == elemB%n1%n) THEN
|
||||||
|
elemA%e3 => elemB
|
||||||
|
elemB%e2 => elemA
|
||||||
|
|
||||||
|
!Revers the normal to point inside the domain
|
||||||
|
elemB%normal = - elemB%normal
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END SUBROUTINE connectTriaEdge
|
||||||
|
|
||||||
END MODULE moduleMesh2DCart
|
END MODULE moduleMesh2DCart
|
||||||
|
|
|
||||||
|
|
@ -1,620 +0,0 @@
|
||||||
MODULE moduleMesh2DCartRead
|
|
||||||
USE moduleMesh
|
|
||||||
USE moduleMesh2DCart
|
|
||||||
|
|
||||||
TYPE, EXTENDS(meshGeneric):: mesh2DCartGeneric
|
|
||||||
CONTAINS
|
|
||||||
PROCEDURE, PASS:: init => init2DCartMesh
|
|
||||||
PROCEDURE, PASS:: readMesh => readMesh2DCartGmsh
|
|
||||||
|
|
||||||
END TYPE
|
|
||||||
|
|
||||||
INTERFACE connected
|
|
||||||
MODULE PROCEDURE connectedVolVol, connectedVolEdge
|
|
||||||
|
|
||||||
END INTERFACE connected
|
|
||||||
|
|
||||||
CONTAINS
|
|
||||||
!Init mesh
|
|
||||||
SUBROUTINE init2DCartMesh(self, meshFormat)
|
|
||||||
USE moduleMesh
|
|
||||||
USE moduleErrors
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
CLASS(mesh2DCartGeneric), INTENT(out):: self
|
|
||||||
CHARACTER(:), ALLOCATABLE, INTENT(in):: meshFormat
|
|
||||||
|
|
||||||
SELECT CASE(meshFormat)
|
|
||||||
CASE ("gmsh")
|
|
||||||
self%printOutput => printOutputGmsh
|
|
||||||
self%printColl => printCollGmsh
|
|
||||||
self%printEM => printEMGmsh
|
|
||||||
|
|
||||||
CASE DEFAULT
|
|
||||||
CALL criticalError("Mesh type " // meshFormat // " not supported.", "init2DCartMesh")
|
|
||||||
|
|
||||||
END SELECT
|
|
||||||
|
|
||||||
END SUBROUTINE init2DCartMesh
|
|
||||||
|
|
||||||
!Read mesh from gmsh file
|
|
||||||
SUBROUTINE readMesh2DCartGmsh(self, filename)
|
|
||||||
USE moduleBoundary
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
CLASS(mesh2DCartGeneric), INTENT(inout):: self
|
|
||||||
CHARACTER(:), ALLOCATABLE, INTENT(in):: filename
|
|
||||||
REAL(8):: x, y
|
|
||||||
INTEGER:: p(1:4)
|
|
||||||
INTEGER:: e=0, et=0, n=0, eTemp=0, elemType=0, bt = 0
|
|
||||||
INTEGER:: totalNumElem
|
|
||||||
INTEGER:: boundaryType
|
|
||||||
|
|
||||||
!Read msh
|
|
||||||
OPEN(10, FILE=TRIM(filename))
|
|
||||||
!Skip header
|
|
||||||
READ(10, *)
|
|
||||||
READ(10, *)
|
|
||||||
READ(10, *)
|
|
||||||
READ(10, *)
|
|
||||||
!Read number of nodes
|
|
||||||
READ(10, *) self%numNodes
|
|
||||||
!Allocate required matrices and vectors
|
|
||||||
ALLOCATE(self%nodes(1:self%numNodes))
|
|
||||||
ALLOCATE(self%K(1:self%numNodes,1:self%numNodes))
|
|
||||||
ALLOCATE(self%IPIV(1:self%numNodes,1:self%numNodes))
|
|
||||||
self%K = 0.D0
|
|
||||||
self%IPIV = 0
|
|
||||||
!Read node cartesian coordinates (x=x, y=y, z=null)
|
|
||||||
DO e=1, self%numNodes
|
|
||||||
READ(10, *) n, x, y
|
|
||||||
ALLOCATE(meshNode2DCart:: self%nodes(n)%obj)
|
|
||||||
CALL self%nodes(n)%obj%init(n, (/x, y, 0.D0 /))
|
|
||||||
|
|
||||||
END DO
|
|
||||||
!Skips comments
|
|
||||||
READ(10, *)
|
|
||||||
READ(10, *)
|
|
||||||
!Reads Totalnumber of elements
|
|
||||||
READ(10, *) TotalnumElem
|
|
||||||
!counts edges and volume elements
|
|
||||||
self%numEdges = 0
|
|
||||||
DO e=1, TotalnumElem
|
|
||||||
READ(10,*) eTemp, elemType
|
|
||||||
IF (elemType==1) THEN
|
|
||||||
self%numEdges=e
|
|
||||||
END IF
|
|
||||||
END DO
|
|
||||||
!Substract the number of edges to the total number of elements
|
|
||||||
!to obtain the number of volume elements
|
|
||||||
self%numVols = TotalnumElem - self%numEdges
|
|
||||||
!Allocates arrays
|
|
||||||
ALLOCATE(self%edges(1:self%numEdges))
|
|
||||||
ALLOCATE(self%vols(1:self%numVols))
|
|
||||||
|
|
||||||
!Go back to the beggining to read elements
|
|
||||||
DO e=1, totalNumElem
|
|
||||||
BACKSPACE(10)
|
|
||||||
END DO
|
|
||||||
|
|
||||||
!Reads edges
|
|
||||||
DO e=1, self%numEdges
|
|
||||||
READ(10,*) n, elemType, eTemp, boundaryType, eTemp, p(1:2)
|
|
||||||
!Associate boundary condition procedure.
|
|
||||||
bt = getBoundaryId(boundaryType)
|
|
||||||
|
|
||||||
ALLOCATE(meshEdge2DCart:: self%edges(e)%obj)
|
|
||||||
|
|
||||||
CALL self%edges(e)%obj%init(n, p(1:2), bt, boundaryType)
|
|
||||||
|
|
||||||
END DO
|
|
||||||
|
|
||||||
!Read and initialize volumes
|
|
||||||
DO e=1, self%numVols
|
|
||||||
READ(10,*) n, elemType
|
|
||||||
BACKSPACE(10)
|
|
||||||
|
|
||||||
SELECT CASE(elemType)
|
|
||||||
CASE (2)
|
|
||||||
!Triangular element
|
|
||||||
READ(10,*) n, elemType, eTemp, eTemp, eTemp, p(1:3)
|
|
||||||
ALLOCATE(meshVol2DCartTria:: self%vols(e)%obj)
|
|
||||||
CALL self%vols(e)%obj%init(n - self%numEdges, p(1:3))
|
|
||||||
|
|
||||||
CASE (3)
|
|
||||||
!Quadrilateral element
|
|
||||||
READ(10,*) n, elemType, eTemp, eTemp, eTemp, p(1:4)
|
|
||||||
ALLOCATE(meshVol2DCartQuad:: self%vols(e)%obj)
|
|
||||||
CALL self%vols(e)%obj%init(n - self%numEdges, p(1:4))
|
|
||||||
|
|
||||||
END SELECT
|
|
||||||
|
|
||||||
END DO
|
|
||||||
|
|
||||||
CLOSE(10)
|
|
||||||
|
|
||||||
!Build connectivity between elements
|
|
||||||
DO e = 1, self%numVols
|
|
||||||
!Connectivity between volumes
|
|
||||||
DO et = 1, self%numVols
|
|
||||||
IF (e /= et) THEN
|
|
||||||
CALL connected(self%vols(e)%obj, self%vols(et)%obj)
|
|
||||||
|
|
||||||
END IF
|
|
||||||
END DO
|
|
||||||
|
|
||||||
!Connectivity between vols and edges
|
|
||||||
DO et = 1, self%numEdges
|
|
||||||
CALL connected(self%vols(e)%obj, self%edges(et)%obj)
|
|
||||||
|
|
||||||
END DO
|
|
||||||
|
|
||||||
!Constructs the global K matrix
|
|
||||||
CALL constructGlobalK(self%K, self%vols(e)%obj)
|
|
||||||
|
|
||||||
END DO
|
|
||||||
|
|
||||||
END SUBROUTINE readMesh2DCartGmsh
|
|
||||||
|
|
||||||
!Selects type of elements to build connection
|
|
||||||
SUBROUTINE connectedVolVol(elemA, elemB)
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
CLASS(meshVol), INTENT(inout):: elemA
|
|
||||||
CLASS(meshVol), INTENT(inout):: elemB
|
|
||||||
|
|
||||||
SELECT TYPE(elemA)
|
|
||||||
TYPE IS(meshVol2DCartQuad)
|
|
||||||
!Element A is a quadrilateral
|
|
||||||
SELECT TYPE(elemB)
|
|
||||||
TYPE IS(meshVol2DCartQuad)
|
|
||||||
!Element B is a quadrilateral
|
|
||||||
CALL connectedQuadQuad(elemA, elemB)
|
|
||||||
|
|
||||||
TYPE IS(meshVol2DCartTria)
|
|
||||||
!Element B is a triangle
|
|
||||||
CALL connectedQuadTria(elemA, elemB)
|
|
||||||
|
|
||||||
END SELECT
|
|
||||||
|
|
||||||
TYPE IS(meshVol2DCartTria)
|
|
||||||
!Element A is a Triangle
|
|
||||||
SELECT TYPE(elemB)
|
|
||||||
TYPE IS(meshVol2DCartQuad)
|
|
||||||
!Element B is a quadrilateral
|
|
||||||
CALL connectedQuadTria(elemB, elemA)
|
|
||||||
|
|
||||||
TYPE IS(meshVol2DCartTria)
|
|
||||||
!Element B is a triangle
|
|
||||||
CALL connectedTriaTria(elemA, elemB)
|
|
||||||
|
|
||||||
END SELECT
|
|
||||||
|
|
||||||
END SELECT
|
|
||||||
|
|
||||||
END SUBROUTINE connectedVolVol
|
|
||||||
|
|
||||||
SUBROUTINE connectedVolEdge(elemA, elemB)
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
CLASS(meshVol), INTENT(inout):: elemA
|
|
||||||
CLASS(meshEdge), INTENT(inout):: elemB
|
|
||||||
|
|
||||||
SELECT TYPE(elemB)
|
|
||||||
CLASS IS(meshEdge2DCart)
|
|
||||||
SELECT TYPE(elemA)
|
|
||||||
TYPE IS(meshVol2DCartQuad)
|
|
||||||
!Element A is a quadrilateral
|
|
||||||
CALL connectedQuadEdge(elemA, elemB)
|
|
||||||
|
|
||||||
TYPE IS(meshVol2DCartTria)
|
|
||||||
!Element A is a triangle
|
|
||||||
CALL connectedTriaEdge(elemA, elemB)
|
|
||||||
|
|
||||||
END SELECT
|
|
||||||
|
|
||||||
END SELECT
|
|
||||||
|
|
||||||
END SUBROUTINE connectedVolEdge
|
|
||||||
|
|
||||||
SUBROUTINE connectedQuadQuad(elemA, elemB)
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
CLASS(meshVol2DCartQuad), INTENT(inout), TARGET:: elemA
|
|
||||||
CLASS(meshVol2DCartQuad), INTENT(inout), TARGET:: elemB
|
|
||||||
|
|
||||||
!Check direction 1
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e1) .AND. &
|
|
||||||
elemA%n1%n == elemB%n4%n .AND. &
|
|
||||||
elemA%n2%n == elemB%n3%n) THEN
|
|
||||||
elemA%e1 => elemB
|
|
||||||
elemB%e3 => elemA
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
!Check direction 2
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e2) .AND. &
|
|
||||||
elemA%n2%n == elemB%n1%n .AND. &
|
|
||||||
elemA%n3%n == elemB%n4%n) THEN
|
|
||||||
elemA%e2 => elemB
|
|
||||||
elemB%e4 => elemA
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
!Check direction 3
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e3) .AND. &
|
|
||||||
elemA%n3%n == elemB%n2%n .AND. &
|
|
||||||
elemA%n4%n == elemB%n1%n) THEN
|
|
||||||
elemA%e3 => elemB
|
|
||||||
elemB%e1 => elemA
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
!Check direction 4
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e4) .AND. &
|
|
||||||
elemA%n4%n == elemB%n3%n .AND. &
|
|
||||||
elemA%n1%n == elemB%n2%n) THEN
|
|
||||||
elemA%e4 => elemB
|
|
||||||
elemB%e2 => elemA
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END SUBROUTINE connectedQuadQuad
|
|
||||||
|
|
||||||
SUBROUTINE connectedQuadTria(elemA, elemB)
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
CLASS(meshVol2DCartQuad), INTENT(inout), TARGET:: elemA
|
|
||||||
CLASS(meshVol2DCartTria), INTENT(inout), TARGET:: elemB
|
|
||||||
|
|
||||||
!Check direction 1
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e1)) THEN
|
|
||||||
IF (elemA%n1%n == elemB%n1%n .AND. &
|
|
||||||
elemA%n2%n == elemB%n3%n) THEN
|
|
||||||
elemA%e1 => elemB
|
|
||||||
elemB%e3 => elemA
|
|
||||||
|
|
||||||
ELSEIF (elemA%n1%n == elemB%n3%n .AND. &
|
|
||||||
elemA%n2%n == elemB%n2%n) THEN
|
|
||||||
elemA%e1 => elemB
|
|
||||||
elemB%e2 => elemA
|
|
||||||
|
|
||||||
ELSEIF (elemA%n1%n == elemB%n2%n .AND. &
|
|
||||||
elemA%n2%n == elemB%n1%n) THEN
|
|
||||||
elemA%e1 => elemB
|
|
||||||
elemB%e1 => elemA
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
!Check direction 2
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e2)) THEN
|
|
||||||
IF (elemA%n2%n == elemB%n1%n .AND. &
|
|
||||||
elemA%n3%n == elemB%n3%n) THEN
|
|
||||||
elemA%e2 => elemB
|
|
||||||
elemB%e3 => elemA
|
|
||||||
|
|
||||||
ELSEIF (elemA%n2%n == elemB%n3%n .AND. &
|
|
||||||
elemA%n3%n == elemB%n2%n) THEN
|
|
||||||
elemA%e2 => elemB
|
|
||||||
elemB%e2 => elemA
|
|
||||||
|
|
||||||
ELSEIF (elemA%n2%n == elemB%n2%n .AND. &
|
|
||||||
elemA%n3%n == elemB%n1%n) THEN
|
|
||||||
elemA%e2 => elemB
|
|
||||||
elemB%e1 => elemA
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
!Check direction 3
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e3)) THEN
|
|
||||||
IF (elemA%n3%n == elemB%n1%n .AND. &
|
|
||||||
elemA%n4%n == elemB%n3%n) THEN
|
|
||||||
elemA%e3 => elemB
|
|
||||||
elemB%e3 => elemA
|
|
||||||
|
|
||||||
ELSEIF (elemA%n3%n == elemB%n3%n .AND. &
|
|
||||||
elemA%n4%n == elemB%n2%n) THEN
|
|
||||||
elemA%e3 => elemB
|
|
||||||
elemB%e2 => elemA
|
|
||||||
|
|
||||||
ELSEIF (elemA%n3%n == elemB%n2%n .AND. &
|
|
||||||
elemA%n4%n == elemB%n1%n) THEN
|
|
||||||
elemA%e3 => elemB
|
|
||||||
elemB%e1 => elemA
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
!Check direction 4
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e4)) THEN
|
|
||||||
IF (elemA%n4%n == elemB%n1%n .AND. &
|
|
||||||
elemA%n1%n == elemB%n3%n) THEN
|
|
||||||
elemA%e4 => elemB
|
|
||||||
elemB%e3 => elemA
|
|
||||||
|
|
||||||
ELSEIF (elemA%n4%n == elemB%n3%n .AND. &
|
|
||||||
elemA%n1%n == elemB%n2%n) THEN
|
|
||||||
elemA%e4 => elemB
|
|
||||||
elemB%e2 => elemA
|
|
||||||
|
|
||||||
ELSEIF (elemA%n4%n == elemB%n2%n .AND. &
|
|
||||||
elemA%n1%n == elemB%n1%n) THEN
|
|
||||||
elemA%e4 => elemB
|
|
||||||
elemB%e1 => elemA
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END SUBROUTINE connectedQuadTria
|
|
||||||
|
|
||||||
SUBROUTINE connectedTriaTria(elemA, elemB)
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
CLASS(meshVol2DCartTria), INTENT(inout), TARGET:: elemA
|
|
||||||
CLASS(meshVol2DCartTria), INTENT(inout), TARGET:: elemB
|
|
||||||
|
|
||||||
!Check direction 1
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e1)) THEN
|
|
||||||
IF (elemA%n1%n == elemB%n1%n .AND. &
|
|
||||||
elemA%n2%n == elemB%n3%n) THEN
|
|
||||||
elemA%e1 => elemB
|
|
||||||
elemB%e3 => elemA
|
|
||||||
|
|
||||||
ELSEIF (elemA%n1%n == elemB%n2%n .AND. &
|
|
||||||
elemA%n2%n == elemB%n1%n) THEN
|
|
||||||
elemA%e1 => elemB
|
|
||||||
elemB%e1 => elemA
|
|
||||||
|
|
||||||
ELSEIF (elemA%n1%n == elemB%n3%n .AND. &
|
|
||||||
elemA%n2%n == elemB%n2%n) THEN
|
|
||||||
elemA%e1 => elemB
|
|
||||||
elemB%e2 => elemA
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
!Check direction 2
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e2)) THEN
|
|
||||||
IF (elemA%n2%n == elemB%n1%n .AND. &
|
|
||||||
elemA%n3%n == elemB%n3%n) THEN
|
|
||||||
elemA%e2 => elemB
|
|
||||||
elemB%e3 => elemA
|
|
||||||
|
|
||||||
ELSEIF (elemA%n2%n == elemB%n2%n .AND. &
|
|
||||||
elemA%n3%n == elemB%n1%n) THEN
|
|
||||||
elemA%e2 => elemB
|
|
||||||
elemB%e1 => elemA
|
|
||||||
|
|
||||||
ELSEIF (elemA%n2%n == elemB%n3%n .AND. &
|
|
||||||
elemA%n3%n == elemB%n2%n) THEN
|
|
||||||
elemA%e2 => elemB
|
|
||||||
elemB%e2 => elemA
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
!Check direction 3
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e3)) THEN
|
|
||||||
IF (elemA%n3%n == elemB%n1%n .AND. &
|
|
||||||
elemA%n1%n == elemB%n3%n) THEN
|
|
||||||
elemA%e3 => elemB
|
|
||||||
elemB%e3 => elemA
|
|
||||||
|
|
||||||
ELSEIF (elemA%n3%n == elemB%n2%n .AND. &
|
|
||||||
elemA%n1%n == elemB%n1%n) THEN
|
|
||||||
elemA%e3 => elemB
|
|
||||||
elemB%e1 => elemA
|
|
||||||
|
|
||||||
ELSEIF (elemA%n3%n == elemB%n3%n .AND. &
|
|
||||||
elemA%n1%n == elemB%n2%n) THEN
|
|
||||||
elemA%e3 => elemB
|
|
||||||
elemB%e2 => elemA
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END SUBROUTINE connectedTriaTria
|
|
||||||
|
|
||||||
SUBROUTINE connectedQuadEdge(elemA, elemB)
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
CLASS(meshVol2DCartQuad), INTENT(inout), TARGET:: elemA
|
|
||||||
CLASS(meshEdge2DCart), INTENT(inout), TARGET:: elemB
|
|
||||||
|
|
||||||
!Check direction 1
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e1)) THEN
|
|
||||||
IF (elemA%n1%n == elemB%n1%n .AND. &
|
|
||||||
elemA%n2%n == elemB%n2%n) THEN
|
|
||||||
elemA%e1 => elemB
|
|
||||||
elemB%e1 => elemA
|
|
||||||
|
|
||||||
ELSEIF (elemA%n1%n == elemB%n2%n .AND. &
|
|
||||||
elemA%n2%n == elemB%n1%n) THEN
|
|
||||||
elemA%e1 => elemB
|
|
||||||
elemB%e2 => elemA
|
|
||||||
|
|
||||||
!Revers the normal to point inside the domain
|
|
||||||
elemB%normal = - elemB%normal
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
!Check direction 2
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e2)) THEN
|
|
||||||
IF (elemA%n2%n == elemB%n1%n .AND. &
|
|
||||||
elemA%n3%n == elemB%n2%n) THEN
|
|
||||||
elemA%e2 => elemB
|
|
||||||
elemB%e1 => elemA
|
|
||||||
|
|
||||||
ELSEIF (elemA%n2%n == elemB%n2%n .AND. &
|
|
||||||
elemA%n3%n == elemB%n1%n) THEN
|
|
||||||
elemA%e2 => elemB
|
|
||||||
elemB%e2 => elemA
|
|
||||||
|
|
||||||
!Revers the normal to point inside the domain
|
|
||||||
elemB%normal = - elemB%normal
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
!Check direction 3
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e3)) THEN
|
|
||||||
IF (elemA%n3%n == elemB%n1%n .AND. &
|
|
||||||
elemA%n4%n == elemB%n2%n) THEN
|
|
||||||
elemA%e3 => elemB
|
|
||||||
elemB%e1 => elemA
|
|
||||||
|
|
||||||
ELSEIF (elemA%n3%n == elemB%n2%n .AND. &
|
|
||||||
elemA%n4%n == elemB%n1%n) THEN
|
|
||||||
elemA%e3 => elemB
|
|
||||||
elemB%e2 => elemA
|
|
||||||
|
|
||||||
!Revers the normal to point inside the domain
|
|
||||||
elemB%normal = - elemB%normal
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
!Check direction 4
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e4)) THEN
|
|
||||||
IF (elemA%n4%n == elemB%n1%n .AND. &
|
|
||||||
elemA%n1%n == elemB%n2%n) THEN
|
|
||||||
elemA%e4 => elemB
|
|
||||||
elemB%e1 => elemA
|
|
||||||
|
|
||||||
ELSEIF (elemA%n4%n == elemB%n2%n .AND. &
|
|
||||||
elemA%n1%n == elemB%n1%n) THEN
|
|
||||||
elemA%e4 => elemB
|
|
||||||
elemB%e2 => elemA
|
|
||||||
|
|
||||||
!Revers the normal to point inside the domain
|
|
||||||
elemB%normal = - elemB%normal
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END SUBROUTINE connectedQuadEdge
|
|
||||||
|
|
||||||
SUBROUTINE connectedTriaEdge(elemA, elemB)
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
CLASS(meshVol2DCartTria), INTENT(inout), TARGET:: elemA
|
|
||||||
CLASS(meshEdge2DCart), INTENT(inout), TARGET:: elemB
|
|
||||||
|
|
||||||
!Check direction 1
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e1)) THEN
|
|
||||||
IF (elemA%n1%n == elemB%n1%n .AND. &
|
|
||||||
elemA%n2%n == elemB%n2%n) THEN
|
|
||||||
elemA%e1 => elemB
|
|
||||||
elemB%e1 => elemA
|
|
||||||
|
|
||||||
ELSEIF (elemA%n1%n == elemB%n2%n .AND. &
|
|
||||||
elemA%n2%n == elemB%n1%n) THEN
|
|
||||||
elemA%e1 => elemB
|
|
||||||
elemB%e2 => elemA
|
|
||||||
|
|
||||||
!Revers the normal to point inside the domain
|
|
||||||
elemB%normal = - elemB%normal
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
!Check direction 2
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e2)) THEN
|
|
||||||
IF (elemA%n2%n == elemB%n1%n .AND. &
|
|
||||||
elemA%n3%n == elemB%n2%n) THEN
|
|
||||||
elemA%e2 => elemB
|
|
||||||
elemB%e1 => elemA
|
|
||||||
|
|
||||||
ELSEIF (elemA%n2%n == elemB%n2%n .AND. &
|
|
||||||
elemA%n3%n == elemB%n1%n) THEN
|
|
||||||
elemA%e2 => elemB
|
|
||||||
elemB%e2 => elemA
|
|
||||||
|
|
||||||
!Revers the normal to point inside the domain
|
|
||||||
elemB%normal = - elemB%normal
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
!Check direction 3
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e3)) THEN
|
|
||||||
IF (elemA%n3%n == elemB%n1%n .AND. &
|
|
||||||
elemA%n1%n == elemB%n2%n) THEN
|
|
||||||
elemA%e3 => elemB
|
|
||||||
elemB%e1 => elemA
|
|
||||||
|
|
||||||
ELSEIF (elemA%n3%n == elemB%n2%n .AND. &
|
|
||||||
elemA%n1%n == elemB%n1%n) THEN
|
|
||||||
elemA%e3 => elemB
|
|
||||||
elemB%e2 => elemA
|
|
||||||
|
|
||||||
!Revers the normal to point inside the domain
|
|
||||||
elemB%normal = - elemB%normal
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END SUBROUTINE connectedTriaEdge
|
|
||||||
|
|
||||||
SUBROUTINE constructGlobalK(K, elem)
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
REAL(8), INTENT(inout):: K(1:,1:)
|
|
||||||
CLASS(meshVol), INTENT(in):: elem
|
|
||||||
REAL(8), ALLOCATABLE:: localK(:,:)
|
|
||||||
INTEGER:: nNodes, i, j
|
|
||||||
INTEGER, ALLOCATABLE:: n(:)
|
|
||||||
|
|
||||||
SELECT TYPE(elem)
|
|
||||||
TYPE IS(meshVol2DCartQuad)
|
|
||||||
nNodes = 4
|
|
||||||
ALLOCATE(localK(1:nNodes,1:nNodes))
|
|
||||||
localK = elem%elemK()
|
|
||||||
ALLOCATE(n(1:nNodes))
|
|
||||||
n = (/ elem%n1%n, elem%n2%n, &
|
|
||||||
elem%n3%n, elem%n4%n /)
|
|
||||||
|
|
||||||
TYPE IS(meshVol2DCartTria)
|
|
||||||
nNodes = 3
|
|
||||||
ALLOCATE(localK(1:nNodes,1:nNodes))
|
|
||||||
localK = elem%elemK()
|
|
||||||
ALLOCATE(n(1:nNodes))
|
|
||||||
n = (/ elem%n1%n, elem%n2%n, elem%n3%n /)
|
|
||||||
|
|
||||||
CLASS DEFAULT
|
|
||||||
nNodes = 0
|
|
||||||
ALLOCATE(localK(1:1, 1:1))
|
|
||||||
localK = 0.D0
|
|
||||||
ALLOCATE(n(1:1))
|
|
||||||
n = 0
|
|
||||||
|
|
||||||
END SELECT
|
|
||||||
|
|
||||||
DO i = 1, nNodes
|
|
||||||
DO j = 1, nNodes
|
|
||||||
K(n(i), n(j)) = K(n(i), n(j)) + localK(i, j)
|
|
||||||
END DO
|
|
||||||
END DO
|
|
||||||
|
|
||||||
END SUBROUTINE constructGlobalK
|
|
||||||
|
|
||||||
END MODULE moduleMesh2DCartRead
|
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
all : moduleMesh2DCyl.o moduleMesh2DCylRead.o
|
all : moduleMesh2DCyl.o
|
||||||
|
|
||||||
moduleMesh2DCyl.o: moduleMesh2DCyl.f90
|
moduleMesh2DCyl.o: moduleMesh2DCyl.f90
|
||||||
$(FC) $(FCFLAGS) -c $(subst .o,.f90,$@) -o $(OBJDIR)/$@
|
$(FC) $(FCFLAGS) -c $(subst .o,.f90,$@) -o $(OBJDIR)/$@
|
||||||
|
|
||||||
moduleMesh2DCylRead.o: moduleMesh2DCyl.o moduleMesh2DCylRead.f90
|
|
||||||
$(FC) $(FCFLAGS) -c $(subst .o,.f90,$@) -o $(OBJDIR)/$@
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ MODULE moduleMesh2DCyl
|
||||||
!Connectivity to nodes
|
!Connectivity to nodes
|
||||||
CLASS(meshNode), POINTER:: n1 => NULL(), n2 => NULL(), n3 => NULL(), n4 => NULL()
|
CLASS(meshNode), POINTER:: n1 => NULL(), n2 => NULL(), n3 => NULL(), n4 => NULL()
|
||||||
!Connectivity to adjacent elements
|
!Connectivity to adjacent elements
|
||||||
CLASS(*), POINTER:: e1 => NULL(), e2 => NULL(), e3 => NULL(), e4 => NULL()
|
CLASS(meshElement), POINTER:: e1 => NULL(), e2 => NULL(), e3 => NULL(), e4 => NULL()
|
||||||
REAL(8):: arNodes(1:4) = 0.D0
|
REAL(8):: arNodes(1:4) = 0.D0
|
||||||
|
|
||||||
CONTAINS
|
CONTAINS
|
||||||
|
|
@ -108,7 +108,7 @@ MODULE moduleMesh2DCyl
|
||||||
!Connectivity to nodes
|
!Connectivity to nodes
|
||||||
CLASS(meshNode), POINTER:: n1 => NULL(), n2 => NULL(), n3 => NULL()
|
CLASS(meshNode), POINTER:: n1 => NULL(), n2 => NULL(), n3 => NULL()
|
||||||
!Connectivity to adjacent elements
|
!Connectivity to adjacent elements
|
||||||
CLASS(*), POINTER:: e1 => NULL(), e2 => NULL(), e3 => NULL()
|
CLASS(meshElement), POINTER:: e1 => NULL(), e2 => NULL(), e3 => NULL()
|
||||||
REAL(8):: arNodes(1:3) = 0.D0
|
REAL(8):: arNodes(1:3) = 0.D0
|
||||||
|
|
||||||
CONTAINS
|
CONTAINS
|
||||||
|
|
@ -271,20 +271,21 @@ MODULE moduleMesh2DCyl
|
||||||
!VOLUME FUNCTIONS
|
!VOLUME FUNCTIONS
|
||||||
!QUAD FUNCTIONS
|
!QUAD FUNCTIONS
|
||||||
!Inits quadrilateral element
|
!Inits quadrilateral element
|
||||||
SUBROUTINE initVolQuad2DCyl(self, n, p)
|
SUBROUTINE initVolQuad2DCyl(self, n, p, nodes)
|
||||||
USE moduleRefParam
|
USE moduleRefParam
|
||||||
IMPLICIT NONE
|
IMPLICIT NONE
|
||||||
|
|
||||||
CLASS(meshVol2DCylQuad), INTENT(out):: self
|
CLASS(meshVol2DCylQuad), INTENT(out):: self
|
||||||
INTEGER, INTENT(in):: n
|
INTEGER, INTENT(in):: n
|
||||||
INTEGER, INTENT(in):: p(:)
|
INTEGER, INTENT(in):: p(:)
|
||||||
|
TYPE(meshNodeCont), INTENT(in), TARGET:: nodes(:)
|
||||||
REAL(8), DIMENSION(1:3):: r1, r2, r3, r4
|
REAL(8), DIMENSION(1:3):: r1, r2, r3, r4
|
||||||
|
|
||||||
self%n = n
|
self%n = n
|
||||||
self%n1 => mesh%nodes(p(1))%obj
|
self%n1 => nodes(p(1))%obj
|
||||||
self%n2 => mesh%nodes(p(2))%obj
|
self%n2 => nodes(p(2))%obj
|
||||||
self%n3 => mesh%nodes(p(3))%obj
|
self%n3 => nodes(p(3))%obj
|
||||||
self%n4 => mesh%nodes(p(4))%obj
|
self%n4 => nodes(p(4))%obj
|
||||||
!Get element coordinates
|
!Get element coordinates
|
||||||
r1 = self%n1%getCoordinates()
|
r1 = self%n1%getCoordinates()
|
||||||
r2 = self%n2%getCoordinates()
|
r2 = self%n2%getCoordinates()
|
||||||
|
|
@ -427,18 +428,19 @@ MODULE moduleMesh2DCyl
|
||||||
END FUNCTION randposVolQuad
|
END FUNCTION randposVolQuad
|
||||||
|
|
||||||
!Computes element local stiffness matrix
|
!Computes element local stiffness matrix
|
||||||
PURE FUNCTION elemKQuad(self) RESULT(ke)
|
PURE FUNCTION elemKQuad(self) RESULT(localK)
|
||||||
USE moduleConstParam, ONLY: PI2
|
USE moduleConstParam, ONLY: PI2
|
||||||
IMPLICIT NONE
|
IMPLICIT NONE
|
||||||
|
|
||||||
CLASS(meshVol2DCylQuad), INTENT(in):: self
|
CLASS(meshVol2DCylQuad), INTENT(in):: self
|
||||||
|
REAL(8), ALLOCATABLE:: localK(:,:)
|
||||||
REAL(8):: r, xi(1:3)
|
REAL(8):: r, xi(1:3)
|
||||||
REAL(8):: fPsi(1:4), dPsi(1:2,1:4)
|
REAL(8):: fPsi(1:4), dPsi(1:2,1:4)
|
||||||
REAL(8):: ke(1:4,1:4)
|
|
||||||
REAL(8):: invJ(1:2,1:2), detJ
|
REAL(8):: invJ(1:2,1:2), detJ
|
||||||
INTEGER:: l, m
|
INTEGER:: l, m
|
||||||
|
|
||||||
ke=0.D0
|
ALLOCATE(localK(1:4, 1:4))
|
||||||
|
localK=0.D0
|
||||||
xi=0.D0
|
xi=0.D0
|
||||||
!Start 2D Gauss Quad Integral
|
!Start 2D Gauss Quad Integral
|
||||||
DO l=1, 3
|
DO l=1, 3
|
||||||
|
|
@ -451,13 +453,13 @@ MODULE moduleMesh2DCyl
|
||||||
detJ = self%detJac(xi,dPsi)
|
detJ = self%detJac(xi,dPsi)
|
||||||
invJ = self%invJac(xi,dPsi)
|
invJ = self%invJac(xi,dPsi)
|
||||||
r = DOT_PRODUCT(fPsi,self%r)
|
r = DOT_PRODUCT(fPsi,self%r)
|
||||||
ke = ke + MATMUL(TRANSPOSE(MATMUL(invJ,dPsi)), &
|
localK = localK + MATMUL(TRANSPOSE(MATMUL(invJ,dPsi)), &
|
||||||
MATMUL(invJ,dPsi))* &
|
MATMUL(invJ,dPsi))* &
|
||||||
r*wQuad(l)*wQuad(m)/detJ
|
r*wQuad(l)*wQuad(m)/detJ
|
||||||
|
|
||||||
END DO
|
END DO
|
||||||
END DO
|
END DO
|
||||||
ke = ke*PI2
|
localK = localK*PI2
|
||||||
|
|
||||||
END FUNCTION elemKQuad
|
END FUNCTION elemKQuad
|
||||||
|
|
||||||
|
|
@ -531,22 +533,22 @@ MODULE moduleMesh2DCyl
|
||||||
w_p = self%weight(part%xi)
|
w_p = self%weight(part%xi)
|
||||||
tensorS = outerProduct(part%v, part%v)
|
tensorS = outerProduct(part%v, part%v)
|
||||||
|
|
||||||
vertex => self%n1%output(part%sp)
|
vertex => self%n1%output(part%species%n)
|
||||||
vertex%den = vertex%den + part%weight*w_p(1)
|
vertex%den = vertex%den + part%weight*w_p(1)
|
||||||
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(1)*part%v(:)
|
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(1)*part%v(:)
|
||||||
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(1)*tensorS
|
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(1)*tensorS
|
||||||
|
|
||||||
vertex => self%n2%output(part%sp)
|
vertex => self%n2%output(part%species%n)
|
||||||
vertex%den = vertex%den + part%weight*w_p(2)
|
vertex%den = vertex%den + part%weight*w_p(2)
|
||||||
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(2)*part%v(:)
|
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(2)*part%v(:)
|
||||||
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(2)*tensorS
|
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(2)*tensorS
|
||||||
|
|
||||||
vertex => self%n3%output(part%sp)
|
vertex => self%n3%output(part%species%n)
|
||||||
vertex%den = vertex%den + part%weight*w_p(3)
|
vertex%den = vertex%den + part%weight*w_p(3)
|
||||||
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(3)*part%v(:)
|
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(3)*part%v(:)
|
||||||
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(3)*tensorS
|
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(3)*tensorS
|
||||||
|
|
||||||
vertex => self%n4%output(part%sp)
|
vertex => self%n4%output(part%species%n)
|
||||||
vertex%den = vertex%den + part%weight*w_p(4)
|
vertex%den = vertex%den + part%weight*w_p(4)
|
||||||
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(4)*part%v(:)
|
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(4)*part%v(:)
|
||||||
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(4)*tensorS
|
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(4)*tensorS
|
||||||
|
|
@ -628,7 +630,7 @@ MODULE moduleMesh2DCyl
|
||||||
|
|
||||||
CLASS(meshVol2DCylQuad), INTENT(in):: self
|
CLASS(meshVol2DCylQuad), INTENT(in):: self
|
||||||
REAL(8), INTENT(in):: xi(1:3)
|
REAL(8), INTENT(in):: xi(1:3)
|
||||||
CLASS(*), POINTER, INTENT(out):: nextElement
|
CLASS(meshElement), POINTER, INTENT(out):: nextElement
|
||||||
REAL(8):: xiArray(1:4)
|
REAL(8):: xiArray(1:4)
|
||||||
INTEGER:: nextInt
|
INTEGER:: nextInt
|
||||||
|
|
||||||
|
|
@ -651,22 +653,23 @@ MODULE moduleMesh2DCyl
|
||||||
|
|
||||||
!TRIA ELEMENT
|
!TRIA ELEMENT
|
||||||
!Init tria element
|
!Init tria element
|
||||||
SUBROUTINE initVolTria2DCyl(self, n, p)
|
SUBROUTINE initVolTria2DCyl(self, n, p, nodes)
|
||||||
USE moduleRefParam
|
USE moduleRefParam
|
||||||
IMPLICIT NONE
|
IMPLICIT NONE
|
||||||
|
|
||||||
CLASS(meshVol2DCylTria), INTENT(out):: self
|
CLASS(meshVol2DCylTria), INTENT(out):: self
|
||||||
INTEGER, INTENT(in):: n
|
INTEGER, INTENT(in):: n
|
||||||
INTEGER, INTENT(in):: p(:)
|
INTEGER, INTENT(in):: p(:)
|
||||||
|
TYPE(meshNodeCont), INTENT(in), TARGET:: nodes(:)
|
||||||
REAL(8), DIMENSION(1:3):: r1, r2, r3
|
REAL(8), DIMENSION(1:3):: r1, r2, r3
|
||||||
|
|
||||||
!Assign node index
|
!Assign node index
|
||||||
self%n = n
|
self%n = n
|
||||||
|
|
||||||
!Assign nodes to element
|
!Assign nodes to element
|
||||||
self%n1 => mesh%nodes(p(1))%obj
|
self%n1 => nodes(p(1))%obj
|
||||||
self%n2 => mesh%nodes(p(2))%obj
|
self%n2 => nodes(p(2))%obj
|
||||||
self%n3 => mesh%nodes(p(3))%obj
|
self%n3 => nodes(p(3))%obj
|
||||||
!Get element coordinates
|
!Get element coordinates
|
||||||
r1 = self%n1%getCoordinates()
|
r1 = self%n1%getCoordinates()
|
||||||
r2 = self%n2%getCoordinates()
|
r2 = self%n2%getCoordinates()
|
||||||
|
|
@ -800,18 +803,19 @@ MODULE moduleMesh2DCyl
|
||||||
END SUBROUTINE partialDerTria
|
END SUBROUTINE partialDerTria
|
||||||
|
|
||||||
!Computes element local stiffness matrix
|
!Computes element local stiffness matrix
|
||||||
PURE FUNCTION elemKTria(self) RESULT(ke)
|
PURE FUNCTION elemKTria(self) RESULT(localK)
|
||||||
USE moduleConstParam, ONLY: PI2
|
USE moduleConstParam, ONLY: PI2
|
||||||
IMPLICIT NONE
|
IMPLICIT NONE
|
||||||
|
|
||||||
CLASS(meshVol2DCylTria), INTENT(in):: self
|
CLASS(meshVol2DCylTria), INTENT(in):: self
|
||||||
|
REAL(8), ALLOCATABLE:: localK(:,:)
|
||||||
REAL(8):: r, xi(1:3)
|
REAL(8):: r, xi(1:3)
|
||||||
REAL(8):: fPsi(1:3), dPsi(1:2,1:3)
|
REAL(8):: fPsi(1:3), dPsi(1:2,1:3)
|
||||||
REAL(8):: ke(1:3,1:3)
|
|
||||||
REAL(8):: invJ(1:2,1:2), detJ
|
REAL(8):: invJ(1:2,1:2), detJ
|
||||||
INTEGER:: l
|
INTEGER:: l
|
||||||
|
|
||||||
ke=0.D0
|
ALLOCATE(localK(1:4, 1:4))
|
||||||
|
localK=0.D0
|
||||||
xi=0.D0
|
xi=0.D0
|
||||||
!Start 2D Gauss Quad Integral
|
!Start 2D Gauss Quad Integral
|
||||||
DO l=1, 4
|
DO l=1, 4
|
||||||
|
|
@ -822,10 +826,10 @@ MODULE moduleMesh2DCyl
|
||||||
invJ = self%invJac(xi,dPsi)
|
invJ = self%invJac(xi,dPsi)
|
||||||
fPsi = self%fPsi(xi)
|
fPsi = self%fPsi(xi)
|
||||||
r = DOT_PRODUCT(fPsi,self%r)
|
r = DOT_PRODUCT(fPsi,self%r)
|
||||||
ke = ke + MATMUL(TRANSPOSE(MATMUL(invJ,dPsi)),MATMUL(invJ,dPsi))*r*wTria(l)/detJ
|
localK = localK + MATMUL(TRANSPOSE(MATMUL(invJ,dPsi)),MATMUL(invJ,dPsi))*r*wTria(l)/detJ
|
||||||
|
|
||||||
END DO
|
END DO
|
||||||
ke = ke*PI2
|
localK = localK*PI2
|
||||||
|
|
||||||
END FUNCTION elemKTria
|
END FUNCTION elemKTria
|
||||||
|
|
||||||
|
|
@ -898,17 +902,17 @@ MODULE moduleMesh2DCyl
|
||||||
w_p = self%weight(part%xi)
|
w_p = self%weight(part%xi)
|
||||||
tensorS = outerProduct(part%v, part%v)
|
tensorS = outerProduct(part%v, part%v)
|
||||||
|
|
||||||
vertex => self%n1%output(part%sp)
|
vertex => self%n1%output(part%species%n)
|
||||||
vertex%den = vertex%den + part%weight*w_p(1)
|
vertex%den = vertex%den + part%weight*w_p(1)
|
||||||
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(1)*part%v(:)
|
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(1)*part%v(:)
|
||||||
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(1)*tensorS
|
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(1)*tensorS
|
||||||
|
|
||||||
vertex => self%n2%output(part%sp)
|
vertex => self%n2%output(part%species%n)
|
||||||
vertex%den = vertex%den + part%weight*w_p(2)
|
vertex%den = vertex%den + part%weight*w_p(2)
|
||||||
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(2)*part%v(:)
|
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(2)*part%v(:)
|
||||||
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(2)*tensorS
|
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(2)*tensorS
|
||||||
|
|
||||||
vertex => self%n3%output(part%sp)
|
vertex => self%n3%output(part%species%n)
|
||||||
vertex%den = vertex%den + part%weight*w_p(3)
|
vertex%den = vertex%den + part%weight*w_p(3)
|
||||||
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(3)*part%v(:)
|
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(3)*part%v(:)
|
||||||
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(3)*tensorS
|
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(3)*tensorS
|
||||||
|
|
@ -979,7 +983,7 @@ MODULE moduleMesh2DCyl
|
||||||
|
|
||||||
CLASS(meshVol2DCylTria), INTENT(in):: self
|
CLASS(meshVol2DCylTria), INTENT(in):: self
|
||||||
REAL(8), INTENT(in):: xi(1:3)
|
REAL(8), INTENT(in):: xi(1:3)
|
||||||
CLASS(*), POINTER, INTENT(out):: nextElement
|
CLASS(meshElement), POINTER, INTENT(out):: nextElement
|
||||||
REAL(8):: xiArray(1:3)
|
REAL(8):: xiArray(1:3)
|
||||||
INTEGER:: nextInt
|
INTEGER:: nextInt
|
||||||
|
|
||||||
|
|
@ -1047,4 +1051,453 @@ MODULE moduleMesh2DCyl
|
||||||
|
|
||||||
END FUNCTION invJ2DCyl
|
END FUNCTION invJ2DCyl
|
||||||
|
|
||||||
|
SUBROUTINE connectMesh2DCyl(self)
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
CLASS(meshGeneric), INTENT(inout):: self
|
||||||
|
INTEGER:: e, et
|
||||||
|
|
||||||
|
DO e = 1, self%numVols
|
||||||
|
!Connect Vol-Vol
|
||||||
|
DO et = 1, self%numVols
|
||||||
|
IF (e /= et) THEN
|
||||||
|
CALL connectVolVol(self%vols(e)%obj, self%vols(et)%obj)
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END DO
|
||||||
|
|
||||||
|
SELECT TYPE(self)
|
||||||
|
TYPE IS(meshParticles)
|
||||||
|
!Connect Vol-Edge
|
||||||
|
DO et = 1, self%numEdges
|
||||||
|
CALL connectVolEdge(self%vols(e)%obj, self%edges(et)%obj)
|
||||||
|
|
||||||
|
END DO
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
END DO
|
||||||
|
|
||||||
|
END SUBROUTINE connectMesh2DCyl
|
||||||
|
|
||||||
|
!Selects type of elements to build connection
|
||||||
|
SUBROUTINE connectVolVol(elemA, elemB)
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
CLASS(meshVol), INTENT(inout):: elemA
|
||||||
|
CLASS(meshVol), INTENT(inout):: elemB
|
||||||
|
|
||||||
|
SELECT TYPE(elemA)
|
||||||
|
TYPE IS(meshVol2DCylQuad)
|
||||||
|
!Element A is a quadrilateral
|
||||||
|
SELECT TYPE(elemB)
|
||||||
|
TYPE IS(meshVol2DCylQuad)
|
||||||
|
!Element B is a quadrilateral
|
||||||
|
CALL connectQuadQuad(elemA, elemB)
|
||||||
|
|
||||||
|
TYPE IS(meshVol2DCylTria)
|
||||||
|
!Element B is a triangle
|
||||||
|
CALL connectQuadTria(elemA, elemB)
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
TYPE IS(meshVol2DCylTria)
|
||||||
|
!Element A is a Triangle
|
||||||
|
SELECT TYPE(elemB)
|
||||||
|
TYPE IS(meshVol2DCylQuad)
|
||||||
|
!Element B is a quadrilateral
|
||||||
|
CALL connectQuadTria(elemB, elemA)
|
||||||
|
|
||||||
|
TYPE IS(meshVol2DCylTria)
|
||||||
|
!Element B is a triangle
|
||||||
|
CALL connectTriaTria(elemA, elemB)
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
END SUBROUTINE connectVolVol
|
||||||
|
|
||||||
|
SUBROUTINE connectVolEdge(elemA, elemB)
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
CLASS(meshVol), INTENT(inout):: elemA
|
||||||
|
CLASS(meshEdge), INTENT(inout):: elemB
|
||||||
|
|
||||||
|
SELECT TYPE(elemB)
|
||||||
|
CLASS IS(meshEdge2DCyl)
|
||||||
|
SELECT TYPE(elemA)
|
||||||
|
TYPE IS(meshVol2DCylQuad)
|
||||||
|
!Element A is a quadrilateral
|
||||||
|
CALL connectQuadEdge(elemA, elemB)
|
||||||
|
|
||||||
|
TYPE IS(meshVol2DCylTria)
|
||||||
|
!Element A is a triangle
|
||||||
|
CALL connectTriaEdge(elemA, elemB)
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
END SUBROUTINE connectVolEdge
|
||||||
|
|
||||||
|
SUBROUTINE connectQuadQuad(elemA, elemB)
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
CLASS(meshVol2DCylQuad), INTENT(inout), TARGET:: elemA
|
||||||
|
CLASS(meshVol2DCylQuad), INTENT(inout), TARGET:: elemB
|
||||||
|
|
||||||
|
!Check direction 1
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e1) .AND. &
|
||||||
|
elemA%n1%n == elemB%n4%n .AND. &
|
||||||
|
elemA%n2%n == elemB%n3%n) THEN
|
||||||
|
elemA%e1 => elemB
|
||||||
|
elemB%e3 => elemA
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
!Check direction 2
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e2) .AND. &
|
||||||
|
elemA%n2%n == elemB%n1%n .AND. &
|
||||||
|
elemA%n3%n == elemB%n4%n) THEN
|
||||||
|
elemA%e2 => elemB
|
||||||
|
elemB%e4 => elemA
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
!Check direction 3
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e3) .AND. &
|
||||||
|
elemA%n3%n == elemB%n2%n .AND. &
|
||||||
|
elemA%n4%n == elemB%n1%n) THEN
|
||||||
|
elemA%e3 => elemB
|
||||||
|
elemB%e1 => elemA
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
!Check direction 4
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e4) .AND. &
|
||||||
|
elemA%n4%n == elemB%n3%n .AND. &
|
||||||
|
elemA%n1%n == elemB%n2%n) THEN
|
||||||
|
elemA%e4 => elemB
|
||||||
|
elemB%e2 => elemA
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END SUBROUTINE connectQuadQuad
|
||||||
|
|
||||||
|
SUBROUTINE connectQuadTria(elemA, elemB)
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
CLASS(meshVol2DCylQuad), INTENT(inout), TARGET:: elemA
|
||||||
|
CLASS(meshVol2DCylTria), INTENT(inout), TARGET:: elemB
|
||||||
|
|
||||||
|
!Check direction 1
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e1)) THEN
|
||||||
|
IF (elemA%n1%n == elemB%n1%n .AND. &
|
||||||
|
elemA%n2%n == elemB%n3%n) THEN
|
||||||
|
elemA%e1 => elemB
|
||||||
|
elemB%e3 => elemA
|
||||||
|
|
||||||
|
ELSEIF (elemA%n1%n == elemB%n3%n .AND. &
|
||||||
|
elemA%n2%n == elemB%n2%n) THEN
|
||||||
|
elemA%e1 => elemB
|
||||||
|
elemB%e2 => elemA
|
||||||
|
|
||||||
|
ELSEIF (elemA%n1%n == elemB%n2%n .AND. &
|
||||||
|
elemA%n2%n == elemB%n1%n) THEN
|
||||||
|
elemA%e1 => elemB
|
||||||
|
elemB%e1 => elemA
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
!Check direction 2
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e2)) THEN
|
||||||
|
IF (elemA%n2%n == elemB%n1%n .AND. &
|
||||||
|
elemA%n3%n == elemB%n3%n) THEN
|
||||||
|
elemA%e2 => elemB
|
||||||
|
elemB%e3 => elemA
|
||||||
|
|
||||||
|
ELSEIF (elemA%n2%n == elemB%n3%n .AND. &
|
||||||
|
elemA%n3%n == elemB%n2%n) THEN
|
||||||
|
elemA%e2 => elemB
|
||||||
|
elemB%e2 => elemA
|
||||||
|
|
||||||
|
ELSEIF (elemA%n2%n == elemB%n2%n .AND. &
|
||||||
|
elemA%n3%n == elemB%n1%n) THEN
|
||||||
|
elemA%e2 => elemB
|
||||||
|
elemB%e1 => elemA
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
!Check direction 3
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e3)) THEN
|
||||||
|
IF (elemA%n3%n == elemB%n1%n .AND. &
|
||||||
|
elemA%n4%n == elemB%n3%n) THEN
|
||||||
|
elemA%e3 => elemB
|
||||||
|
elemB%e3 => elemA
|
||||||
|
|
||||||
|
ELSEIF (elemA%n3%n == elemB%n3%n .AND. &
|
||||||
|
elemA%n4%n == elemB%n2%n) THEN
|
||||||
|
elemA%e3 => elemB
|
||||||
|
elemB%e2 => elemA
|
||||||
|
|
||||||
|
ELSEIF (elemA%n3%n == elemB%n2%n .AND. &
|
||||||
|
elemA%n4%n == elemB%n1%n) THEN
|
||||||
|
elemA%e3 => elemB
|
||||||
|
elemB%e1 => elemA
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
!Check direction 4
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e4)) THEN
|
||||||
|
IF (elemA%n4%n == elemB%n1%n .AND. &
|
||||||
|
elemA%n1%n == elemB%n3%n) THEN
|
||||||
|
elemA%e4 => elemB
|
||||||
|
elemB%e3 => elemA
|
||||||
|
|
||||||
|
ELSEIF (elemA%n4%n == elemB%n3%n .AND. &
|
||||||
|
elemA%n1%n == elemB%n2%n) THEN
|
||||||
|
elemA%e4 => elemB
|
||||||
|
elemB%e2 => elemA
|
||||||
|
|
||||||
|
ELSEIF (elemA%n4%n == elemB%n2%n .AND. &
|
||||||
|
elemA%n1%n == elemB%n1%n) THEN
|
||||||
|
elemA%e4 => elemB
|
||||||
|
elemB%e1 => elemA
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END SUBROUTINE connectQuadTria
|
||||||
|
|
||||||
|
SUBROUTINE connectTriaTria(elemA, elemB)
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
CLASS(meshVol2DCylTria), INTENT(inout), TARGET:: elemA
|
||||||
|
CLASS(meshVol2DCylTria), INTENT(inout), TARGET:: elemB
|
||||||
|
|
||||||
|
!Check direction 1
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e1)) THEN
|
||||||
|
IF (elemA%n1%n == elemB%n1%n .AND. &
|
||||||
|
elemA%n2%n == elemB%n3%n) THEN
|
||||||
|
elemA%e1 => elemB
|
||||||
|
elemB%e3 => elemA
|
||||||
|
|
||||||
|
ELSEIF (elemA%n1%n == elemB%n2%n .AND. &
|
||||||
|
elemA%n2%n == elemB%n1%n) THEN
|
||||||
|
elemA%e1 => elemB
|
||||||
|
elemB%e1 => elemA
|
||||||
|
|
||||||
|
ELSEIF (elemA%n1%n == elemB%n3%n .AND. &
|
||||||
|
elemA%n2%n == elemB%n2%n) THEN
|
||||||
|
elemA%e1 => elemB
|
||||||
|
elemB%e2 => elemA
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
!Check direction 2
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e2)) THEN
|
||||||
|
IF (elemA%n2%n == elemB%n1%n .AND. &
|
||||||
|
elemA%n3%n == elemB%n3%n) THEN
|
||||||
|
elemA%e2 => elemB
|
||||||
|
elemB%e3 => elemA
|
||||||
|
|
||||||
|
ELSEIF (elemA%n2%n == elemB%n2%n .AND. &
|
||||||
|
elemA%n3%n == elemB%n1%n) THEN
|
||||||
|
elemA%e2 => elemB
|
||||||
|
elemB%e1 => elemA
|
||||||
|
|
||||||
|
ELSEIF (elemA%n2%n == elemB%n3%n .AND. &
|
||||||
|
elemA%n3%n == elemB%n2%n) THEN
|
||||||
|
elemA%e2 => elemB
|
||||||
|
elemB%e2 => elemA
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
!Check direction 3
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e3)) THEN
|
||||||
|
IF (elemA%n3%n == elemB%n1%n .AND. &
|
||||||
|
elemA%n1%n == elemB%n3%n) THEN
|
||||||
|
elemA%e3 => elemB
|
||||||
|
elemB%e3 => elemA
|
||||||
|
|
||||||
|
ELSEIF (elemA%n3%n == elemB%n2%n .AND. &
|
||||||
|
elemA%n1%n == elemB%n1%n) THEN
|
||||||
|
elemA%e3 => elemB
|
||||||
|
elemB%e1 => elemA
|
||||||
|
|
||||||
|
ELSEIF (elemA%n3%n == elemB%n3%n .AND. &
|
||||||
|
elemA%n1%n == elemB%n2%n) THEN
|
||||||
|
elemA%e3 => elemB
|
||||||
|
elemB%e2 => elemA
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END SUBROUTINE connectTriaTria
|
||||||
|
|
||||||
|
SUBROUTINE connectQuadEdge(elemA, elemB)
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
CLASS(meshVol2DCylQuad), INTENT(inout), TARGET:: elemA
|
||||||
|
CLASS(meshEdge2DCyl), INTENT(inout), TARGET:: elemB
|
||||||
|
|
||||||
|
!Check direction 1
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e1)) THEN
|
||||||
|
IF (elemA%n1%n == elemB%n1%n .AND. &
|
||||||
|
elemA%n2%n == elemB%n2%n) THEN
|
||||||
|
elemA%e1 => elemB
|
||||||
|
elemB%e1 => elemA
|
||||||
|
|
||||||
|
ELSEIF (elemA%n1%n == elemB%n2%n .AND. &
|
||||||
|
elemA%n2%n == elemB%n1%n) THEN
|
||||||
|
elemA%e1 => elemB
|
||||||
|
elemB%e2 => elemA
|
||||||
|
|
||||||
|
!Revers the normal to point inside the domain
|
||||||
|
elemB%normal = - elemB%normal
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
!Check direction 2
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e2)) THEN
|
||||||
|
IF (elemA%n2%n == elemB%n1%n .AND. &
|
||||||
|
elemA%n3%n == elemB%n2%n) THEN
|
||||||
|
elemA%e2 => elemB
|
||||||
|
elemB%e1 => elemA
|
||||||
|
|
||||||
|
ELSEIF (elemA%n2%n == elemB%n2%n .AND. &
|
||||||
|
elemA%n3%n == elemB%n1%n) THEN
|
||||||
|
elemA%e2 => elemB
|
||||||
|
elemB%e2 => elemA
|
||||||
|
|
||||||
|
!Revers the normal to point inside the domain
|
||||||
|
elemB%normal = - elemB%normal
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
!Check direction 3
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e3)) THEN
|
||||||
|
IF (elemA%n3%n == elemB%n1%n .AND. &
|
||||||
|
elemA%n4%n == elemB%n2%n) THEN
|
||||||
|
elemA%e3 => elemB
|
||||||
|
elemB%e1 => elemA
|
||||||
|
|
||||||
|
ELSEIF (elemA%n3%n == elemB%n2%n .AND. &
|
||||||
|
elemA%n4%n == elemB%n1%n) THEN
|
||||||
|
elemA%e3 => elemB
|
||||||
|
elemB%e2 => elemA
|
||||||
|
|
||||||
|
!Revers the normal to point inside the domain
|
||||||
|
elemB%normal = - elemB%normal
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
!Check direction 4
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e4)) THEN
|
||||||
|
IF (elemA%n4%n == elemB%n1%n .AND. &
|
||||||
|
elemA%n1%n == elemB%n2%n) THEN
|
||||||
|
elemA%e4 => elemB
|
||||||
|
elemB%e1 => elemA
|
||||||
|
|
||||||
|
ELSEIF (elemA%n4%n == elemB%n2%n .AND. &
|
||||||
|
elemA%n1%n == elemB%n1%n) THEN
|
||||||
|
elemA%e4 => elemB
|
||||||
|
elemB%e2 => elemA
|
||||||
|
|
||||||
|
!Revers the normal to point inside the domain
|
||||||
|
elemB%normal = - elemB%normal
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END SUBROUTINE connectQuadEdge
|
||||||
|
|
||||||
|
SUBROUTINE connectTriaEdge(elemA, elemB)
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
CLASS(meshVol2DCylTria), INTENT(inout), TARGET:: elemA
|
||||||
|
CLASS(meshEdge2DCyl), INTENT(inout), TARGET:: elemB
|
||||||
|
|
||||||
|
!Check direction 1
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e1)) THEN
|
||||||
|
IF (elemA%n1%n == elemB%n1%n .AND. &
|
||||||
|
elemA%n2%n == elemB%n2%n) THEN
|
||||||
|
elemA%e1 => elemB
|
||||||
|
elemB%e1 => elemA
|
||||||
|
|
||||||
|
ELSEIF (elemA%n1%n == elemB%n2%n .AND. &
|
||||||
|
elemA%n2%n == elemB%n1%n) THEN
|
||||||
|
elemA%e1 => elemB
|
||||||
|
elemB%e2 => elemA
|
||||||
|
|
||||||
|
!Revers the normal to point inside the domain
|
||||||
|
elemB%normal = - elemB%normal
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
!Check direction 2
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e2)) THEN
|
||||||
|
IF (elemA%n2%n == elemB%n1%n .AND. &
|
||||||
|
elemA%n3%n == elemB%n2%n) THEN
|
||||||
|
elemA%e2 => elemB
|
||||||
|
elemB%e1 => elemA
|
||||||
|
|
||||||
|
ELSEIF (elemA%n2%n == elemB%n2%n .AND. &
|
||||||
|
elemA%n3%n == elemB%n1%n) THEN
|
||||||
|
elemA%e2 => elemB
|
||||||
|
elemB%e2 => elemA
|
||||||
|
|
||||||
|
!Revers the normal to point inside the domain
|
||||||
|
elemB%normal = - elemB%normal
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
!Check direction 3
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e3)) THEN
|
||||||
|
IF (elemA%n3%n == elemB%n1%n .AND. &
|
||||||
|
elemA%n1%n == elemB%n2%n) THEN
|
||||||
|
elemA%e3 => elemB
|
||||||
|
elemB%e1 => elemA
|
||||||
|
|
||||||
|
ELSEIF (elemA%n3%n == elemB%n2%n .AND. &
|
||||||
|
elemA%n1%n == elemB%n1%n) THEN
|
||||||
|
elemA%e3 => elemB
|
||||||
|
elemB%e2 => elemA
|
||||||
|
|
||||||
|
!Revers the normal to point inside the domain
|
||||||
|
elemB%normal = - elemB%normal
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END SUBROUTINE connectTriaEdge
|
||||||
|
|
||||||
END MODULE moduleMesh2DCyl
|
END MODULE moduleMesh2DCyl
|
||||||
|
|
|
||||||
|
|
@ -1,643 +0,0 @@
|
||||||
MODULE moduleMesh2DCylRead
|
|
||||||
USE moduleMesh
|
|
||||||
USE moduleMesh2DCyl
|
|
||||||
|
|
||||||
TYPE, EXTENDS(meshGeneric):: mesh2DCylGeneric
|
|
||||||
CONTAINS
|
|
||||||
PROCEDURE, PASS:: init => init2DCylMesh
|
|
||||||
PROCEDURE, PASS:: readMesh => readMesh2DCylGmsh
|
|
||||||
|
|
||||||
END TYPE
|
|
||||||
|
|
||||||
INTERFACE connected
|
|
||||||
MODULE PROCEDURE connectedVolVol, connectedVolEdge
|
|
||||||
|
|
||||||
END INTERFACE connected
|
|
||||||
|
|
||||||
CONTAINS
|
|
||||||
!Init mesh
|
|
||||||
SUBROUTINE init2DCylMesh(self, meshFormat)
|
|
||||||
USE moduleMesh
|
|
||||||
USE moduleErrors
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
CLASS(mesh2DCylGeneric), INTENT(out):: self
|
|
||||||
CHARACTER(:), ALLOCATABLE, INTENT(in):: meshFormat
|
|
||||||
|
|
||||||
SELECT CASE(meshFormat)
|
|
||||||
CASE ("gmsh")
|
|
||||||
self%printOutput => printOutputGmsh
|
|
||||||
self%printColl => printCollGmsh
|
|
||||||
self%printEM => printEMGmsh
|
|
||||||
|
|
||||||
CASE DEFAULT
|
|
||||||
CALL criticalError("Mesh type " // meshFormat // " not supported.", "init2DCylMesh")
|
|
||||||
|
|
||||||
END SELECT
|
|
||||||
|
|
||||||
END SUBROUTINE init2DCylMesh
|
|
||||||
|
|
||||||
!Read mesh from gmsh file
|
|
||||||
SUBROUTINE readMesh2DCylGmsh(self, filename)
|
|
||||||
USE moduleBoundary
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
CLASS(mesh2DCylGeneric), INTENT(inout):: self
|
|
||||||
CHARACTER(:), ALLOCATABLE, INTENT(in):: filename
|
|
||||||
REAL(8):: r, z
|
|
||||||
INTEGER:: p(1:4)
|
|
||||||
INTEGER:: e=0, et=0, n=0, eTemp=0, elemType=0, bt = 0
|
|
||||||
INTEGER:: totalNumElem
|
|
||||||
INTEGER:: boundaryType
|
|
||||||
|
|
||||||
!Read msh
|
|
||||||
OPEN(10, FILE=TRIM(filename))
|
|
||||||
!Skip header
|
|
||||||
READ(10, *)
|
|
||||||
READ(10, *)
|
|
||||||
READ(10, *)
|
|
||||||
READ(10, *)
|
|
||||||
!Read number of nodes
|
|
||||||
READ(10, *) self%numNodes
|
|
||||||
!Allocate required matrices and vectors
|
|
||||||
ALLOCATE(self%nodes(1:self%numNodes))
|
|
||||||
ALLOCATE(self%K(1:self%numNodes,1:self%numNodes))
|
|
||||||
ALLOCATE(self%IPIV(1:self%numNodes,1:self%numNodes))
|
|
||||||
self%K = 0.D0
|
|
||||||
self%IPIV = 0
|
|
||||||
!Read nodes cartesian coordinates (x=z, y=r, z=null)
|
|
||||||
DO e=1, self%numNodes
|
|
||||||
READ(10, *) n, z, r
|
|
||||||
ALLOCATE(meshNode2DCyl:: self%nodes(n)%obj)
|
|
||||||
CALL self%nodes(n)%obj%init(n, (/z, r, 0.D0 /))
|
|
||||||
|
|
||||||
END DO
|
|
||||||
!Skips comments
|
|
||||||
READ(10, *)
|
|
||||||
READ(10, *)
|
|
||||||
!Reads Totalnumber of elements
|
|
||||||
READ(10, *) TotalnumElem
|
|
||||||
!counts edges and volume elements
|
|
||||||
self%numEdges = 0
|
|
||||||
DO e=1, TotalnumElem
|
|
||||||
READ(10,*) eTemp, elemType
|
|
||||||
IF (elemType==1) THEN
|
|
||||||
self%numEdges=e
|
|
||||||
END IF
|
|
||||||
END DO
|
|
||||||
!Substract the number of edges to the total number of elements
|
|
||||||
!to obtain the number of volume elements
|
|
||||||
self%numVols = TotalnumElem - self%numEdges
|
|
||||||
!Allocates arrays
|
|
||||||
ALLOCATE(self%edges(1:self%numEdges))
|
|
||||||
ALLOCATE(self%vols(1:self%numVols))
|
|
||||||
|
|
||||||
!Go back to the beggining to read elements
|
|
||||||
DO e=1, totalNumElem
|
|
||||||
BACKSPACE(10)
|
|
||||||
END DO
|
|
||||||
|
|
||||||
!Reads edges
|
|
||||||
DO e=1, self%numEdges
|
|
||||||
READ(10,*) n, elemType, eTemp, boundaryType, eTemp, p(1:2)
|
|
||||||
!Associate boundary condition procedure.
|
|
||||||
bt = getBoundaryId(boundaryType)
|
|
||||||
|
|
||||||
ALLOCATE(meshEdge2DCyl:: self%edges(e)%obj)
|
|
||||||
|
|
||||||
CALL self%edges(e)%obj%init(n, p(1:2), bt, boundaryType)
|
|
||||||
|
|
||||||
END DO
|
|
||||||
|
|
||||||
!Read and initialize volumes
|
|
||||||
DO e=1, self%numVols
|
|
||||||
READ(10,*) n, elemType
|
|
||||||
BACKSPACE(10)
|
|
||||||
|
|
||||||
SELECT CASE(elemType)
|
|
||||||
CASE (2)
|
|
||||||
!Triangular element
|
|
||||||
READ(10,*) n, elemType, eTemp, eTemp, eTemp, p(1:3)
|
|
||||||
ALLOCATE(meshVol2DCylTria:: self%vols(e)%obj)
|
|
||||||
CALL self%vols(e)%obj%init(n - self%numEdges, p(1:3))
|
|
||||||
|
|
||||||
CASE (3)
|
|
||||||
!Quadrilateral element
|
|
||||||
READ(10,*) n, elemType, eTemp, eTemp, eTemp, p(1:4)
|
|
||||||
ALLOCATE(meshVol2DCylQuad:: self%vols(e)%obj)
|
|
||||||
CALL self%vols(e)%obj%init(n - self%numEdges, p(1:4))
|
|
||||||
|
|
||||||
END SELECT
|
|
||||||
|
|
||||||
END DO
|
|
||||||
|
|
||||||
CLOSE(10)
|
|
||||||
|
|
||||||
!Build connectivity between elements
|
|
||||||
DO e = 1, self%numVols
|
|
||||||
!Connectivity between volumes
|
|
||||||
DO et = 1, self%numVols
|
|
||||||
IF (e /= et) THEN
|
|
||||||
CALL connected(self%vols(e)%obj, self%vols(et)%obj)
|
|
||||||
|
|
||||||
END IF
|
|
||||||
END DO
|
|
||||||
|
|
||||||
!Connectivity between vols and edges
|
|
||||||
DO et = 1, self%numEdges
|
|
||||||
CALL connected(self%vols(e)%obj, self%edges(et)%obj)
|
|
||||||
|
|
||||||
END DO
|
|
||||||
|
|
||||||
!Constructs the global K matrix
|
|
||||||
CALL constructGlobalK(self%K, self%vols(e)%obj)
|
|
||||||
|
|
||||||
END DO
|
|
||||||
|
|
||||||
END SUBROUTINE readMesh2DCylGmsh
|
|
||||||
|
|
||||||
!Selects type of elements to build connection
|
|
||||||
SUBROUTINE connectedVolVol(elemA, elemB)
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
CLASS(meshVol), INTENT(inout):: elemA
|
|
||||||
CLASS(meshVol), INTENT(inout):: elemB
|
|
||||||
|
|
||||||
SELECT TYPE(elemA)
|
|
||||||
TYPE IS(meshVol2DCylQuad)
|
|
||||||
!Element A is a quadrilateral
|
|
||||||
SELECT TYPE(elemB)
|
|
||||||
TYPE IS(meshVol2DCylQuad)
|
|
||||||
!Element B is a quadrilateral
|
|
||||||
CALL connectedQuadQuad(elemA, elemB)
|
|
||||||
|
|
||||||
TYPE IS(meshVol2DCylTria)
|
|
||||||
!Element B is a triangle
|
|
||||||
CALL connectedQuadTria(elemA, elemB)
|
|
||||||
|
|
||||||
END SELECT
|
|
||||||
|
|
||||||
TYPE IS(meshVol2DCylTria)
|
|
||||||
!Element A is a Triangle
|
|
||||||
SELECT TYPE(elemB)
|
|
||||||
TYPE IS(meshVol2DCylQuad)
|
|
||||||
!Element B is a quadrilateral
|
|
||||||
CALL connectedQuadTria(elemB, elemA)
|
|
||||||
|
|
||||||
TYPE IS(meshVol2DCylTria)
|
|
||||||
!Element B is a triangle
|
|
||||||
CALL connectedTriaTria(elemA, elemB)
|
|
||||||
|
|
||||||
END SELECT
|
|
||||||
|
|
||||||
END SELECT
|
|
||||||
|
|
||||||
END SUBROUTINE connectedVolVol
|
|
||||||
|
|
||||||
SUBROUTINE connectedVolEdge(elemA, elemB)
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
CLASS(meshVol), INTENT(inout):: elemA
|
|
||||||
CLASS(meshEdge), INTENT(inout):: elemB
|
|
||||||
|
|
||||||
SELECT TYPE(elemB)
|
|
||||||
CLASS IS(meshEdge2DCyl)
|
|
||||||
SELECT TYPE(elemA)
|
|
||||||
TYPE IS(meshVol2DCylQuad)
|
|
||||||
!Element A is a quadrilateral
|
|
||||||
CALL connectedQuadEdge(elemA, elemB)
|
|
||||||
|
|
||||||
TYPE IS(meshVol2DCylTria)
|
|
||||||
!Element A is a triangle
|
|
||||||
CALL connectedTriaEdge(elemA, elemB)
|
|
||||||
|
|
||||||
END SELECT
|
|
||||||
|
|
||||||
END SELECT
|
|
||||||
|
|
||||||
END SUBROUTINE connectedVolEdge
|
|
||||||
|
|
||||||
PURE FUNCTION coincidentNodes(nodesA, nodesB) RESULT(coincident)
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
INTEGER, DIMENSION(1:2), INTENT(in):: nodesA, nodesB
|
|
||||||
LOGICAL:: coincident
|
|
||||||
INTEGER:: i
|
|
||||||
|
|
||||||
coincident = .FALSE.
|
|
||||||
DO i = 1, 2
|
|
||||||
IF (ANY(nodesA(i) == nodesB)) THEN
|
|
||||||
coincident = .TRUE.
|
|
||||||
|
|
||||||
ELSE
|
|
||||||
coincident = .FALSE.
|
|
||||||
EXIT
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END DO
|
|
||||||
|
|
||||||
END FUNCTION coincidentNodes
|
|
||||||
|
|
||||||
|
|
||||||
SUBROUTINE connectedQuadQuad(elemA, elemB)
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
CLASS(meshVol2DCylQuad), INTENT(inout), TARGET:: elemA
|
|
||||||
CLASS(meshVol2DCylQuad), INTENT(inout), TARGET:: elemB
|
|
||||||
|
|
||||||
!Check direction 1
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e1) .AND. &
|
|
||||||
elemA%n1%n == elemB%n4%n .AND. &
|
|
||||||
elemA%n2%n == elemB%n3%n) THEN
|
|
||||||
elemA%e1 => elemB
|
|
||||||
elemB%e3 => elemA
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
!Check direction 2
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e2) .AND. &
|
|
||||||
elemA%n2%n == elemB%n1%n .AND. &
|
|
||||||
elemA%n3%n == elemB%n4%n) THEN
|
|
||||||
elemA%e2 => elemB
|
|
||||||
elemB%e4 => elemA
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
!Check direction 3
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e3) .AND. &
|
|
||||||
elemA%n3%n == elemB%n2%n .AND. &
|
|
||||||
elemA%n4%n == elemB%n1%n) THEN
|
|
||||||
elemA%e3 => elemB
|
|
||||||
elemB%e1 => elemA
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
!Check direction 4
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e4) .AND. &
|
|
||||||
elemA%n4%n == elemB%n3%n .AND. &
|
|
||||||
elemA%n1%n == elemB%n2%n) THEN
|
|
||||||
elemA%e4 => elemB
|
|
||||||
elemB%e2 => elemA
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END SUBROUTINE connectedQuadQuad
|
|
||||||
|
|
||||||
SUBROUTINE connectedQuadTria(elemA, elemB)
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
CLASS(meshVol2DCylQuad), INTENT(inout), TARGET:: elemA
|
|
||||||
CLASS(meshVol2DCylTria), INTENT(inout), TARGET:: elemB
|
|
||||||
|
|
||||||
!Check direction 1
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e1)) THEN
|
|
||||||
IF (elemA%n1%n == elemB%n1%n .AND. &
|
|
||||||
elemA%n2%n == elemB%n3%n) THEN
|
|
||||||
elemA%e1 => elemB
|
|
||||||
elemB%e3 => elemA
|
|
||||||
|
|
||||||
ELSEIF (elemA%n1%n == elemB%n3%n .AND. &
|
|
||||||
elemA%n2%n == elemB%n2%n) THEN
|
|
||||||
elemA%e1 => elemB
|
|
||||||
elemB%e2 => elemA
|
|
||||||
|
|
||||||
ELSEIF (elemA%n1%n == elemB%n2%n .AND. &
|
|
||||||
elemA%n2%n == elemB%n1%n) THEN
|
|
||||||
elemA%e1 => elemB
|
|
||||||
elemB%e1 => elemA
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
!Check direction 2
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e2)) THEN
|
|
||||||
IF (elemA%n2%n == elemB%n1%n .AND. &
|
|
||||||
elemA%n3%n == elemB%n3%n) THEN
|
|
||||||
elemA%e2 => elemB
|
|
||||||
elemB%e3 => elemA
|
|
||||||
|
|
||||||
ELSEIF (elemA%n2%n == elemB%n3%n .AND. &
|
|
||||||
elemA%n3%n == elemB%n2%n) THEN
|
|
||||||
elemA%e2 => elemB
|
|
||||||
elemB%e2 => elemA
|
|
||||||
|
|
||||||
ELSEIF (elemA%n2%n == elemB%n2%n .AND. &
|
|
||||||
elemA%n3%n == elemB%n1%n) THEN
|
|
||||||
elemA%e2 => elemB
|
|
||||||
elemB%e1 => elemA
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
!Check direction 3
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e3)) THEN
|
|
||||||
IF (elemA%n3%n == elemB%n1%n .AND. &
|
|
||||||
elemA%n4%n == elemB%n3%n) THEN
|
|
||||||
elemA%e3 => elemB
|
|
||||||
elemB%e3 => elemA
|
|
||||||
|
|
||||||
ELSEIF (elemA%n3%n == elemB%n3%n .AND. &
|
|
||||||
elemA%n4%n == elemB%n2%n) THEN
|
|
||||||
elemA%e3 => elemB
|
|
||||||
elemB%e2 => elemA
|
|
||||||
|
|
||||||
ELSEIF (elemA%n3%n == elemB%n2%n .AND. &
|
|
||||||
elemA%n4%n == elemB%n1%n) THEN
|
|
||||||
elemA%e3 => elemB
|
|
||||||
elemB%e1 => elemA
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
!Check direction 4
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e4)) THEN
|
|
||||||
IF (elemA%n4%n == elemB%n1%n .AND. &
|
|
||||||
elemA%n1%n == elemB%n3%n) THEN
|
|
||||||
elemA%e4 => elemB
|
|
||||||
elemB%e3 => elemA
|
|
||||||
|
|
||||||
ELSEIF (elemA%n4%n == elemB%n3%n .AND. &
|
|
||||||
elemA%n1%n == elemB%n2%n) THEN
|
|
||||||
elemA%e4 => elemB
|
|
||||||
elemB%e2 => elemA
|
|
||||||
|
|
||||||
ELSEIF (elemA%n4%n == elemB%n2%n .AND. &
|
|
||||||
elemA%n1%n == elemB%n1%n) THEN
|
|
||||||
elemA%e4 => elemB
|
|
||||||
elemB%e1 => elemA
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END SUBROUTINE connectedQuadTria
|
|
||||||
|
|
||||||
SUBROUTINE connectedTriaTria(elemA, elemB)
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
CLASS(meshVol2DCylTria), INTENT(inout), TARGET:: elemA
|
|
||||||
CLASS(meshVol2DCylTria), INTENT(inout), TARGET:: elemB
|
|
||||||
|
|
||||||
!Check direction 1
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e1)) THEN
|
|
||||||
IF (elemA%n1%n == elemB%n1%n .AND. &
|
|
||||||
elemA%n2%n == elemB%n3%n) THEN
|
|
||||||
elemA%e1 => elemB
|
|
||||||
elemB%e3 => elemA
|
|
||||||
|
|
||||||
ELSEIF (elemA%n1%n == elemB%n2%n .AND. &
|
|
||||||
elemA%n2%n == elemB%n1%n) THEN
|
|
||||||
elemA%e1 => elemB
|
|
||||||
elemB%e1 => elemA
|
|
||||||
|
|
||||||
ELSEIF (elemA%n1%n == elemB%n3%n .AND. &
|
|
||||||
elemA%n2%n == elemB%n2%n) THEN
|
|
||||||
elemA%e1 => elemB
|
|
||||||
elemB%e2 => elemA
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
!Check direction 2
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e2)) THEN
|
|
||||||
IF (elemA%n2%n == elemB%n1%n .AND. &
|
|
||||||
elemA%n3%n == elemB%n3%n) THEN
|
|
||||||
elemA%e2 => elemB
|
|
||||||
elemB%e3 => elemA
|
|
||||||
|
|
||||||
ELSEIF (elemA%n2%n == elemB%n2%n .AND. &
|
|
||||||
elemA%n3%n == elemB%n1%n) THEN
|
|
||||||
elemA%e2 => elemB
|
|
||||||
elemB%e1 => elemA
|
|
||||||
|
|
||||||
ELSEIF (elemA%n2%n == elemB%n3%n .AND. &
|
|
||||||
elemA%n3%n == elemB%n2%n) THEN
|
|
||||||
elemA%e2 => elemB
|
|
||||||
elemB%e2 => elemA
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
!Check direction 3
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e3)) THEN
|
|
||||||
IF (elemA%n3%n == elemB%n1%n .AND. &
|
|
||||||
elemA%n1%n == elemB%n3%n) THEN
|
|
||||||
elemA%e3 => elemB
|
|
||||||
elemB%e3 => elemA
|
|
||||||
|
|
||||||
ELSEIF (elemA%n3%n == elemB%n2%n .AND. &
|
|
||||||
elemA%n1%n == elemB%n1%n) THEN
|
|
||||||
elemA%e3 => elemB
|
|
||||||
elemB%e1 => elemA
|
|
||||||
|
|
||||||
ELSEIF (elemA%n3%n == elemB%n3%n .AND. &
|
|
||||||
elemA%n1%n == elemB%n2%n) THEN
|
|
||||||
elemA%e3 => elemB
|
|
||||||
elemB%e2 => elemA
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END SUBROUTINE connectedTriaTria
|
|
||||||
|
|
||||||
SUBROUTINE connectedQuadEdge(elemA, elemB)
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
CLASS(meshVol2DCylQuad), INTENT(inout), TARGET:: elemA
|
|
||||||
CLASS(meshEdge2DCyl), INTENT(inout), TARGET:: elemB
|
|
||||||
|
|
||||||
!Check direction 1
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e1)) THEN
|
|
||||||
IF (elemA%n1%n == elemB%n1%n .AND. &
|
|
||||||
elemA%n2%n == elemB%n2%n) THEN
|
|
||||||
elemA%e1 => elemB
|
|
||||||
elemB%e1 => elemA
|
|
||||||
|
|
||||||
ELSEIF (elemA%n1%n == elemB%n2%n .AND. &
|
|
||||||
elemA%n2%n == elemB%n1%n) THEN
|
|
||||||
elemA%e1 => elemB
|
|
||||||
elemB%e2 => elemA
|
|
||||||
|
|
||||||
!Revers the normal to point inside the domain
|
|
||||||
elemB%normal = - elemB%normal
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
!Check direction 2
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e2)) THEN
|
|
||||||
IF (elemA%n2%n == elemB%n1%n .AND. &
|
|
||||||
elemA%n3%n == elemB%n2%n) THEN
|
|
||||||
elemA%e2 => elemB
|
|
||||||
elemB%e1 => elemA
|
|
||||||
|
|
||||||
ELSEIF (elemA%n2%n == elemB%n2%n .AND. &
|
|
||||||
elemA%n3%n == elemB%n1%n) THEN
|
|
||||||
elemA%e2 => elemB
|
|
||||||
elemB%e2 => elemA
|
|
||||||
|
|
||||||
!Revers the normal to point inside the domain
|
|
||||||
elemB%normal = - elemB%normal
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
!Check direction 3
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e3)) THEN
|
|
||||||
IF (elemA%n3%n == elemB%n1%n .AND. &
|
|
||||||
elemA%n4%n == elemB%n2%n) THEN
|
|
||||||
elemA%e3 => elemB
|
|
||||||
elemB%e1 => elemA
|
|
||||||
|
|
||||||
ELSEIF (elemA%n3%n == elemB%n2%n .AND. &
|
|
||||||
elemA%n4%n == elemB%n1%n) THEN
|
|
||||||
elemA%e3 => elemB
|
|
||||||
elemB%e2 => elemA
|
|
||||||
|
|
||||||
!Revers the normal to point inside the domain
|
|
||||||
elemB%normal = - elemB%normal
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
!Check direction 4
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e4)) THEN
|
|
||||||
IF (elemA%n4%n == elemB%n1%n .AND. &
|
|
||||||
elemA%n1%n == elemB%n2%n) THEN
|
|
||||||
elemA%e4 => elemB
|
|
||||||
elemB%e1 => elemA
|
|
||||||
|
|
||||||
ELSEIF (elemA%n4%n == elemB%n2%n .AND. &
|
|
||||||
elemA%n1%n == elemB%n1%n) THEN
|
|
||||||
elemA%e4 => elemB
|
|
||||||
elemB%e2 => elemA
|
|
||||||
|
|
||||||
!Revers the normal to point inside the domain
|
|
||||||
elemB%normal = - elemB%normal
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END SUBROUTINE connectedQuadEdge
|
|
||||||
|
|
||||||
SUBROUTINE connectedTriaEdge(elemA, elemB)
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
CLASS(meshVol2DCylTria), INTENT(inout), TARGET:: elemA
|
|
||||||
CLASS(meshEdge2DCyl), INTENT(inout), TARGET:: elemB
|
|
||||||
|
|
||||||
!Check direction 1
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e1)) THEN
|
|
||||||
IF (elemA%n1%n == elemB%n1%n .AND. &
|
|
||||||
elemA%n2%n == elemB%n2%n) THEN
|
|
||||||
elemA%e1 => elemB
|
|
||||||
elemB%e1 => elemA
|
|
||||||
|
|
||||||
ELSEIF (elemA%n1%n == elemB%n2%n .AND. &
|
|
||||||
elemA%n2%n == elemB%n1%n) THEN
|
|
||||||
elemA%e1 => elemB
|
|
||||||
elemB%e2 => elemA
|
|
||||||
|
|
||||||
!Revers the normal to point inside the domain
|
|
||||||
elemB%normal = - elemB%normal
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
!Check direction 2
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e2)) THEN
|
|
||||||
IF (elemA%n2%n == elemB%n1%n .AND. &
|
|
||||||
elemA%n3%n == elemB%n2%n) THEN
|
|
||||||
elemA%e2 => elemB
|
|
||||||
elemB%e1 => elemA
|
|
||||||
|
|
||||||
ELSEIF (elemA%n2%n == elemB%n2%n .AND. &
|
|
||||||
elemA%n3%n == elemB%n1%n) THEN
|
|
||||||
elemA%e2 => elemB
|
|
||||||
elemB%e2 => elemA
|
|
||||||
|
|
||||||
!Revers the normal to point inside the domain
|
|
||||||
elemB%normal = - elemB%normal
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
!Check direction 3
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e3)) THEN
|
|
||||||
IF (elemA%n3%n == elemB%n1%n .AND. &
|
|
||||||
elemA%n1%n == elemB%n2%n) THEN
|
|
||||||
elemA%e3 => elemB
|
|
||||||
elemB%e1 => elemA
|
|
||||||
|
|
||||||
ELSEIF (elemA%n3%n == elemB%n2%n .AND. &
|
|
||||||
elemA%n1%n == elemB%n1%n) THEN
|
|
||||||
elemA%e3 => elemB
|
|
||||||
elemB%e2 => elemA
|
|
||||||
|
|
||||||
!Revers the normal to point inside the domain
|
|
||||||
elemB%normal = - elemB%normal
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END SUBROUTINE connectedTriaEdge
|
|
||||||
|
|
||||||
SUBROUTINE constructGlobalK(K, elem)
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
REAL(8), INTENT(inout):: K(1:,1:)
|
|
||||||
CLASS(meshVol), INTENT(in):: elem
|
|
||||||
REAL(8), ALLOCATABLE:: localK(:,:)
|
|
||||||
INTEGER:: nNodes, i, j
|
|
||||||
INTEGER, ALLOCATABLE:: n(:)
|
|
||||||
|
|
||||||
SELECT TYPE(elem)
|
|
||||||
TYPE IS(meshVol2DCylQuad)
|
|
||||||
nNodes = 4
|
|
||||||
ALLOCATE(localK(1:nNodes,1:nNodes))
|
|
||||||
localK = elem%elemK()
|
|
||||||
ALLOCATE(n(1:nNodes))
|
|
||||||
n = (/ elem%n1%n, elem%n2%n, &
|
|
||||||
elem%n3%n, elem%n4%n /)
|
|
||||||
|
|
||||||
TYPE IS(meshVol2DCylTria)
|
|
||||||
nNodes = 3
|
|
||||||
ALLOCATE(localK(1:nNodes,1:nNodes))
|
|
||||||
localK = elem%elemK()
|
|
||||||
ALLOCATE(n(1:nNodes))
|
|
||||||
n = (/ elem%n1%n, elem%n2%n, elem%n3%n /)
|
|
||||||
|
|
||||||
CLASS DEFAULT
|
|
||||||
nNodes = 0
|
|
||||||
ALLOCATE(localK(1:1, 1:1))
|
|
||||||
localK = 0.D0
|
|
||||||
ALLOCATE(n(1:1))
|
|
||||||
n = 0
|
|
||||||
|
|
||||||
END SELECT
|
|
||||||
|
|
||||||
DO i = 1, nNodes
|
|
||||||
DO j = 1, nNodes
|
|
||||||
K(n(i), n(j)) = K(n(i), n(j)) + localK(i, j)
|
|
||||||
END DO
|
|
||||||
END DO
|
|
||||||
|
|
||||||
END SUBROUTINE constructGlobalK
|
|
||||||
|
|
||||||
END MODULE moduleMesh2DCylRead
|
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
all : moduleMesh3DCart.o moduleMesh3DCartRead.o
|
all : moduleMesh3DCart.o
|
||||||
|
|
||||||
moduleMesh3DCart.o: moduleMesh3DCart.f90
|
moduleMesh3DCart.o: moduleMesh3DCart.f90
|
||||||
$(FC) $(FCFLAGS) -c $(subst .o,.f90,$@) -o $(OBJDIR)/$@
|
$(FC) $(FCFLAGS) -c $(subst .o,.f90,$@) -o $(OBJDIR)/$@
|
||||||
|
|
||||||
moduleMesh3DCartRead.o: moduleMesh3DCart.o moduleMesh3DCartRead.f90
|
|
||||||
$(FC) $(FCFLAGS) -c $(subst .o,.f90,$@) -o $(OBJDIR)/$@
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ MODULE moduleMesh3DCart
|
||||||
!Connectivity to nodes
|
!Connectivity to nodes
|
||||||
CLASS(meshNode), POINTER:: n1 => NULL(), n2 => NULL(), n3 => NULL(), n4 => NULL()
|
CLASS(meshNode), POINTER:: n1 => NULL(), n2 => NULL(), n3 => NULL(), n4 => NULL()
|
||||||
!Connectivity to adjacent elements
|
!Connectivity to adjacent elements
|
||||||
CLASS(*), POINTER:: e1 => NULL(), e2 => NULL(), e3 => NULL(), e4 => NULL()
|
CLASS(meshElement), POINTER:: e1 => NULL(), e2 => NULL(), e3 => NULL(), e4 => NULL()
|
||||||
CONTAINS
|
CONTAINS
|
||||||
PROCEDURE, PASS:: init => initVolTetra3DCart
|
PROCEDURE, PASS:: init => initVolTetra3DCart
|
||||||
PROCEDURE, PASS:: randPos => randPosVolTetra
|
PROCEDURE, PASS:: randPos => randPosVolTetra
|
||||||
|
|
@ -248,21 +248,22 @@ MODULE moduleMesh3DCart
|
||||||
!VOLUME FUNCTIONS
|
!VOLUME FUNCTIONS
|
||||||
!TETRA FUNCTIONS
|
!TETRA FUNCTIONS
|
||||||
!Inits tetrahedron element
|
!Inits tetrahedron element
|
||||||
SUBROUTINE initVolTetra3DCart(self, n, p)
|
SUBROUTINE initVolTetra3DCart(self, n, p, nodes)
|
||||||
USE moduleRefParam
|
USE moduleRefParam
|
||||||
IMPLICIT NONE
|
IMPLICIT NONE
|
||||||
|
|
||||||
CLASS(meshVol3DCartTetra), INTENT(out):: self
|
CLASS(meshVol3DCartTetra), INTENT(out):: self
|
||||||
INTEGER, INTENT(in):: n
|
INTEGER, INTENT(in):: n
|
||||||
INTEGER, INTENT(in):: p(:)
|
INTEGER, INTENT(in):: p(:)
|
||||||
|
TYPE(meshNodeCont), INTENT(in), TARGET:: nodes(:)
|
||||||
REAL(8), DIMENSION(1:3):: r1, r2, r3, r4 !Positions of each node
|
REAL(8), DIMENSION(1:3):: r1, r2, r3, r4 !Positions of each node
|
||||||
REAL(8):: volNodes(1:4) !Volume of each node
|
REAL(8):: volNodes(1:4) !Volume of each node
|
||||||
|
|
||||||
self%n = n
|
self%n = n
|
||||||
self%n1 => mesh%nodes(p(1))%obj
|
self%n1 => nodes(p(1))%obj
|
||||||
self%n2 => mesh%nodes(p(2))%obj
|
self%n2 => nodes(p(2))%obj
|
||||||
self%n3 => mesh%nodes(p(3))%obj
|
self%n3 => nodes(p(3))%obj
|
||||||
self%n4 => mesh%nodes(p(4))%obj
|
self%n4 => nodes(p(4))%obj
|
||||||
!Get element coordinates
|
!Get element coordinates
|
||||||
r1 = self%n1%getCoordinates()
|
r1 = self%n1%getCoordinates()
|
||||||
r2 = self%n2%getCoordinates()
|
r2 = self%n2%getCoordinates()
|
||||||
|
|
@ -417,23 +418,25 @@ MODULE moduleMesh3DCart
|
||||||
|
|
||||||
END SUBROUTINE partialDerTetra
|
END SUBROUTINE partialDerTetra
|
||||||
|
|
||||||
PURE FUNCTION elemKTetra(self) RESULT(ke)
|
PURE FUNCTION elemKTetra(self) RESULT(localK)
|
||||||
IMPLICIT NONE
|
IMPLICIT NONE
|
||||||
|
|
||||||
CLASS(meshVol3DCartTetra), INTENT(in):: self
|
CLASS(meshVol3DCartTetra), INTENT(in):: self
|
||||||
|
REAL(8), ALLOCATABLE:: localK(:,:)
|
||||||
REAL(8):: xii(1:3)
|
REAL(8):: xii(1:3)
|
||||||
REAL(8):: fPsi(1:4), dPsi(1:3, 1:4)
|
REAL(8):: fPsi(1:4), dPsi(1:3, 1:4)
|
||||||
REAL(8):: ke(1:4,1:4)
|
|
||||||
REAL(8):: invJ(1:3,1:3), detJ
|
REAL(8):: invJ(1:3,1:3), detJ
|
||||||
|
|
||||||
|
ALLOCATE(localK(1:4,1:4))
|
||||||
|
localK = 0.D0
|
||||||
|
xii = 0.D0
|
||||||
!TODO: One point Gauss integral. Upgrade when possible
|
!TODO: One point Gauss integral. Upgrade when possible
|
||||||
ke = 0.D0
|
|
||||||
xii = (/ 0.25D0, 0.25D0, 0.25D0 /)
|
xii = (/ 0.25D0, 0.25D0, 0.25D0 /)
|
||||||
dPsi = self%dPsi(xii)
|
dPsi = self%dPsi(xii)
|
||||||
detJ = self%detJac(xii, dPsi)
|
detJ = self%detJac(xii, dPsi)
|
||||||
invJ = self%invJac(xii, dPsi)
|
invJ = self%invJac(xii, dPsi)
|
||||||
fPsi = self%fPsi(xii)
|
fPsi = self%fPsi(xii)
|
||||||
ke = ke + MATMUL(TRANSPOSE(MATMUL(invJ,dPsi)),MATMUL(invJ,dPsi))*1.D0/detJ
|
localK = MATMUL(TRANSPOSE(MATMUL(invJ,dPsi)),MATMUL(invJ,dPsi))*1.D0/detJ
|
||||||
|
|
||||||
END FUNCTION elemKTetra
|
END FUNCTION elemKTetra
|
||||||
|
|
||||||
|
|
@ -456,7 +459,7 @@ MODULE moduleMesh3DCart
|
||||||
detJ = self%detJac(xii, dPsi)
|
detJ = self%detJac(xii, dPsi)
|
||||||
fPsi = self%fPsi(xii)
|
fPsi = self%fPsi(xii)
|
||||||
f = DOT_PRODUCT(fPsi, source)
|
f = DOT_PRODUCT(fPsi, source)
|
||||||
localF = localF + f*fPsi*1.D0*detJ
|
localF = f*fPsi*1.D0*detJ
|
||||||
|
|
||||||
END FUNCTION elemFTetra
|
END FUNCTION elemFTetra
|
||||||
|
|
||||||
|
|
@ -496,22 +499,22 @@ MODULE moduleMesh3DCart
|
||||||
w_p = self%weight(part%xi)
|
w_p = self%weight(part%xi)
|
||||||
tensorS = outerProduct(part%v, part%v)
|
tensorS = outerProduct(part%v, part%v)
|
||||||
|
|
||||||
vertex => self%n1%output(part%sp)
|
vertex => self%n1%output(part%species%n)
|
||||||
vertex%den = vertex%den + part%weight*w_p(1)
|
vertex%den = vertex%den + part%weight*w_p(1)
|
||||||
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(1)*part%v(:)
|
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(1)*part%v(:)
|
||||||
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(1)*tensorS
|
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(1)*tensorS
|
||||||
|
|
||||||
vertex => self%n2%output(part%sp)
|
vertex => self%n2%output(part%species%n)
|
||||||
vertex%den = vertex%den + part%weight*w_p(2)
|
vertex%den = vertex%den + part%weight*w_p(2)
|
||||||
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(2)*part%v(:)
|
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(2)*part%v(:)
|
||||||
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(2)*tensorS
|
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(2)*tensorS
|
||||||
|
|
||||||
vertex => self%n3%output(part%sp)
|
vertex => self%n3%output(part%species%n)
|
||||||
vertex%den = vertex%den + part%weight*w_p(3)
|
vertex%den = vertex%den + part%weight*w_p(3)
|
||||||
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(3)*part%v(:)
|
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(3)*part%v(:)
|
||||||
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(3)*tensorS
|
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(3)*tensorS
|
||||||
|
|
||||||
vertex => self%n4%output(part%sp)
|
vertex => self%n4%output(part%species%n)
|
||||||
vertex%den = vertex%den + part%weight*w_p(4)
|
vertex%den = vertex%den + part%weight*w_p(4)
|
||||||
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(4)*part%v(:)
|
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(4)*part%v(:)
|
||||||
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(4)*tensorS
|
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(4)*tensorS
|
||||||
|
|
@ -579,7 +582,7 @@ MODULE moduleMesh3DCart
|
||||||
|
|
||||||
CLASS(meshVol3DCartTetra), INTENT(in):: self
|
CLASS(meshVol3DCartTetra), INTENT(in):: self
|
||||||
REAL(8), INTENT(in):: xi(1:3)
|
REAL(8), INTENT(in):: xi(1:3)
|
||||||
CLASS(*), POINTER, INTENT(out):: nextElement
|
CLASS(meshElement), POINTER, INTENT(out):: nextElement
|
||||||
REAL(8):: xiArray(1:4)
|
REAL(8):: xiArray(1:4)
|
||||||
INTEGER:: nextInt
|
INTEGER:: nextInt
|
||||||
|
|
||||||
|
|
@ -662,5 +665,373 @@ MODULE moduleMesh3DCart
|
||||||
|
|
||||||
END FUNCTION invJ3DCart
|
END FUNCTION invJ3DCart
|
||||||
|
|
||||||
|
!Selects type of elements to build connection
|
||||||
|
SUBROUTINE connectVolVol(elemA, elemB)
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
CLASS(meshVol), INTENT(inout):: elemA
|
||||||
|
CLASS(meshVol), INTENT(inout):: elemB
|
||||||
|
|
||||||
|
SELECT TYPE(elemA)
|
||||||
|
TYPE IS(meshVol3DCartTetra)
|
||||||
|
!Element A is a tetrahedron
|
||||||
|
SELECT TYPE(elemB)
|
||||||
|
TYPE IS(meshVol3DCartTetra)
|
||||||
|
!Element B is a tetrahedron
|
||||||
|
CALL connectTetraTetra(elemA, elemB)
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
END SUBROUTINE connectVolVol
|
||||||
|
|
||||||
|
SUBROUTINE connectVolEdge(elemA, elemB)
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
CLASS(meshVol), INTENT(inout):: elemA
|
||||||
|
CLASS(meshEdge), INTENT(inout):: elemB
|
||||||
|
|
||||||
|
SELECT TYPE(elemB)
|
||||||
|
CLASS IS(meshEdge3DCartTria)
|
||||||
|
SELECT TYPE(elemA)
|
||||||
|
TYPE IS(meshVol3DCartTetra)
|
||||||
|
!Element A is a tetrahedron
|
||||||
|
CALL connectTetraEdge(elemA, elemB)
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
END SUBROUTINE connectVolEdge
|
||||||
|
|
||||||
|
SUBROUTINE connectMesh3DCart(self)
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
CLASS(meshGeneric), INTENT(inout):: self
|
||||||
|
INTEGER:: e, et
|
||||||
|
|
||||||
|
DO e = 1, self%numVols
|
||||||
|
!Connect Vol-Vol
|
||||||
|
DO et = 1, self%numVols
|
||||||
|
IF (e /= et) THEN
|
||||||
|
CALL connectVolVol(self%vols(e)%obj, self%vols(et)%obj)
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END DO
|
||||||
|
|
||||||
|
SELECT TYPE(self)
|
||||||
|
TYPE IS(meshParticles)
|
||||||
|
!Connect Vol-Edge
|
||||||
|
DO et = 1, self%numEdges
|
||||||
|
CALL connectVolEdge(self%vols(e)%obj, self%edges(et)%obj)
|
||||||
|
|
||||||
|
END DO
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
END DO
|
||||||
|
|
||||||
|
END SUBROUTINE connectMesh3DCart
|
||||||
|
|
||||||
|
!Checks if two sets of nodes are coincidend in any order
|
||||||
|
PURE FUNCTION coincidentNodes(nodesA, nodesB) RESULT(coincident)
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
INTEGER, DIMENSION(1:3), INTENT(in):: nodesA, nodesB
|
||||||
|
LOGICAL:: coincident
|
||||||
|
INTEGER:: i
|
||||||
|
|
||||||
|
coincident = .FALSE.
|
||||||
|
DO i = 1, 3
|
||||||
|
IF (ANY(nodesA(i) == nodesB)) THEN
|
||||||
|
coincident = .TRUE.
|
||||||
|
|
||||||
|
ELSE
|
||||||
|
coincident = .FALSE.
|
||||||
|
EXIT
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END DO
|
||||||
|
|
||||||
|
END FUNCTION coincidentNodes
|
||||||
|
|
||||||
|
SUBROUTINE connectTetraTetra(elemA, elemB)
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
CLASS(meshVol3DCartTetra), INTENT(inout), TARGET:: elemA
|
||||||
|
CLASS(meshVol3DCartTetra), INTENT(inout), TARGET:: elemB
|
||||||
|
|
||||||
|
!Check surface 1
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e1)) THEN
|
||||||
|
IF (coincidentNodes((/elemA%n1%n, elemA%n2%n, elemA%n3%n/), &
|
||||||
|
(/elemB%n1%n, elemB%n2%n, elemB%n3%n/))) THEN
|
||||||
|
|
||||||
|
elemA%e1 => elemB
|
||||||
|
elemB%e1 => elemA
|
||||||
|
|
||||||
|
ELSEIF (coincidentNodes((/elemA%n1%n, elemA%n2%n, elemA%n3%n/), &
|
||||||
|
(/elemB%n2%n, elemB%n3%n, elemB%n4%n/))) THEN
|
||||||
|
|
||||||
|
elemA%e1 => elemB
|
||||||
|
elemB%e2 => elemA
|
||||||
|
|
||||||
|
ELSEIF (coincidentNodes((/elemA%n1%n, elemA%n2%n, elemA%n3%n/), &
|
||||||
|
(/elemB%n1%n, elemB%n2%n, elemB%n4%n/))) THEN
|
||||||
|
|
||||||
|
elemA%e1 => elemB
|
||||||
|
elemB%e3 => elemA
|
||||||
|
|
||||||
|
ELSEIF (coincidentNodes((/elemA%n1%n, elemA%n2%n, elemA%n3%n/), &
|
||||||
|
(/elemB%n1%n, elemB%n3%n, elemB%n4%n/))) THEN
|
||||||
|
|
||||||
|
elemA%e1 => elemB
|
||||||
|
elemB%e4 => elemA
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
!Check surface 2
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e2)) THEN
|
||||||
|
IF (coincidentNodes((/elemA%n2%n, elemA%n3%n, elemA%n4%n/), &
|
||||||
|
(/elemB%n1%n, elemB%n2%n, elemB%n3%n/))) THEN
|
||||||
|
|
||||||
|
elemA%e2 => elemB
|
||||||
|
elemB%e1 => elemA
|
||||||
|
|
||||||
|
ELSEIF (coincidentNodes((/elemA%n2%n, elemA%n3%n, elemA%n4%n/), &
|
||||||
|
(/elemB%n2%n, elemB%n3%n, elemB%n4%n/))) THEN
|
||||||
|
|
||||||
|
elemA%e2 => elemB
|
||||||
|
elemB%e2 => elemA
|
||||||
|
|
||||||
|
ELSEIF (coincidentNodes((/elemA%n2%n, elemA%n3%n, elemA%n4%n/), &
|
||||||
|
(/elemB%n1%n, elemB%n2%n, elemB%n4%n/))) THEN
|
||||||
|
|
||||||
|
elemA%e2 => elemB
|
||||||
|
elemB%e3 => elemA
|
||||||
|
|
||||||
|
ELSEIF (coincidentNodes((/elemA%n2%n, elemA%n3%n, elemA%n4%n/), &
|
||||||
|
(/elemB%n1%n, elemB%n3%n, elemB%n4%n/))) THEN
|
||||||
|
|
||||||
|
elemA%e2 => elemB
|
||||||
|
elemB%e4 => elemA
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
!Check surface 3
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e3)) THEN
|
||||||
|
IF (coincidentNodes((/elemA%n1%n, elemA%n2%n, elemA%n4%n/), &
|
||||||
|
(/elemB%n1%n, elemB%n2%n, elemB%n3%n/))) THEN
|
||||||
|
|
||||||
|
elemA%e3 => elemB
|
||||||
|
elemB%e1 => elemA
|
||||||
|
|
||||||
|
ELSEIF (coincidentNodes((/elemA%n1%n, elemA%n2%n, elemA%n4%n/), &
|
||||||
|
(/elemB%n2%n, elemB%n3%n, elemB%n4%n/))) THEN
|
||||||
|
|
||||||
|
elemA%e3 => elemB
|
||||||
|
elemB%e2 => elemA
|
||||||
|
|
||||||
|
ELSEIF (coincidentNodes((/elemA%n1%n, elemA%n2%n, elemA%n4%n/), &
|
||||||
|
(/elemB%n1%n, elemB%n2%n, elemB%n4%n/))) THEN
|
||||||
|
|
||||||
|
elemA%e3 => elemB
|
||||||
|
elemB%e3 => elemA
|
||||||
|
|
||||||
|
ELSEIF (coincidentNodes((/elemA%n1%n, elemA%n2%n, elemA%n4%n/), &
|
||||||
|
(/elemB%n1%n, elemB%n3%n, elemB%n4%n/))) THEN
|
||||||
|
|
||||||
|
elemA%e3 => elemB
|
||||||
|
elemB%e4 => elemA
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
!Check surface 4
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e4)) THEN
|
||||||
|
IF (coincidentNodes((/elemA%n1%n, elemA%n3%n, elemA%n4%n/), &
|
||||||
|
(/elemB%n1%n, elemB%n2%n, elemB%n3%n/))) THEN
|
||||||
|
|
||||||
|
elemA%e4 => elemB
|
||||||
|
elemB%e1 => elemA
|
||||||
|
|
||||||
|
ELSEIF (coincidentNodes((/elemA%n1%n, elemA%n3%n, elemA%n4%n/), &
|
||||||
|
(/elemB%n2%n, elemB%n3%n, elemB%n4%n/))) THEN
|
||||||
|
|
||||||
|
elemA%e4 => elemB
|
||||||
|
elemB%e2 => elemA
|
||||||
|
|
||||||
|
ELSEIF (coincidentNodes((/elemA%n1%n, elemA%n3%n, elemA%n4%n/), &
|
||||||
|
(/elemB%n1%n, elemB%n2%n, elemB%n4%n/))) THEN
|
||||||
|
|
||||||
|
elemA%e4 => elemB
|
||||||
|
elemB%e3 => elemA
|
||||||
|
|
||||||
|
ELSEIF (coincidentNodes((/elemA%n1%n, elemA%n3%n, elemA%n4%n/), &
|
||||||
|
(/elemB%n1%n, elemB%n3%n, elemB%n4%n/))) THEN
|
||||||
|
|
||||||
|
elemA%e4 => elemB
|
||||||
|
elemB%e4 => elemA
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END SUBROUTINE connectTetraTetra
|
||||||
|
|
||||||
|
SUBROUTINE connectTetraEdge(elemA, elemB)
|
||||||
|
USE moduleMath
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
CLASS(meshVol3DCartTetra), INTENT(inout), TARGET:: elemA
|
||||||
|
CLASS(meshEdge3DCartTria), INTENT(inout), TARGET:: elemB
|
||||||
|
INTEGER:: nodesEdge(1:3)
|
||||||
|
REAL(8), DIMENSION(1:3):: vec1, vec2
|
||||||
|
REAL(8):: normVol(1:3)
|
||||||
|
|
||||||
|
nodesEdge = (/ elemB%n1%n, elemB%n2%n, elemB%n3%n /)
|
||||||
|
|
||||||
|
!Check surface 1
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e1)) THEN
|
||||||
|
IF (coincidentNodes((/elemA%n1%n, elemA%n2%n, elema%n3%n/), &
|
||||||
|
nodesEdge)) THEN
|
||||||
|
|
||||||
|
vec1 = (/ elemA%x(2) - elemA%x(1), &
|
||||||
|
elemA%y(2) - elemA%y(1), &
|
||||||
|
elemA%z(2) - elemA%z(1) /)
|
||||||
|
vec2 = (/ elemA%x(3) - elemA%x(1), &
|
||||||
|
elemA%y(3) - elemA%y(1), &
|
||||||
|
elemA%z(3) - elemA%z(1) /)
|
||||||
|
normVol = crossProduct(vec1, vec2)
|
||||||
|
normVol = normalize(normVol)
|
||||||
|
|
||||||
|
IF (DOT_PRODUCT(elemB%normal, normVol) == -1.D0) THEN
|
||||||
|
|
||||||
|
elemA%e1 => elemB
|
||||||
|
elemB%e1 => elemA
|
||||||
|
|
||||||
|
ELSE
|
||||||
|
|
||||||
|
elemA%e1 => elemB
|
||||||
|
elemB%e2 => elemA
|
||||||
|
|
||||||
|
!Revers the normal to point inside the domain
|
||||||
|
elemB%normal = -elemB%normal
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
!Check surface 2
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e2)) THEN
|
||||||
|
IF (coincidentNodes((/elemA%n2%n, elemA%n3%n, elemA%n4%n/), &
|
||||||
|
nodesEdge)) THEN
|
||||||
|
|
||||||
|
vec1 = (/ elemA%x(3) - elemA%x(2), &
|
||||||
|
elemA%y(3) - elemA%y(2), &
|
||||||
|
elemA%z(3) - elemA%z(2) /)
|
||||||
|
vec2 = (/ elemA%x(4) - elemA%x(2), &
|
||||||
|
elemA%y(4) - elemA%y(2), &
|
||||||
|
elemA%z(4) - elemA%z(2) /)
|
||||||
|
normVol = crossProduct(vec1, vec2)
|
||||||
|
normVol = normalize(normVol)
|
||||||
|
|
||||||
|
IF (DOT_PRODUCT(elemB%normal, normVol) == -1.D0) THEN
|
||||||
|
|
||||||
|
elemA%e2 => elemB
|
||||||
|
elemB%e1 => elemA
|
||||||
|
|
||||||
|
ELSE
|
||||||
|
|
||||||
|
elemA%e2 => elemB
|
||||||
|
elemB%e2 => elemA
|
||||||
|
|
||||||
|
!Revers the normal to point inside the domain
|
||||||
|
elemB%normal = -elemB%normal
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
!Check surface 3
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e3)) THEN
|
||||||
|
IF (coincidentNodes((/elemA%n1%n, elemA%n2%n, elema%n4%n/), &
|
||||||
|
nodesEdge)) THEN
|
||||||
|
|
||||||
|
vec1 = (/ elemA%x(2) - elemA%x(1), &
|
||||||
|
elemA%y(2) - elemA%y(1), &
|
||||||
|
elemA%z(2) - elemA%z(1) /)
|
||||||
|
vec2 = (/ elemA%x(4) - elemA%x(1), &
|
||||||
|
elemA%y(4) - elemA%y(1), &
|
||||||
|
elemA%z(4) - elemA%z(1) /)
|
||||||
|
normVol = crossProduct(vec1, vec2)
|
||||||
|
normVol = normalize(normVol)
|
||||||
|
|
||||||
|
IF (DOT_PRODUCT(elemB%normal, normVol) == -1.D0) THEN
|
||||||
|
|
||||||
|
elemA%e3 => elemB
|
||||||
|
elemB%e1 => elemA
|
||||||
|
|
||||||
|
ELSE
|
||||||
|
|
||||||
|
elemA%e3 => elemB
|
||||||
|
elemB%e2 => elemA
|
||||||
|
|
||||||
|
!Revers the normal to point inside the domain
|
||||||
|
elemB%normal = -elemB%normal
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
!Check surface 4
|
||||||
|
IF (.NOT. ASSOCIATED(elemA%e4)) THEN
|
||||||
|
IF (coincidentNodes((/elemA%n1%n, elemA%n3%n, elema%n4%n/), &
|
||||||
|
nodesEdge)) THEN
|
||||||
|
|
||||||
|
vec1 = (/ elemA%x(3) - elemA%x(1), &
|
||||||
|
elemA%y(3) - elemA%y(1), &
|
||||||
|
elemA%z(3) - elemA%z(1) /)
|
||||||
|
vec2 = (/ elemA%x(4) - elemA%x(1), &
|
||||||
|
elemA%y(4) - elemA%y(1), &
|
||||||
|
elemA%z(4) - elemA%z(1) /)
|
||||||
|
normVol = crossProduct(vec1, vec2)
|
||||||
|
normVol = normalize(normVol)
|
||||||
|
|
||||||
|
IF (DOT_PRODUCT(elemB%normal, normVol) == -1.D0) THEN
|
||||||
|
|
||||||
|
elemA%e4 => elemB
|
||||||
|
elemB%e1 => elemA
|
||||||
|
|
||||||
|
|
||||||
|
ELSE
|
||||||
|
|
||||||
|
elemA%e4 => elemB
|
||||||
|
elemB%e2 => elemA
|
||||||
|
|
||||||
|
!Revers the normal to point inside the domain
|
||||||
|
elemB%normal = -elemB%normal
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END SUBROUTINE connectTetraEdge
|
||||||
|
|
||||||
END MODULE moduleMesh3DCart
|
END MODULE moduleMesh3DCart
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,544 +0,0 @@
|
||||||
MODULE moduleMesh3DCartRead
|
|
||||||
USE moduleMesh
|
|
||||||
USE moduleMesh3DCart
|
|
||||||
|
|
||||||
TYPE, EXTENDS(meshGeneric):: mesh3DCartGeneric
|
|
||||||
CONTAINS
|
|
||||||
PROCEDURE, PASS:: init => init3DCartMesh
|
|
||||||
PROCEDURE, PASS:: readMesh => readMesh3DCartGmsh
|
|
||||||
|
|
||||||
END TYPE
|
|
||||||
|
|
||||||
INTERFACE connected
|
|
||||||
MODULE PROCEDURE connectedVolVol, connectedVolEdge
|
|
||||||
|
|
||||||
END INTERFACE connected
|
|
||||||
|
|
||||||
CONTAINS
|
|
||||||
!Init mesh
|
|
||||||
SUBROUTINE init3DCartMesh(self, meshFormat)
|
|
||||||
USE moduleMesh
|
|
||||||
USE moduleErrors
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
CLASS(mesh3DCartGeneric), INTENT(out):: self
|
|
||||||
CHARACTER(:), ALLOCATABLE, INTENT(in):: meshFormat
|
|
||||||
|
|
||||||
SELECT CASE(meshFormat)
|
|
||||||
CASE ("gmsh")
|
|
||||||
self%printOutput => printOutputGmsh
|
|
||||||
self%printColl => printCollGmsh
|
|
||||||
self%printEM => printEMGmsh
|
|
||||||
|
|
||||||
CASE DEFAULT
|
|
||||||
CALL criticalError("Mesh type " // meshFormat // " not supported.", "init3DCartMesh")
|
|
||||||
|
|
||||||
END SELECT
|
|
||||||
|
|
||||||
END SUBROUTINE init3DCartMesh
|
|
||||||
|
|
||||||
!Read mesh from gmsh file
|
|
||||||
SUBROUTINE readMesh3DCartGmsh(self, filename)
|
|
||||||
USE moduleBoundary
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
CLASS(mesh3DCartGeneric), INTENT(inout):: self
|
|
||||||
CHARACTER(:), ALLOCATABLE, INTENT(in):: filename
|
|
||||||
REAL(8):: x, y, z
|
|
||||||
INTEGER:: p(1:4)
|
|
||||||
INTEGER:: e = 0, et = 0, n = 0, eTemp = 0, elemType = 0, bt = 0
|
|
||||||
INTEGER:: totalNumElem
|
|
||||||
INTEGER:: boundaryType
|
|
||||||
|
|
||||||
!Read mesh
|
|
||||||
OPEN(10, FILE=TRIM(filename))
|
|
||||||
!Skip header
|
|
||||||
READ(10, *)
|
|
||||||
READ(10, *)
|
|
||||||
READ(10, *)
|
|
||||||
READ(10, *)
|
|
||||||
!Read number of nodes
|
|
||||||
READ(10, *) self%numNodes
|
|
||||||
!Allocate required matrices and vectors
|
|
||||||
ALLOCATE(self%nodes(1:self%numNodes))
|
|
||||||
ALLOCATE(self%K(1:self%numNodes, 1:self%numNodes))
|
|
||||||
ALLOCATE(self%IPIV(1:self%numNodes, 1:self%numNodes))
|
|
||||||
self%K = 0.D0
|
|
||||||
self%IPIV = 0
|
|
||||||
|
|
||||||
!Read node cartesian coordinates (x = x, y = y, z = z)
|
|
||||||
DO e = 1, self%numNodes
|
|
||||||
READ(10, *) n, x, y, z
|
|
||||||
ALLOCATE(meshNode3Dcart::self%nodes(n)%obj)
|
|
||||||
CALL self%nodes(n)%obj%init(n, (/x, y, z /))
|
|
||||||
|
|
||||||
END DO
|
|
||||||
|
|
||||||
!Skip comments
|
|
||||||
READ(10, *)
|
|
||||||
READ(10, *)
|
|
||||||
|
|
||||||
!Reads total number of elements
|
|
||||||
READ(10, *) totalNumElem
|
|
||||||
!conts edges and volume elements
|
|
||||||
self%numEdges = 0
|
|
||||||
DO e = 1, totalNumElem
|
|
||||||
READ(10, *) eTemp, elemType
|
|
||||||
IF (elemType == 2) THEN
|
|
||||||
self%numEdges = e
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END DO
|
|
||||||
|
|
||||||
!Substract the number of edges to the total number of elements to obtain the number
|
|
||||||
!of volume elements
|
|
||||||
self%numVols = totalNumElem - self%numEdges
|
|
||||||
|
|
||||||
!Allocate required arrays
|
|
||||||
ALLOCATE(self%edges(1:self%numEdges))
|
|
||||||
ALLOCATE(self%vols(1:self%numVols))
|
|
||||||
|
|
||||||
!Go back to the beggining to read each specific element
|
|
||||||
DO e = 1, totalNumElem
|
|
||||||
BACKSPACE(10)
|
|
||||||
|
|
||||||
END DO
|
|
||||||
|
|
||||||
!Reads surfaces
|
|
||||||
DO e = 1, self%numEdges
|
|
||||||
READ(10, *) n, elemType
|
|
||||||
BACKSPACE(10)
|
|
||||||
|
|
||||||
SELECT CASE(elemType)
|
|
||||||
CASE(2)
|
|
||||||
!Triangular surface
|
|
||||||
READ(10, *) n, elemType, eTemp, boundaryType, eTemp, p(1:3)
|
|
||||||
bt = getBoundaryID(boundaryType)
|
|
||||||
|
|
||||||
ALLOCATE(meshEdge3DCartTria:: self%edges(e)%obj)
|
|
||||||
|
|
||||||
CALL self%edges(e)%obj%init(n, p(1:3), bt, boundaryType)
|
|
||||||
|
|
||||||
END SELECT
|
|
||||||
|
|
||||||
END DO
|
|
||||||
|
|
||||||
!Read and initialize volumes
|
|
||||||
DO e = 1, self%numVols
|
|
||||||
READ(10, *) n, elemType
|
|
||||||
BACKSPACE(10)
|
|
||||||
|
|
||||||
SELECT CASE(elemType)
|
|
||||||
CASE(4)
|
|
||||||
!Tetrahedron element
|
|
||||||
READ(10, *) n, elemType, eTemp, eTemp, eTemp, p(1:4)
|
|
||||||
ALLOCATE(meshVol3DCartTetra:: self%vols(e)%obj)
|
|
||||||
CALL self%vols(e)%obj%init(n - self%numEdges, p(1:4))
|
|
||||||
|
|
||||||
END SELECT
|
|
||||||
|
|
||||||
END DO
|
|
||||||
|
|
||||||
CLOSE(10)
|
|
||||||
|
|
||||||
!Build connectivy between elements
|
|
||||||
DO e = 1, self%numVols
|
|
||||||
!Connectivity between volumes
|
|
||||||
DO et = 1, self%numVols
|
|
||||||
IF (e /= et) THEN
|
|
||||||
CALL connected(self%vols(e)%obj, self%vols(et)%obj)
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END DO
|
|
||||||
|
|
||||||
!Connectivity between vols and surfaces
|
|
||||||
DO et = 1, self%numEdges
|
|
||||||
CALL connected(self%vols(e)%obj, self%edges(et)%obj)
|
|
||||||
|
|
||||||
END DO
|
|
||||||
|
|
||||||
!Constructs the global K matrix
|
|
||||||
CALL constructGlobalK(self%K, self%vols(e)%obj)
|
|
||||||
|
|
||||||
END DO
|
|
||||||
|
|
||||||
END SUBROUTINE readMesh3DCartGmsh
|
|
||||||
|
|
||||||
!Selects type of elements to build connection
|
|
||||||
SUBROUTINE connectedVolVol(elemA, elemB)
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
CLASS(meshVol), INTENT(inout):: elemA
|
|
||||||
CLASS(meshVol), INTENT(inout):: elemB
|
|
||||||
|
|
||||||
SELECT TYPE(elemA)
|
|
||||||
TYPE IS(meshVol3DCartTetra)
|
|
||||||
!Element A is a tetrahedron
|
|
||||||
SELECT TYPE(elemB)
|
|
||||||
TYPE IS(meshVol3DCartTetra)
|
|
||||||
!Element B is a tetrahedron
|
|
||||||
CALL connectedTetraTetra(elemA, elemB)
|
|
||||||
|
|
||||||
END SELECT
|
|
||||||
|
|
||||||
END SELECT
|
|
||||||
|
|
||||||
END SUBROUTINE connectedVolVol
|
|
||||||
|
|
||||||
|
|
||||||
SUBROUTINE connectedVolEdge(elemA, elemB)
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
CLASS(meshVol), INTENT(inout):: elemA
|
|
||||||
CLASS(meshEdge), INTENT(inout):: elemB
|
|
||||||
|
|
||||||
SELECT TYPE(elemB)
|
|
||||||
CLASS IS(meshEdge3DCartTria)
|
|
||||||
SELECT TYPE(elemA)
|
|
||||||
TYPE IS(meshVol3DCartTetra)
|
|
||||||
!Element A is a tetrahedron
|
|
||||||
CALL connectedTetraEdge(elemA, elemB)
|
|
||||||
|
|
||||||
END SELECT
|
|
||||||
|
|
||||||
END SELECT
|
|
||||||
|
|
||||||
END SUBROUTINE connectedVolEdge
|
|
||||||
|
|
||||||
PURE FUNCTION coincidentNodes(nodesA, nodesB) RESULT(coincident)
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
INTEGER, DIMENSION(1:3), INTENT(in):: nodesA, nodesB
|
|
||||||
LOGICAL:: coincident
|
|
||||||
INTEGER:: i
|
|
||||||
|
|
||||||
coincident = .FALSE.
|
|
||||||
DO i = 1, 3
|
|
||||||
IF (ANY(nodesA(i) == nodesB)) THEN
|
|
||||||
coincident = .TRUE.
|
|
||||||
|
|
||||||
ELSE
|
|
||||||
coincident = .FALSE.
|
|
||||||
EXIT
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END DO
|
|
||||||
|
|
||||||
END FUNCTION coincidentNodes
|
|
||||||
|
|
||||||
SUBROUTINE connectedTetraTetra(elemA, elemB)
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
CLASS(meshVol3DCartTetra), INTENT(inout), TARGET:: elemA
|
|
||||||
CLASS(meshVol3DCartTetra), INTENT(inout), TARGET:: elemB
|
|
||||||
|
|
||||||
!TODO: Try to find a much clear way to do this
|
|
||||||
|
|
||||||
!Check surface 1
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e1)) THEN
|
|
||||||
IF (coincidentNodes((/elemA%n1%n, elemA%n2%n, elemA%n3%n/), &
|
|
||||||
(/elemB%n1%n, elemB%n2%n, elemB%n3%n/))) THEN
|
|
||||||
|
|
||||||
elemA%e1 => elemB
|
|
||||||
elemB%e1 => elemA
|
|
||||||
|
|
||||||
ELSEIF (coincidentNodes((/elemA%n1%n, elemA%n2%n, elemA%n3%n/), &
|
|
||||||
(/elemB%n2%n, elemB%n3%n, elemB%n4%n/))) THEN
|
|
||||||
|
|
||||||
elemA%e1 => elemB
|
|
||||||
elemB%e2 => elemA
|
|
||||||
|
|
||||||
ELSEIF (coincidentNodes((/elemA%n1%n, elemA%n2%n, elemA%n3%n/), &
|
|
||||||
(/elemB%n1%n, elemB%n2%n, elemB%n4%n/))) THEN
|
|
||||||
|
|
||||||
elemA%e1 => elemB
|
|
||||||
elemB%e3 => elemA
|
|
||||||
|
|
||||||
ELSEIF (coincidentNodes((/elemA%n1%n, elemA%n2%n, elemA%n3%n/), &
|
|
||||||
(/elemB%n1%n, elemB%n3%n, elemB%n4%n/))) THEN
|
|
||||||
|
|
||||||
elemA%e1 => elemB
|
|
||||||
elemB%e4 => elemA
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
!Check surface 2
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e2)) THEN
|
|
||||||
IF (coincidentNodes((/elemA%n2%n, elemA%n3%n, elemA%n4%n/), &
|
|
||||||
(/elemB%n1%n, elemB%n2%n, elemB%n3%n/))) THEN
|
|
||||||
|
|
||||||
elemA%e2 => elemB
|
|
||||||
elemB%e1 => elemA
|
|
||||||
|
|
||||||
ELSEIF (coincidentNodes((/elemA%n2%n, elemA%n3%n, elemA%n4%n/), &
|
|
||||||
(/elemB%n2%n, elemB%n3%n, elemB%n4%n/))) THEN
|
|
||||||
|
|
||||||
elemA%e2 => elemB
|
|
||||||
elemB%e2 => elemA
|
|
||||||
|
|
||||||
ELSEIF (coincidentNodes((/elemA%n2%n, elemA%n3%n, elemA%n4%n/), &
|
|
||||||
(/elemB%n1%n, elemB%n2%n, elemB%n4%n/))) THEN
|
|
||||||
|
|
||||||
elemA%e2 => elemB
|
|
||||||
elemB%e3 => elemA
|
|
||||||
|
|
||||||
ELSEIF (coincidentNodes((/elemA%n2%n, elemA%n3%n, elemA%n4%n/), &
|
|
||||||
(/elemB%n1%n, elemB%n3%n, elemB%n4%n/))) THEN
|
|
||||||
|
|
||||||
elemA%e2 => elemB
|
|
||||||
elemB%e4 => elemA
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
!Check surface 3
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e3)) THEN
|
|
||||||
IF (coincidentNodes((/elemA%n1%n, elemA%n2%n, elemA%n4%n/), &
|
|
||||||
(/elemB%n1%n, elemB%n2%n, elemB%n3%n/))) THEN
|
|
||||||
|
|
||||||
elemA%e3 => elemB
|
|
||||||
elemB%e1 => elemA
|
|
||||||
|
|
||||||
ELSEIF (coincidentNodes((/elemA%n1%n, elemA%n2%n, elemA%n4%n/), &
|
|
||||||
(/elemB%n2%n, elemB%n3%n, elemB%n4%n/))) THEN
|
|
||||||
|
|
||||||
elemA%e3 => elemB
|
|
||||||
elemB%e2 => elemA
|
|
||||||
|
|
||||||
ELSEIF (coincidentNodes((/elemA%n1%n, elemA%n2%n, elemA%n4%n/), &
|
|
||||||
(/elemB%n1%n, elemB%n2%n, elemB%n4%n/))) THEN
|
|
||||||
|
|
||||||
elemA%e3 => elemB
|
|
||||||
elemB%e3 => elemA
|
|
||||||
|
|
||||||
ELSEIF (coincidentNodes((/elemA%n1%n, elemA%n2%n, elemA%n4%n/), &
|
|
||||||
(/elemB%n1%n, elemB%n3%n, elemB%n4%n/))) THEN
|
|
||||||
|
|
||||||
elemA%e3 => elemB
|
|
||||||
elemB%e4 => elemA
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
!Check surface 4
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e4)) THEN
|
|
||||||
IF (coincidentNodes((/elemA%n1%n, elemA%n3%n, elemA%n4%n/), &
|
|
||||||
(/elemB%n1%n, elemB%n2%n, elemB%n3%n/))) THEN
|
|
||||||
|
|
||||||
elemA%e4 => elemB
|
|
||||||
elemB%e1 => elemA
|
|
||||||
|
|
||||||
ELSEIF (coincidentNodes((/elemA%n1%n, elemA%n3%n, elemA%n4%n/), &
|
|
||||||
(/elemB%n2%n, elemB%n3%n, elemB%n4%n/))) THEN
|
|
||||||
|
|
||||||
elemA%e4 => elemB
|
|
||||||
elemB%e2 => elemA
|
|
||||||
|
|
||||||
ELSEIF (coincidentNodes((/elemA%n1%n, elemA%n3%n, elemA%n4%n/), &
|
|
||||||
(/elemB%n1%n, elemB%n2%n, elemB%n4%n/))) THEN
|
|
||||||
|
|
||||||
elemA%e4 => elemB
|
|
||||||
elemB%e3 => elemA
|
|
||||||
|
|
||||||
ELSEIF (coincidentNodes((/elemA%n1%n, elemA%n3%n, elemA%n4%n/), &
|
|
||||||
(/elemB%n1%n, elemB%n3%n, elemB%n4%n/))) THEN
|
|
||||||
|
|
||||||
elemA%e4 => elemB
|
|
||||||
elemB%e4 => elemA
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END SUBROUTINE connectedTetraTetra
|
|
||||||
|
|
||||||
SUBROUTINE connectedTetraEdge(elemA, elemB)
|
|
||||||
USE moduleMath
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
CLASS(meshVol3DCartTetra), INTENT(inout), TARGET:: elemA
|
|
||||||
CLASS(meshEdge3DCartTria), INTENT(inout), TARGET:: elemB
|
|
||||||
INTEGER:: nodesEdge(1:3)
|
|
||||||
REAL(8), DIMENSION(1:3):: vec1, vec2
|
|
||||||
REAL(8):: normVol(1:3)
|
|
||||||
|
|
||||||
nodesEdge = (/ elemB%n1%n, elemB%n2%n, elemB%n3%n /)
|
|
||||||
|
|
||||||
!Check surface 1
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e1)) THEN
|
|
||||||
IF (coincidentNodes((/elemA%n1%n, elemA%n2%n, elema%n3%n/), &
|
|
||||||
nodesEdge)) THEN
|
|
||||||
|
|
||||||
vec1 = (/ elemA%x(2) - elemA%x(1), &
|
|
||||||
elemA%y(2) - elemA%y(1), &
|
|
||||||
elemA%z(2) - elemA%z(1) /)
|
|
||||||
vec2 = (/ elemA%x(3) - elemA%x(1), &
|
|
||||||
elemA%y(3) - elemA%y(1), &
|
|
||||||
elemA%z(3) - elemA%z(1) /)
|
|
||||||
normVol = crossProduct(vec1, vec2)
|
|
||||||
normVol = normalize(normVol)
|
|
||||||
|
|
||||||
IF (DOT_PRODUCT(elemB%normal, normVol) == -1.D0) THEN
|
|
||||||
|
|
||||||
elemA%e1 => elemB
|
|
||||||
elemB%e1 => elemA
|
|
||||||
|
|
||||||
ELSE
|
|
||||||
|
|
||||||
elemA%e1 => elemB
|
|
||||||
elemB%e2 => elemA
|
|
||||||
|
|
||||||
!Revers the normal to point inside the domain
|
|
||||||
elemB%normal = -elemB%normal
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
!Check surface 2
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e2)) THEN
|
|
||||||
IF (coincidentNodes((/elemA%n2%n, elemA%n3%n, elemA%n4%n/), &
|
|
||||||
nodesEdge)) THEN
|
|
||||||
|
|
||||||
vec1 = (/ elemA%x(3) - elemA%x(2), &
|
|
||||||
elemA%y(3) - elemA%y(2), &
|
|
||||||
elemA%z(3) - elemA%z(2) /)
|
|
||||||
vec2 = (/ elemA%x(4) - elemA%x(2), &
|
|
||||||
elemA%y(4) - elemA%y(2), &
|
|
||||||
elemA%z(4) - elemA%z(2) /)
|
|
||||||
normVol = crossProduct(vec1, vec2)
|
|
||||||
normVol = normalize(normVol)
|
|
||||||
|
|
||||||
IF (DOT_PRODUCT(elemB%normal, normVol) == -1.D0) THEN
|
|
||||||
|
|
||||||
elemA%e2 => elemB
|
|
||||||
elemB%e1 => elemA
|
|
||||||
|
|
||||||
ELSE
|
|
||||||
|
|
||||||
elemA%e2 => elemB
|
|
||||||
elemB%e2 => elemA
|
|
||||||
|
|
||||||
!Revers the normal to point inside the domain
|
|
||||||
elemB%normal = -elemB%normal
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
!Check surface 3
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e3)) THEN
|
|
||||||
IF (coincidentNodes((/elemA%n1%n, elemA%n2%n, elema%n4%n/), &
|
|
||||||
nodesEdge)) THEN
|
|
||||||
|
|
||||||
vec1 = (/ elemA%x(2) - elemA%x(1), &
|
|
||||||
elemA%y(2) - elemA%y(1), &
|
|
||||||
elemA%z(2) - elemA%z(1) /)
|
|
||||||
vec2 = (/ elemA%x(4) - elemA%x(1), &
|
|
||||||
elemA%y(4) - elemA%y(1), &
|
|
||||||
elemA%z(4) - elemA%z(1) /)
|
|
||||||
normVol = crossProduct(vec1, vec2)
|
|
||||||
normVol = normalize(normVol)
|
|
||||||
|
|
||||||
IF (DOT_PRODUCT(elemB%normal, normVol) == -1.D0) THEN
|
|
||||||
|
|
||||||
elemA%e3 => elemB
|
|
||||||
elemB%e1 => elemA
|
|
||||||
|
|
||||||
ELSE
|
|
||||||
|
|
||||||
elemA%e3 => elemB
|
|
||||||
elemB%e2 => elemA
|
|
||||||
|
|
||||||
!Revers the normal to point inside the domain
|
|
||||||
elemB%normal = -elemB%normal
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
!Check surface 4
|
|
||||||
IF (.NOT. ASSOCIATED(elemA%e4)) THEN
|
|
||||||
IF (coincidentNodes((/elemA%n1%n, elemA%n3%n, elema%n4%n/), &
|
|
||||||
nodesEdge)) THEN
|
|
||||||
|
|
||||||
vec1 = (/ elemA%x(3) - elemA%x(1), &
|
|
||||||
elemA%y(3) - elemA%y(1), &
|
|
||||||
elemA%z(3) - elemA%z(1) /)
|
|
||||||
vec2 = (/ elemA%x(4) - elemA%x(1), &
|
|
||||||
elemA%y(4) - elemA%y(1), &
|
|
||||||
elemA%z(4) - elemA%z(1) /)
|
|
||||||
normVol = crossProduct(vec1, vec2)
|
|
||||||
normVol = normalize(normVol)
|
|
||||||
|
|
||||||
IF (DOT_PRODUCT(elemB%normal, normVol) == -1.D0) THEN
|
|
||||||
|
|
||||||
elemA%e4 => elemB
|
|
||||||
elemB%e1 => elemA
|
|
||||||
|
|
||||||
|
|
||||||
ELSE
|
|
||||||
|
|
||||||
elemA%e4 => elemB
|
|
||||||
elemB%e2 => elemA
|
|
||||||
|
|
||||||
!Revers the normal to point inside the domain
|
|
||||||
elemB%normal = -elemB%normal
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END SUBROUTINE connectedTetraEdge
|
|
||||||
|
|
||||||
SUBROUTINE constructGlobalK(K, elem)
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
REAL(8), INTENT(inout):: K(1:, 1:)
|
|
||||||
CLASS(meshVol), INTENT(in):: elem
|
|
||||||
REAL(8), ALLOCATABLE:: localK(:,:)
|
|
||||||
INTEGER:: nNodes, i, j
|
|
||||||
INTEGER, ALLOCATABLE:: n(:)
|
|
||||||
|
|
||||||
SELECT TYPE(elem)
|
|
||||||
TYPE IS(meshVol3DCartTetra)
|
|
||||||
nNodes = 4
|
|
||||||
ALLOCATE(localK(1:nNodes,1:nNodes))
|
|
||||||
localK = elem%elemK()
|
|
||||||
ALLOCATE(n(1:nNodes))
|
|
||||||
n = (/ elem%n1%n, elem%n2%n, &
|
|
||||||
elem%n3%n, elem%n4%n /)
|
|
||||||
|
|
||||||
CLASS DEFAULT
|
|
||||||
nNodes = 0
|
|
||||||
ALLOCATE(localK(1:1, 1:1))
|
|
||||||
localK = 0.D0
|
|
||||||
ALLOCATE(n(1:1))
|
|
||||||
n = 0
|
|
||||||
|
|
||||||
END SELECT
|
|
||||||
|
|
||||||
DO i = 1, nNodes
|
|
||||||
DO j = 1, nNodes
|
|
||||||
K(n(i), n(j)) = K(n(i), n(j)) + localK(i, j)
|
|
||||||
END DO
|
|
||||||
END DO
|
|
||||||
|
|
||||||
END SUBROUTINE constructGlobalK
|
|
||||||
|
|
||||||
END MODULE moduleMesh3DCartRead
|
|
||||||
7
src/modules/mesh/inout/gmsh2/makefile
Normal file
7
src/modules/mesh/inout/gmsh2/makefile
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
all: moduleMeshInputGmsh2.o moduleMeshOutputGmsh2.o
|
||||||
|
|
||||||
|
moduleMeshInputGmsh2.o: moduleMeshOutputGmsh2.o moduleMeshInputGmsh2.f90
|
||||||
|
$(FC) $(FCFLAGS) -c $(subst .o,.f90,$@) -o $(OBJDIR)/$@
|
||||||
|
|
||||||
|
%.o: %.f90
|
||||||
|
$(FC) $(FCFLAGS) -c $< -o $(OBJDIR)/$@
|
||||||
291
src/modules/mesh/inout/gmsh2/moduleMeshInputGmsh2.f90
Normal file
291
src/modules/mesh/inout/gmsh2/moduleMeshInputGmsh2.f90
Normal file
|
|
@ -0,0 +1,291 @@
|
||||||
|
MODULE moduleMeshInputGmsh2
|
||||||
|
|
||||||
|
CONTAINS
|
||||||
|
!Inits a mesh to use Gmsh2 format
|
||||||
|
SUBROUTINE initGmsh2(self)
|
||||||
|
USE moduleMesh
|
||||||
|
USE moduleMeshOutputGmsh2
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
CLASS(meshGeneric), INTENT(inout), TARGET:: self
|
||||||
|
|
||||||
|
IF (ASSOCIATED(meshForMCC, self)) self%printColl => printCollGmsh2
|
||||||
|
SELECT TYPE(self)
|
||||||
|
TYPE IS(meshParticles)
|
||||||
|
self%printOutput => printOutputGmsh2
|
||||||
|
self%printEM => printEMGmsh2
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
self%readMesh => readGmsh2
|
||||||
|
|
||||||
|
END SUBROUTINE initGmsh2
|
||||||
|
|
||||||
|
!Reads a Gmsh 2 format
|
||||||
|
SUBROUTINE readGmsh2(self, filename)
|
||||||
|
USE moduleMesh3DCart
|
||||||
|
USE moduleMesh2DCyl
|
||||||
|
USE moduleMesh2DCart
|
||||||
|
USE moduleMesh1DRad
|
||||||
|
USE moduleMesh1DCart
|
||||||
|
USE moduleBoundary
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
CLASS(meshGeneric), INTENT(inout):: self
|
||||||
|
CHARACTER(:), ALLOCATABLE, INTENT(in):: filename
|
||||||
|
REAL(8):: r(1:3) !3 generic coordinates
|
||||||
|
INTEGER, ALLOCATABLE:: p(:) !Array for nodes
|
||||||
|
INTEGER:: e = 0, n = 0, eTemp = 0, elemType = 0, bt = 0
|
||||||
|
INTEGER:: totalNumElem
|
||||||
|
INTEGER:: numEdges
|
||||||
|
INTEGER:: boundaryType
|
||||||
|
|
||||||
|
!Read mesh
|
||||||
|
OPEN(10, FILE=TRIM(filename))
|
||||||
|
|
||||||
|
!Skip header
|
||||||
|
READ(10, *)
|
||||||
|
READ(10, *)
|
||||||
|
READ(10, *)
|
||||||
|
READ(10, *)
|
||||||
|
|
||||||
|
!Read number of nodes
|
||||||
|
READ(10, *) self%numNodes
|
||||||
|
|
||||||
|
!Allocate required matrices and vectors
|
||||||
|
ALLOCATE(self%nodes(1:self%numNodes))
|
||||||
|
SELECT TYPE(self)
|
||||||
|
TYPE IS(meshParticles)
|
||||||
|
ALLOCATE(self%K(1:self%numNodes, 1:self%numNodes))
|
||||||
|
ALLOCATE(self%IPIV(1:self%numNodes, 1:self%numNodes))
|
||||||
|
self%K = 0.D0
|
||||||
|
self%IPIV = 0
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
!Read the nodes information
|
||||||
|
DO e = 1, self%numNodes
|
||||||
|
READ(10, *) n, r(1), r(2), r(3)
|
||||||
|
SELECT CASE(self%geometry)
|
||||||
|
CASE("3DCart")
|
||||||
|
ALLOCATE(meshNode3Dcart::self%nodes(n)%obj)
|
||||||
|
|
||||||
|
CASE("2DCyl")
|
||||||
|
ALLOCATE(meshNode2DCyl:: self%nodes(n)%obj)
|
||||||
|
r(3) = 0.D0
|
||||||
|
|
||||||
|
CASE("2DCart")
|
||||||
|
ALLOCATE(meshNode2DCart:: self%nodes(n)%obj)
|
||||||
|
r(3) = 0.D0
|
||||||
|
|
||||||
|
CASE("1DRad")
|
||||||
|
ALLOCATE(meshNode1DRad:: self%nodes(n)%obj)
|
||||||
|
r(2:3) = 0.D0
|
||||||
|
|
||||||
|
CASE("1DCart")
|
||||||
|
ALLOCATE(meshNode1DCart:: self%nodes(n)%obj)
|
||||||
|
r(2:3) = 0.D0
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
CALL self%nodes(n)%obj%init(n, r)
|
||||||
|
|
||||||
|
END DO
|
||||||
|
|
||||||
|
|
||||||
|
!Skip comments
|
||||||
|
READ(10, *)
|
||||||
|
READ(10, *)
|
||||||
|
|
||||||
|
!Reads total number of elements (no nodes)
|
||||||
|
READ(10, *) totalNumElem
|
||||||
|
|
||||||
|
!conts edges and volume elements
|
||||||
|
SELECT TYPE(self)
|
||||||
|
TYPE IS(meshParticles)
|
||||||
|
self%numEdges = 0
|
||||||
|
DO e = 1, totalNumElem
|
||||||
|
READ(10, *) eTemp, elemType
|
||||||
|
SELECT CASE(self%geometry)
|
||||||
|
CASE("3DCart")
|
||||||
|
!Element type 2 is triangle in gmsh
|
||||||
|
IF (elemType == 2) self%numEdges = e
|
||||||
|
|
||||||
|
CASE("2DCyl","2DCart")
|
||||||
|
!Element type 1 is segment in Gmsh
|
||||||
|
IF (elemType == 1) self%numEdges = e
|
||||||
|
|
||||||
|
CASE("1DRad","1DCart")
|
||||||
|
!Element type 15 is physical point in Gmsh
|
||||||
|
IF (elemType == 15) self%numEdges = e
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
END DO
|
||||||
|
|
||||||
|
!Substract the number of edges to the total number of elements
|
||||||
|
!to obtain the number of volume elements
|
||||||
|
self%numVols = TotalnumElem - self%numEdges
|
||||||
|
ALLOCATE(self%edges(1:self%numEdges))
|
||||||
|
numEdges = self%numEdges
|
||||||
|
|
||||||
|
!Go back to the beggining to read elements
|
||||||
|
DO e=1, totalNumElem
|
||||||
|
BACKSPACE(10)
|
||||||
|
END DO
|
||||||
|
|
||||||
|
TYPE IS(meshCollisions)
|
||||||
|
self%numVols = TotalnumElem
|
||||||
|
numEdges = 0
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
!Allocates arrays
|
||||||
|
ALLOCATE(self%vols(1:self%numVols))
|
||||||
|
|
||||||
|
SELECT TYPE(self)
|
||||||
|
TYPE IS(meshParticles)
|
||||||
|
!Reads edges
|
||||||
|
DO e=1, self%numEdges
|
||||||
|
!Reads the edge according to the geometry
|
||||||
|
SELECT CASE(self%geometry)
|
||||||
|
CASE("3DCart")
|
||||||
|
READ(10, *) n, elemType, eTemp, boundaryType
|
||||||
|
BACKSPACE(10)
|
||||||
|
|
||||||
|
!Associate boundary condition procedure.
|
||||||
|
bt = getBoundaryID(boundaryType)
|
||||||
|
|
||||||
|
SELECT CASE(elemType)
|
||||||
|
CASE(2)
|
||||||
|
!Triangular surface
|
||||||
|
ALLOCATE(p(1:3))
|
||||||
|
|
||||||
|
READ(10, *) n, elemType, eTemp, boundaryType, eTemp, p(1:3)
|
||||||
|
|
||||||
|
ALLOCATE(meshEdge3DCartTria:: self%edges(e)%obj)
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
CASE("2DCyl")
|
||||||
|
ALLOCATE(p(1:2))
|
||||||
|
|
||||||
|
READ(10,*) n, elemType, eTemp, boundaryType, eTemp, p(1:2)
|
||||||
|
!Associate boundary condition procedure.
|
||||||
|
bt = getBoundaryId(boundaryType)
|
||||||
|
|
||||||
|
ALLOCATE(meshEdge2DCyl:: self%edges(e)%obj)
|
||||||
|
|
||||||
|
CASE("2DCart")
|
||||||
|
ALLOCATE(p(1:2))
|
||||||
|
|
||||||
|
READ(10,*) n, elemType, eTemp, boundaryType, eTemp, p(1:2)
|
||||||
|
!Associate boundary condition procedure.
|
||||||
|
bt = getBoundaryId(boundaryType)
|
||||||
|
|
||||||
|
ALLOCATE(meshEdge2DCart:: self%edges(e)%obj)
|
||||||
|
|
||||||
|
CASE("1DRad")
|
||||||
|
ALLOCATE(p(1:1))
|
||||||
|
|
||||||
|
READ(10, *) n, elemType, eTemp, boundaryType, eTemp, p(1)
|
||||||
|
!Associate boundary condition
|
||||||
|
bt = getBoundaryId(boundaryType)
|
||||||
|
|
||||||
|
ALLOCATE(meshEdge1DRad:: self%edges(e)%obj)
|
||||||
|
|
||||||
|
CASE("1DCart")
|
||||||
|
ALLOCATE(p(1:1))
|
||||||
|
|
||||||
|
READ(10, *) n, elemType, eTemp, boundaryType, eTemp, p(1)
|
||||||
|
!Associate boundary condition
|
||||||
|
bt = getBoundaryId(boundaryType)
|
||||||
|
|
||||||
|
ALLOCATE(meshEdge1DCart:: self%edges(e)%obj)
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
CALL self%edges(e)%obj%init(n, p, bt, boundaryType)
|
||||||
|
DEALLOCATE(p)
|
||||||
|
|
||||||
|
END DO
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
!Read and initialize volumes
|
||||||
|
DO e = 1, self%numVols
|
||||||
|
!Reads the volume according to the geometry
|
||||||
|
SELECT CASE(self%geometry)
|
||||||
|
CASE("3DCart")
|
||||||
|
READ(10, *) n, elemType
|
||||||
|
BACKSPACE(10)
|
||||||
|
|
||||||
|
SELECT CASE(elemType)
|
||||||
|
CASE(4)
|
||||||
|
!Tetrahedron element
|
||||||
|
ALLOCATE(p(1:4))
|
||||||
|
READ(10, *) n, elemType, eTemp, eTemp, eTemp, p(1:4)
|
||||||
|
ALLOCATE(meshVol3DCartTetra:: self%vols(e)%obj)
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
CASE("2DCyl")
|
||||||
|
READ(10,*) n, elemType
|
||||||
|
BACKSPACE(10)
|
||||||
|
|
||||||
|
SELECT CASE(elemType)
|
||||||
|
CASE (2)
|
||||||
|
!Triangular element
|
||||||
|
ALLOCATE(p(1:3))
|
||||||
|
READ(10,*) n, elemType, eTemp, eTemp, eTemp, p(1:3)
|
||||||
|
ALLOCATE(meshVol2DCylTria:: self%vols(e)%obj)
|
||||||
|
|
||||||
|
CASE (3)
|
||||||
|
!Quadrilateral element
|
||||||
|
ALLOCATE(p(1:4))
|
||||||
|
READ(10,*) n, elemType, eTemp, eTemp, eTemp, p(1:4)
|
||||||
|
ALLOCATE(meshVol2DCylQuad:: self%vols(e)%obj)
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
CASE("2DCart")
|
||||||
|
READ(10,*) n, elemType
|
||||||
|
BACKSPACE(10)
|
||||||
|
|
||||||
|
SELECT CASE(elemType)
|
||||||
|
CASE (2)
|
||||||
|
!Triangular element
|
||||||
|
ALLOCATE(p(1:3))
|
||||||
|
READ(10,*) n, elemType, eTemp, eTemp, eTemp, p(1:3)
|
||||||
|
ALLOCATE(meshVol2DCartTria:: self%vols(e)%obj)
|
||||||
|
|
||||||
|
CASE (3)
|
||||||
|
!Quadrilateral element
|
||||||
|
ALLOCATE(p(1:4))
|
||||||
|
READ(10,*) n, elemType, eTemp, eTemp, eTemp, p(1:4)
|
||||||
|
ALLOCATE(meshVol2DCartQuad:: self%vols(e)%obj)
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
CASE("1DRad")
|
||||||
|
ALLOCATE(p(1:2))
|
||||||
|
|
||||||
|
READ(10, *) n, elemType, eTemp, eTemp, eTemp, p(1:2)
|
||||||
|
ALLOCATE(meshVol1DRadSegm:: self%vols(e)%obj)
|
||||||
|
|
||||||
|
CASE("1DCart")
|
||||||
|
ALLOCATE(p(1:2))
|
||||||
|
|
||||||
|
READ(10, *) n, elemType, eTemp, eTemp, eTemp, p(1:2)
|
||||||
|
ALLOCATE(meshVol1DCartSegm:: self%vols(e)%obj)
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
CALL self%vols(e)%obj%init(n - numEdges, p, self%nodes)
|
||||||
|
DEALLOCATE(p)
|
||||||
|
|
||||||
|
END DO
|
||||||
|
|
||||||
|
CLOSE(10)
|
||||||
|
|
||||||
|
END SUBROUTINE readGmsh2
|
||||||
|
|
||||||
|
END MODULE moduleMeshInputGmsh2
|
||||||
209
src/modules/mesh/inout/gmsh2/moduleMeshOutputGmsh2.f90
Normal file
209
src/modules/mesh/inout/gmsh2/moduleMeshOutputGmsh2.f90
Normal file
|
|
@ -0,0 +1,209 @@
|
||||||
|
MODULE moduleMeshOutputGmsh2
|
||||||
|
|
||||||
|
CONTAINS
|
||||||
|
!Prints the scattered properties of particles into the nodes
|
||||||
|
SUBROUTINE printOutputGmsh2(self, t)
|
||||||
|
USE moduleMesh
|
||||||
|
USE moduleRefParam
|
||||||
|
USE moduleSpecies
|
||||||
|
USE moduleOutput
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
CLASS(meshParticles), INTENT(in):: self
|
||||||
|
INTEGER, INTENT(in):: t
|
||||||
|
INTEGER:: n, i
|
||||||
|
TYPE(outputFormat):: output(1:self%numNodes)
|
||||||
|
REAL(8):: time
|
||||||
|
CHARACTER(:), ALLOCATABLE:: fileName
|
||||||
|
CHARACTER (LEN=iterationDigits):: tstring
|
||||||
|
|
||||||
|
time = DBLE(t)*tauMin*ti_ref
|
||||||
|
|
||||||
|
DO i = 1, nSpecies
|
||||||
|
WRITE(tstring, iterationFormat) t
|
||||||
|
fileName='OUTPUT_' // tstring// '_' // species(i)%obj%name // '.msh'
|
||||||
|
WRITE(*, "(6X,A15,A)") "Creating file: ", fileName
|
||||||
|
OPEN (60, file = path // folder // '/' // fileName)
|
||||||
|
WRITE(60, "(A)") '$MeshFormat'
|
||||||
|
WRITE(60, "(A)") '2.2 0 8'
|
||||||
|
WRITE(60, "(A)") '$EndMeshFormat'
|
||||||
|
WRITE(60, "(A)") '$NodeData'
|
||||||
|
WRITE(60, "(A)") '1'
|
||||||
|
WRITE(60, "(A)") '"Density ' // species(i)%obj%name // ' (m^-3)"'
|
||||||
|
WRITE(60, *) 1
|
||||||
|
WRITE(60, *) time
|
||||||
|
WRITE(60, *) 3
|
||||||
|
WRITE(60, *) t
|
||||||
|
WRITE(60, *) 1
|
||||||
|
WRITE(60, *) self%numNodes
|
||||||
|
DO n=1, self%numNodes
|
||||||
|
CALL calculateOutput(self%nodes(n)%obj%output(i), output(n), self%nodes(n)%obj%v, species(i)%obj)
|
||||||
|
WRITE(60, "(I6,ES20.6E3)") n, output(n)%density
|
||||||
|
END DO
|
||||||
|
WRITE(60, "(A)") '$EndNodeData'
|
||||||
|
WRITE(60, "(A)") '$NodeData'
|
||||||
|
WRITE(60, "(A)") '1'
|
||||||
|
WRITE(60, "(A)") '"Velocity ' // species(i)%obj%name // ' (m/s)"'
|
||||||
|
WRITE(60, *) 1
|
||||||
|
WRITE(60, *) time
|
||||||
|
WRITE(60, *) 3
|
||||||
|
WRITE(60, *) t
|
||||||
|
WRITE(60, *) 3
|
||||||
|
WRITE(60, *) self%numNodes
|
||||||
|
DO n=1, self%numNodes
|
||||||
|
WRITE(60, "(I6,3(ES20.6E3))") n, output(n)%velocity
|
||||||
|
END DO
|
||||||
|
WRITE(60, "(A)") '$EndNodeData'
|
||||||
|
WRITE(60, "(A)") '$NodeData'
|
||||||
|
WRITE(60, "(A)") '1'
|
||||||
|
WRITE(60, "(A)") '"Pressure ' // species(i)%obj%name // ' (Pa)"'
|
||||||
|
WRITE(60, *) 1
|
||||||
|
WRITE(60, *) time
|
||||||
|
WRITE(60, *) 3
|
||||||
|
WRITE(60, *) t
|
||||||
|
WRITE(60, *) 1
|
||||||
|
WRITE(60, *) self%numNodes
|
||||||
|
DO n=1, self%numNodes
|
||||||
|
WRITE(60, "(I6,3(ES20.6E3))") n, output(n)%pressure
|
||||||
|
END DO
|
||||||
|
WRITE(60, "(A)") '$EndNodeData'
|
||||||
|
WRITE(60, "(A)") '$NodeData'
|
||||||
|
WRITE(60, "(A)") '1'
|
||||||
|
WRITE(60, "(A)") '"Temperature ' // species(i)%obj%name // ' (K)"'
|
||||||
|
WRITE(60, *) 1
|
||||||
|
WRITE(60, *) time
|
||||||
|
WRITE(60, *) 3
|
||||||
|
WRITE(60, *) t
|
||||||
|
WRITE(60, *) 1
|
||||||
|
WRITE(60, *) self%numNodes
|
||||||
|
DO n=1, self%numNodes
|
||||||
|
WRITE(60, "(I6,3(ES20.6E3))") n, output(n)%temperature
|
||||||
|
END DO
|
||||||
|
WRITE(60, "(A)") '$EndNodeData'
|
||||||
|
CLOSE (60)
|
||||||
|
|
||||||
|
END DO
|
||||||
|
|
||||||
|
END SUBROUTINE printOutputGmsh2
|
||||||
|
|
||||||
|
!Prints the number of collisions into the volumes
|
||||||
|
SUBROUTINE printCollGmsh2(self, t)
|
||||||
|
USE moduleMesh
|
||||||
|
USE moduleRefParam
|
||||||
|
USE moduleCaseParam
|
||||||
|
USE moduleCollisions
|
||||||
|
USE moduleOutput
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
CLASS(meshGeneric), INTENT(in):: self
|
||||||
|
INTEGER:: numEdges
|
||||||
|
INTEGER, INTENT(in):: t
|
||||||
|
INTEGER:: n
|
||||||
|
REAL(8):: time
|
||||||
|
CHARACTER(:), ALLOCATABLE:: fileName
|
||||||
|
CHARACTER (LEN=iterationDigits):: tstring
|
||||||
|
|
||||||
|
SELECT TYPE(self)
|
||||||
|
TYPE IS(meshParticles)
|
||||||
|
numEdges = self%numEdges
|
||||||
|
|
||||||
|
TYPE IS(meshCollisions)
|
||||||
|
numEdges = 0
|
||||||
|
|
||||||
|
CLASS DEFAULT
|
||||||
|
numEdges = 0
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
IF (collOutput) THEN
|
||||||
|
time = DBLE(t)*tauMin*ti_ref
|
||||||
|
WRITE(tstring, iterationFormat) t
|
||||||
|
|
||||||
|
fileName='OUTPUT_' // tstring// '_Collisions.msh'
|
||||||
|
WRITE(*, "(6X,A15,A)") "Creating file: ", fileName
|
||||||
|
OPEN (60, file = path // folder // '/' // fileName)
|
||||||
|
WRITE(60, "(A)") '$MeshFormat'
|
||||||
|
WRITE(60, "(A)") '2.2 0 8'
|
||||||
|
WRITE(60, "(A)") '$EndMeshFormat'
|
||||||
|
WRITE(60, "(A)") '$ElementData'
|
||||||
|
WRITE(60, "(A)") '1'
|
||||||
|
WRITE(60, "(A)") '"Collisions"'
|
||||||
|
WRITE(60, *) 1
|
||||||
|
WRITE(60, *) time
|
||||||
|
WRITE(60, *) 3
|
||||||
|
WRITE(60, *) t
|
||||||
|
WRITE(60, *) 1
|
||||||
|
WRITE(60, *) self%numVols
|
||||||
|
DO n=1, self%numVols
|
||||||
|
WRITE(60, "(I6,I10)") n + numEdges, self%vols(n)%obj%nColl
|
||||||
|
END DO
|
||||||
|
WRITE(60, "(A)") '$EndElementData'
|
||||||
|
|
||||||
|
CLOSE(60)
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END SUBROUTINE printCollGmsh2
|
||||||
|
|
||||||
|
!Prints the electrostatic EM properties into the nodes and volumes
|
||||||
|
SUBROUTINE printEMGmsh2(self, t)
|
||||||
|
USE moduleMesh
|
||||||
|
USE moduleRefParam
|
||||||
|
USE moduleCaseParam
|
||||||
|
USE moduleOutput
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
CLASS(meshParticles), INTENT(in):: self
|
||||||
|
INTEGER, INTENT(in):: t
|
||||||
|
INTEGER:: n, e
|
||||||
|
REAL(8):: time
|
||||||
|
CHARACTER(:), ALLOCATABLE:: fileName
|
||||||
|
CHARACTER (LEN=iterationDigits):: tstring
|
||||||
|
REAL(8):: xi(1:3)
|
||||||
|
|
||||||
|
xi = (/ 0.D0, 0.D0, 0.D0 /)
|
||||||
|
|
||||||
|
IF (emOutput) THEN
|
||||||
|
time = DBLE(t)*tauMin*ti_ref
|
||||||
|
WRITE(tstring, iterationFormat) t
|
||||||
|
|
||||||
|
fileName='OUTPUT_' // tstring// '_EMField.msh'
|
||||||
|
WRITE(*, "(6X,A15,A)") "Creating file: ", fileName
|
||||||
|
OPEN (20, file = path // folder // '/' // fileName)
|
||||||
|
WRITE(20, "(A)") '$MeshFormat'
|
||||||
|
WRITE(20, "(A)") '2.2 0 8'
|
||||||
|
WRITE(20, "(A)") '$EndMeshFormat'
|
||||||
|
WRITE(20, "(A)") '$NodeData'
|
||||||
|
WRITE(20, "(A)") '1'
|
||||||
|
WRITE(20, "(A)") '"Potential (V)"'
|
||||||
|
WRITE(20, *) 1
|
||||||
|
WRITE(20, *) time
|
||||||
|
WRITE(20, *) 3
|
||||||
|
WRITE(20, *) t
|
||||||
|
WRITE(20, *) 1
|
||||||
|
WRITE(20, *) self%numNodes
|
||||||
|
DO n=1, self%numNodes
|
||||||
|
WRITE(20, *) n, self%nodes(n)%obj%emData%phi*Volt_ref
|
||||||
|
END DO
|
||||||
|
WRITE(20, "(A)") '$EndNodeData'
|
||||||
|
|
||||||
|
WRITE(20, "(A)") '$ElementData'
|
||||||
|
WRITE(20, "(A)") '1'
|
||||||
|
WRITE(20, "(A)") '"Electric Field (V/m)"'
|
||||||
|
WRITE(20, *) 1
|
||||||
|
WRITE(20, *) time
|
||||||
|
WRITE(20, *) 3
|
||||||
|
WRITE(20, *) t
|
||||||
|
WRITE(20, *) 3
|
||||||
|
WRITE(20, *) self%numVols
|
||||||
|
DO e=1, self%numVols
|
||||||
|
WRITE(20, *) e+self%numEdges, self%vols(e)%obj%gatherEF(xi)*EF_ref
|
||||||
|
END DO
|
||||||
|
WRITE(20, "(A)") '$EndElementData'
|
||||||
|
CLOSE(20)
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END SUBROUTINE printEMGmsh2
|
||||||
|
|
||||||
|
END MODULE moduleMeshOutputGmsh2
|
||||||
4
src/modules/mesh/inout/makefile
Normal file
4
src/modules/mesh/inout/makefile
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
all: gmsh2.o
|
||||||
|
|
||||||
|
gmsh2.o:
|
||||||
|
$(MAKE) -C gmsh2 all
|
||||||
|
|
@ -1,18 +1,18 @@
|
||||||
all: moduleMesh.o moduleMeshBoundary.o 3DCart.o 2DCyl.o 2DCart.o 1DRad.o 1DCart.o
|
all: moduleMesh.o moduleMeshBoundary.o inout.o 3DCart.o 2DCyl.o 2DCart.o 1DRad.o 1DCart.o
|
||||||
|
|
||||||
3DCart.o:
|
3DCart.o: moduleMesh.o
|
||||||
$(MAKE) -C 3DCart all
|
$(MAKE) -C 3DCart all
|
||||||
|
|
||||||
2DCyl.o:
|
2DCyl.o: moduleMesh.o
|
||||||
$(MAKE) -C 2DCyl all
|
$(MAKE) -C 2DCyl all
|
||||||
|
|
||||||
2DCart.o:
|
2DCart.o: moduleMesh.o
|
||||||
$(MAKE) -C 2DCart all
|
$(MAKE) -C 2DCart all
|
||||||
|
|
||||||
1DCart.o:
|
1DCart.o: moduleMesh.o
|
||||||
$(MAKE) -C 1DCart all
|
$(MAKE) -C 1DCart all
|
||||||
|
|
||||||
1DRad.o:
|
1DRad.o: moduleMesh.o
|
||||||
$(MAKE) -C 1DRad all
|
$(MAKE) -C 1DRad all
|
||||||
|
|
||||||
moduleMesh.o: moduleMesh.f90
|
moduleMesh.o: moduleMesh.f90
|
||||||
|
|
@ -20,3 +20,6 @@ moduleMesh.o: moduleMesh.f90
|
||||||
|
|
||||||
moduleMeshBoundary.o: moduleMesh.o moduleMeshBoundary.f90
|
moduleMeshBoundary.o: moduleMesh.o moduleMeshBoundary.f90
|
||||||
$(FC) $(FCFLAGS) -c $(subst .o,.f90,$@) -o $(OBJDIR)/$@
|
$(FC) $(FCFLAGS) -c $(subst .o,.f90,$@) -o $(OBJDIR)/$@
|
||||||
|
|
||||||
|
inout.o: 3DCart.o 2DCyl.o 2DCart.o 1DRad.o 1DCart.o
|
||||||
|
$(MAKE) -C inout all
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,16 @@ MODULE moduleMesh
|
||||||
USE moduleBoundary
|
USE moduleBoundary
|
||||||
IMPLICIT NONE
|
IMPLICIT NONE
|
||||||
|
|
||||||
!Parent of Node element
|
!Generic mesh element
|
||||||
TYPE, PUBLIC, ABSTRACT:: meshNode
|
TYPE, PUBLIC, ABSTRACT:: meshElement
|
||||||
!Node index
|
!Index
|
||||||
INTEGER:: n = 0
|
INTEGER:: n = 0
|
||||||
|
CONTAINS
|
||||||
|
|
||||||
|
END TYPE meshElement
|
||||||
|
|
||||||
|
!Parent of Node element
|
||||||
|
TYPE, PUBLIC, ABSTRACT, EXTENDS(meshElement):: meshNode
|
||||||
!Node volume
|
!Node volume
|
||||||
REAL(8):: v = 0.D0
|
REAL(8):: v = 0.D0
|
||||||
!Output values
|
!Output values
|
||||||
|
|
@ -44,26 +50,28 @@ MODULE moduleMesh
|
||||||
!Containers for nodes in the mesh
|
!Containers for nodes in the mesh
|
||||||
TYPE:: meshNodeCont
|
TYPE:: meshNodeCont
|
||||||
CLASS(meshNode), ALLOCATABLE:: obj
|
CLASS(meshNode), ALLOCATABLE:: obj
|
||||||
|
CONTAINS
|
||||||
|
|
||||||
END TYPE meshNodeCont
|
END TYPE meshNodeCont
|
||||||
|
|
||||||
!Type for array of boundary functions (one per species)
|
!Type for array of boundary functions (one per species)
|
||||||
TYPE, PUBLIC:: fBoundaryGeneric
|
TYPE, PUBLIC:: fBoundaryGeneric
|
||||||
PROCEDURE(boundary_interface), POINTER, NOPASS:: apply => NULL()
|
PROCEDURE(boundary_interface), POINTER, NOPASS:: apply => NULL()
|
||||||
|
CONTAINS
|
||||||
|
|
||||||
END TYPE
|
END TYPE
|
||||||
|
|
||||||
!Parent of Edge element
|
!Parent of Edge element
|
||||||
TYPE, PUBLIC, ABSTRACT:: meshEdge
|
TYPE, PUBLIC, ABSTRACT, EXTENDS(meshElement):: meshEdge
|
||||||
!Element index
|
|
||||||
INTEGER:: n = 0
|
|
||||||
!Connectivity to vols
|
!Connectivity to vols
|
||||||
CLASS(meshVol), POINTER:: e1 => NULL(), e2 => NULL()
|
CLASS(meshVol), POINTER:: e1 => NULL(), e2 => NULL()
|
||||||
|
!Connectivity to vols in meshColl
|
||||||
|
CLASS(meshVol), POINTER:: eColl => NULL()
|
||||||
!Normal vector
|
!Normal vector
|
||||||
REAL(8):: normal(1:3)
|
REAL(8):: normal(1:3)
|
||||||
!Weight for random injection of particles
|
!Weight for random injection of particles
|
||||||
REAL(8):: weight = 1.D0
|
REAL(8):: weight = 1.D0
|
||||||
!Pointer to boundary element
|
!Pointer to boundary type
|
||||||
TYPE(boundaryCont), POINTER:: boundary
|
TYPE(boundaryCont), POINTER:: boundary
|
||||||
!Array of functions for boundary conditions
|
!Array of functions for boundary conditions
|
||||||
TYPE(fBoundaryGeneric), ALLOCATABLE:: fBoundary(:)
|
TYPE(fBoundaryGeneric), ALLOCATABLE:: fBoundary(:)
|
||||||
|
|
@ -98,7 +106,7 @@ MODULE moduleMesh
|
||||||
|
|
||||||
END FUNCTION getNodesEdge_interface
|
END FUNCTION getNodesEdge_interface
|
||||||
|
|
||||||
!Returns the intersecction between an edge and a line defined by point r0 and vector v0
|
!Returns the intersecction between an edge and a line defined by point r0
|
||||||
PURE FUNCTION intersectionEdge_interface(self, r0) RESULT(r)
|
PURE FUNCTION intersectionEdge_interface(self, r0) RESULT(r)
|
||||||
IMPORT:: meshEdge
|
IMPORT:: meshEdge
|
||||||
CLASS(meshEdge), INTENT(in):: self
|
CLASS(meshEdge), INTENT(in):: self
|
||||||
|
|
@ -136,9 +144,7 @@ MODULE moduleMesh
|
||||||
END TYPE meshEdgeCont
|
END TYPE meshEdgeCont
|
||||||
|
|
||||||
!Parent of Volume element
|
!Parent of Volume element
|
||||||
TYPE, PUBLIC, ABSTRACT:: meshVol
|
TYPE, PUBLIC, ABSTRACT, EXTENDS(meshElement):: meshVol
|
||||||
!Volume index
|
|
||||||
INTEGER:: n = 0
|
|
||||||
!Maximum collision rate
|
!Maximum collision rate
|
||||||
REAL(8):: sigmaVrelMax = 0.D0
|
REAL(8):: sigmaVrelMax = 0.D0
|
||||||
!Volume
|
!Volume
|
||||||
|
|
@ -149,8 +155,6 @@ MODULE moduleMesh
|
||||||
INTEGER(KIND=OMP_LOCK_KIND):: lock
|
INTEGER(KIND=OMP_LOCK_KIND):: lock
|
||||||
!Number of collisions per volume
|
!Number of collisions per volume
|
||||||
INTEGER:: nColl = 0
|
INTEGER:: nColl = 0
|
||||||
!Collisional fraction
|
|
||||||
REAL(8):: collFrac = 0.D0
|
|
||||||
!Total weight of particles inside cell
|
!Total weight of particles inside cell
|
||||||
REAL(8):: totalWeight = 0.D0
|
REAL(8):: totalWeight = 0.D0
|
||||||
CONTAINS
|
CONTAINS
|
||||||
|
|
@ -159,21 +163,23 @@ MODULE moduleMesh
|
||||||
PROCEDURE(randPosVol_interface), DEFERRED, PASS:: randPos
|
PROCEDURE(randPosVol_interface), DEFERRED, PASS:: randPos
|
||||||
PROCEDURE(scatter_interface), DEFERRED, PASS:: scatter
|
PROCEDURE(scatter_interface), DEFERRED, PASS:: scatter
|
||||||
PROCEDURE(gatherEF_interface), DEFERRED, PASS:: gatherEF
|
PROCEDURE(gatherEF_interface), DEFERRED, PASS:: gatherEF
|
||||||
|
PROCEDURE(elemK_interface), DEFERRED, PASS:: elemK
|
||||||
PROCEDURE(elemF_interface), DEFERRED, PASS:: elemF
|
PROCEDURE(elemF_interface), DEFERRED, PASS:: elemF
|
||||||
PROCEDURE, PASS:: findCell
|
PROCEDURE, PASS:: findCell
|
||||||
PROCEDURE(phy2log_interface), DEFERRED, PASS:: phy2log
|
PROCEDURE(phy2log_interface), DEFERRED, PASS:: phy2log
|
||||||
PROCEDURE(inside_interface), DEFERRED, NOPASS:: inside
|
PROCEDURE(inside_interface), DEFERRED, NOPASS:: inside
|
||||||
PROCEDURE(nextElement_interface), DEFERRED, PASS:: nextElement
|
PROCEDURE(nextElement_interface), DEFERRED, PASS:: nextElement
|
||||||
PROCEDURE, PASS:: collision
|
|
||||||
|
|
||||||
END TYPE meshVol
|
END TYPE meshVol
|
||||||
|
|
||||||
ABSTRACT INTERFACE
|
ABSTRACT INTERFACE
|
||||||
SUBROUTINE initVol_interface(self, n, p)
|
SUBROUTINE initVol_interface(self, n, p, nodes)
|
||||||
IMPORT:: meshVol
|
IMPORT:: meshVol
|
||||||
|
IMPORT meshNodeCont
|
||||||
CLASS(meshVol), INTENT(out):: self
|
CLASS(meshVol), INTENT(out):: self
|
||||||
INTEGER, INTENT(in):: n
|
INTEGER, INTENT(in):: n
|
||||||
INTEGER, INTENT(in):: p(:)
|
INTEGER, INTENT(in):: p(:)
|
||||||
|
TYPE(meshNodeCont), INTENT(in), TARGET:: nodes(:)
|
||||||
|
|
||||||
END SUBROUTINE initVol_interface
|
END SUBROUTINE initVol_interface
|
||||||
|
|
||||||
|
|
@ -202,6 +208,13 @@ MODULE moduleMesh
|
||||||
|
|
||||||
END FUNCTION getNodesVol_interface
|
END FUNCTION getNodesVol_interface
|
||||||
|
|
||||||
|
PURE FUNCTION elemK_interface(self) RESULT(localK)
|
||||||
|
IMPORT:: meshVol
|
||||||
|
CLASS(meshVol), INTENT(in):: self
|
||||||
|
REAL(8), ALLOCATABLE:: localK(:,:)
|
||||||
|
|
||||||
|
END FUNCTION elemK_interface
|
||||||
|
|
||||||
PURE FUNCTION elemF_interface(self, source) RESULT(localF)
|
PURE FUNCTION elemF_interface(self, source) RESULT(localF)
|
||||||
IMPORT:: meshVol
|
IMPORT:: meshVol
|
||||||
CLASS(meshVol), INTENT(in):: self
|
CLASS(meshVol), INTENT(in):: self
|
||||||
|
|
@ -211,10 +224,10 @@ MODULE moduleMesh
|
||||||
END FUNCTION elemF_interface
|
END FUNCTION elemF_interface
|
||||||
|
|
||||||
SUBROUTINE nextElement_interface(self, xi, nextElement)
|
SUBROUTINE nextElement_interface(self, xi, nextElement)
|
||||||
IMPORT:: meshVol
|
IMPORT:: meshVol, meshElement
|
||||||
CLASS(meshVol), INTENT(in):: self
|
CLASS(meshVol), INTENT(in):: self
|
||||||
REAL(8), INTENT(in):: xi(1:3)
|
REAL(8), INTENT(in):: xi(1:3)
|
||||||
CLASS(*), POINTER, INTENT(out):: nextElement
|
CLASS(meshElement), POINTER, INTENT(out):: nextElement
|
||||||
|
|
||||||
END SUBROUTINE nextElement_interface
|
END SUBROUTINE nextElement_interface
|
||||||
|
|
||||||
|
|
@ -248,38 +261,25 @@ MODULE moduleMesh
|
||||||
|
|
||||||
END TYPE meshVolCont
|
END TYPE meshVolCont
|
||||||
|
|
||||||
!Abstract type of mesh
|
!Generic mesh type
|
||||||
TYPE, PUBLIC, ABSTRACT:: meshGeneric
|
TYPE, ABSTRACT:: meshGeneric
|
||||||
INTEGER:: numEdges, numNodes, numVols
|
!Geometry of the mesh
|
||||||
|
CHARACTER(:), ALLOCATABLE:: geometry
|
||||||
|
!Number of elements
|
||||||
|
INTEGER:: numNodes, numVols
|
||||||
!Array of nodes
|
!Array of nodes
|
||||||
TYPE(meshNodeCont), ALLOCATABLE:: nodes(:)
|
TYPE(meshNodeCont), ALLOCATABLE:: nodes(:)
|
||||||
!Array of boundary elements
|
|
||||||
TYPE(meshEdgeCont), ALLOCATABLE:: edges(:)
|
|
||||||
!Array of volume elements
|
!Array of volume elements
|
||||||
TYPE(meshVolCont), ALLOCATABLE:: vols(:)
|
TYPE(meshVolCont), ALLOCATABLE:: vols(:)
|
||||||
!Global stiffness matrix
|
PROCEDURE(readMesh_interface), POINTER, PASS:: readMesh => NULL()
|
||||||
REAL(8), ALLOCATABLE, DIMENSION(:,:):: K
|
PROCEDURE(connectMesh_interface), POINTER, PASS:: connectMesh => NULL()
|
||||||
!Permutation matrix for P L U factorization
|
|
||||||
INTEGER, ALLOCATABLE, DIMENSION(:,:):: IPIV
|
|
||||||
PROCEDURE(printOutput_interface), POINTER, PASS:: printOutput => NULL()
|
|
||||||
PROCEDURE(printColl_interface), POINTER, PASS:: printColl => NULL()
|
PROCEDURE(printColl_interface), POINTER, PASS:: printColl => NULL()
|
||||||
PROCEDURE(printEM_interface), POINTER, PASS:: printEM => NULL()
|
|
||||||
CONTAINS
|
CONTAINS
|
||||||
PROCEDURE(initMesh_interface), DEFERRED, PASS:: init
|
PROCEDURE, PASS:: doCollisions
|
||||||
PROCEDURE(readMesh_interface), DEFERRED, PASS:: readMesh
|
|
||||||
|
|
||||||
END TYPE meshGeneric
|
END TYPE
|
||||||
|
|
||||||
ABSTRACT INTERFACE
|
ABSTRACT INTERFACE
|
||||||
!Inits the mesh
|
|
||||||
SUBROUTINE initMesh_interface(self, meshFormat)
|
|
||||||
IMPORT meshGeneric
|
|
||||||
|
|
||||||
CLASS(meshGeneric), INTENT(out):: self
|
|
||||||
CHARACTER(:), ALLOCATABLE, INTENT(in):: meshFormat
|
|
||||||
|
|
||||||
END SUBROUTINE initMesh_interface
|
|
||||||
|
|
||||||
!Reads the mesh from a file
|
!Reads the mesh from a file
|
||||||
SUBROUTINE readMesh_interface(self, filename)
|
SUBROUTINE readMesh_interface(self, filename)
|
||||||
IMPORT meshGeneric
|
IMPORT meshGeneric
|
||||||
|
|
@ -289,16 +289,15 @@ MODULE moduleMesh
|
||||||
|
|
||||||
END SUBROUTINE readMesh_interface
|
END SUBROUTINE readMesh_interface
|
||||||
|
|
||||||
!Prints Species data
|
!Connects volume and edges to the mesh
|
||||||
SUBROUTINE printOutput_interface(self, t)
|
SUBROUTINE connectMesh_interface(self)
|
||||||
IMPORT meshGeneric
|
IMPORT meshGeneric
|
||||||
|
|
||||||
CLASS(meshGeneric), INTENT(in):: self
|
CLASS(meshGeneric), INTENT(inout):: self
|
||||||
INTEGER, INTENT(in):: t
|
|
||||||
|
|
||||||
END SUBROUTINE printOutput_interface
|
END SUBROUTINE connectMesh_interface
|
||||||
|
|
||||||
!Prints number of collisions
|
!Prints number of collisions in each volume
|
||||||
SUBROUTINE printColl_interface(self, t)
|
SUBROUTINE printColl_interface(self, t)
|
||||||
IMPORT meshGeneric
|
IMPORT meshGeneric
|
||||||
|
|
||||||
|
|
@ -307,21 +306,127 @@ MODULE moduleMesh
|
||||||
|
|
||||||
END SUBROUTINE printColl_interface
|
END SUBROUTINE printColl_interface
|
||||||
|
|
||||||
|
END INTERFACE
|
||||||
|
|
||||||
|
!Particle mesh
|
||||||
|
TYPE, EXTENDS(meshGeneric), PUBLIC:: meshParticles
|
||||||
|
INTEGER:: numEdges
|
||||||
|
!Array of boundary elements
|
||||||
|
TYPE(meshEdgeCont), ALLOCATABLE:: edges(:)
|
||||||
|
!Global stiffness matrix
|
||||||
|
REAL(8), ALLOCATABLE, DIMENSION(:,:):: K
|
||||||
|
!Permutation matrix for P L U factorization
|
||||||
|
INTEGER, ALLOCATABLE, DIMENSION(:,:):: IPIV
|
||||||
|
PROCEDURE(printOutput_interface), POINTER, PASS:: printOutput => NULL()
|
||||||
|
PROCEDURE(printEM_interface), POINTER, PASS:: printEM => NULL()
|
||||||
|
PROCEDURE(doCoulomb_interface), POINTER, PASS:: doCoulomb => NULL()
|
||||||
|
CONTAINS
|
||||||
|
PROCEDURE, PASS:: constructGlobalK
|
||||||
|
|
||||||
|
END TYPE meshParticles
|
||||||
|
|
||||||
|
ABSTRACT INTERFACE
|
||||||
|
!Perform Coulomb Scattering
|
||||||
|
SUBROUTINE doCoulomb_interface(self)
|
||||||
|
IMPORT meshParticles
|
||||||
|
|
||||||
|
CLASS(meshParticles), INTENT(inout):: self
|
||||||
|
|
||||||
|
END SUBROUTINE doCoulomb_interface
|
||||||
|
|
||||||
|
!Prints Species data
|
||||||
|
SUBROUTINE printOutput_interface(self, t)
|
||||||
|
IMPORT meshParticles
|
||||||
|
|
||||||
|
CLASS(meshParticles), INTENT(in):: self
|
||||||
|
INTEGER, INTENT(in):: t
|
||||||
|
|
||||||
|
END SUBROUTINE printOutput_interface
|
||||||
|
|
||||||
!Prints EM info
|
!Prints EM info
|
||||||
SUBROUTINE printEM_interface(self, t)
|
SUBROUTINE printEM_interface(self, t)
|
||||||
IMPORT meshGeneric
|
IMPORT meshParticles
|
||||||
|
|
||||||
CLASS(meshGeneric), INTENT(in):: self
|
CLASS(meshParticles), INTENT(in):: self
|
||||||
INTEGER, INTENT(in):: t
|
INTEGER, INTENT(in):: t
|
||||||
|
|
||||||
END SUBROUTINE printEM_interface
|
END SUBROUTINE printEM_interface
|
||||||
|
|
||||||
|
|
||||||
END INTERFACE
|
END INTERFACE
|
||||||
|
|
||||||
!Generic mesh
|
TYPE(meshParticles), TARGET:: mesh
|
||||||
CLASS(meshGeneric), ALLOCATABLE, TARGET:: mesh
|
|
||||||
|
!Collision (MCC) mesh
|
||||||
|
TYPE, EXTENDS(meshGeneric):: meshCollisions
|
||||||
|
CONTAINS
|
||||||
|
|
||||||
|
END TYPE meshCollisions
|
||||||
|
|
||||||
|
TYPE(meshCollisions), TARGET:: meshColl
|
||||||
|
|
||||||
|
ABSTRACT INTERFACE
|
||||||
|
SUBROUTINE readMeshColl_interface(self, filename)
|
||||||
|
IMPORT meshCollisions
|
||||||
|
|
||||||
|
CLASS(meshCollisions), INTENT(inout):: self
|
||||||
|
CHARACTER(:), ALLOCATABLE, INTENT(in):: filename
|
||||||
|
|
||||||
|
END SUBROUTINE readMeshColl_interface
|
||||||
|
|
||||||
|
SUBROUTINE connectMeshColl_interface(self)
|
||||||
|
IMPORT meshParticles
|
||||||
|
|
||||||
|
CLASS(meshParticles), INTENT(inout):: self
|
||||||
|
|
||||||
|
END SUBROUTINE connectMeshColl_interface
|
||||||
|
|
||||||
|
END INTERFACE
|
||||||
|
|
||||||
|
!Pointer to mesh used for MC collisions
|
||||||
|
CLASS(meshGeneric), POINTER:: meshForMCC => NULL()
|
||||||
|
|
||||||
|
!Procedure to find a volume for a particle in meshColl
|
||||||
|
PROCEDURE(findCellColl_interface), POINTER:: findCellColl => NULL()
|
||||||
|
|
||||||
|
ABSTRACT INTERFACE
|
||||||
|
SUBROUTINE findCellColl_interface(part)
|
||||||
|
USE moduleSpecies
|
||||||
|
|
||||||
|
TYPE(particle), INTENT(inout):: part
|
||||||
|
|
||||||
|
END SUBROUTINE findCellColl_interface
|
||||||
|
|
||||||
|
END INTERFACE
|
||||||
|
|
||||||
CONTAINS
|
CONTAINS
|
||||||
|
!Constructs the global K matrix
|
||||||
|
SUBROUTINE constructGlobalK(self)
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
CLASS(meshParticles), INTENT(inout):: self
|
||||||
|
INTEGER:: e
|
||||||
|
INTEGER, ALLOCATABLE:: n(:)
|
||||||
|
REAL(8), ALLOCATABLE:: localK(:,:)
|
||||||
|
INTEGER:: nNodes, i, j
|
||||||
|
|
||||||
|
DO e = 1, self%numVols
|
||||||
|
n = self%vols(e)%obj%getNodes()
|
||||||
|
localK = self%vols(e)%obj%elemK()
|
||||||
|
nNodes = SIZE(n)
|
||||||
|
|
||||||
|
DO i = 1, nNodes
|
||||||
|
DO j = 1, nNodes
|
||||||
|
self%K(n(i), n(j)) = self%K(n(i), n(j)) + localK(i, j)
|
||||||
|
|
||||||
|
END DO
|
||||||
|
|
||||||
|
END DO
|
||||||
|
|
||||||
|
END DO
|
||||||
|
|
||||||
|
END SUBROUTINE constructGlobalK
|
||||||
|
|
||||||
!Reset the output of node
|
!Reset the output of node
|
||||||
PURE SUBROUTINE resetOutput(self)
|
PURE SUBROUTINE resetOutput(self)
|
||||||
USE moduleSpecies
|
USE moduleSpecies
|
||||||
|
|
@ -343,14 +448,15 @@ MODULE moduleMesh
|
||||||
!Find next cell for particle
|
!Find next cell for particle
|
||||||
RECURSIVE SUBROUTINE findCell(self, part, oldCell)
|
RECURSIVE SUBROUTINE findCell(self, part, oldCell)
|
||||||
USE moduleSpecies
|
USE moduleSpecies
|
||||||
|
USE moduleErrors
|
||||||
USE OMP_LIB
|
USE OMP_LIB
|
||||||
IMPLICIT NONE
|
IMPLICIT NONE
|
||||||
|
|
||||||
CLASS(meshVol), INTENT(inout):: self
|
CLASS(meshVol), INTENT(inout):: self
|
||||||
CLASS(meshVol), OPTIONAL, INTENT(in):: oldCell
|
|
||||||
CLASS(particle), INTENT(inout), TARGET:: part
|
CLASS(particle), INTENT(inout), TARGET:: part
|
||||||
|
CLASS(meshVol), OPTIONAL, INTENT(in):: oldCell
|
||||||
REAL(8):: xi(1:3)
|
REAL(8):: xi(1:3)
|
||||||
CLASS(*), POINTER:: nextElement
|
CLASS(meshElement), POINTER:: nextElement
|
||||||
|
|
||||||
xi = self%phy2log(part%r)
|
xi = self%phy2log(part%r)
|
||||||
!Checks if particle is inside 'self' cell
|
!Checks if particle is inside 'self' cell
|
||||||
|
|
@ -375,7 +481,7 @@ MODULE moduleMesh
|
||||||
|
|
||||||
CLASS IS (meshEdge)
|
CLASS IS (meshEdge)
|
||||||
!Particle encountered a surface, apply boundary
|
!Particle encountered a surface, apply boundary
|
||||||
CALL nextElement%fBoundary(part%sp)%apply(nextElement,part)
|
CALL nextElement%fBoundary(part%species%n)%apply(nextElement,part)
|
||||||
|
|
||||||
!If particle is still inside the domain, call findCell
|
!If particle is still inside the domain, call findCell
|
||||||
IF (part%n_in) THEN
|
IF (part%n_in) THEN
|
||||||
|
|
@ -389,15 +495,100 @@ MODULE moduleMesh
|
||||||
END IF
|
END IF
|
||||||
|
|
||||||
CLASS DEFAULT
|
CLASS DEFAULT
|
||||||
WRITE(*,*) "ERROR, CHECK findCell"
|
WRITE (*, "(A, I6)") "Element = ", self%n
|
||||||
|
CALL criticalError("No connectivity found for element", "findCell")
|
||||||
|
|
||||||
END SELECT
|
END SELECT
|
||||||
|
|
||||||
END IF
|
END IF
|
||||||
|
|
||||||
END SUBROUTINE findCell
|
END SUBROUTINE findCell
|
||||||
|
|
||||||
|
!If Coll and Particle are the same, simply copy the part%vol into part%volColl
|
||||||
|
SUBROUTINE findCellSameMesh(part)
|
||||||
|
USE moduleSpecies
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
TYPE(particle), INTENT(inout):: part
|
||||||
|
|
||||||
|
part%volColl = part%vol
|
||||||
|
|
||||||
|
END SUBROUTINE findCellSameMesh
|
||||||
|
|
||||||
|
!TODO: try to combine this with the findCell for a regular mesh
|
||||||
|
!Find the volume in which particle reside in the mesh for collisions
|
||||||
|
SUBROUTINE findCellCollMesh(part)
|
||||||
|
USE moduleSpecies
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
TYPE(particle), INTENT(inout):: part
|
||||||
|
LOGICAL:: found
|
||||||
|
CLASS(meshVol), POINTER:: vol
|
||||||
|
REAL(8), DIMENSION(1:3):: xii
|
||||||
|
CLASS(meshElement), POINTER:: nextElement
|
||||||
|
|
||||||
|
found = .FALSE.
|
||||||
|
|
||||||
|
vol => meshColl%vols(part%volColl)%obj
|
||||||
|
DO WHILE(.NOT. found)
|
||||||
|
xii = vol%phy2log(part%r)
|
||||||
|
IF (vol%inside(xii)) THEN
|
||||||
|
part%volColl = vol%n
|
||||||
|
CALL OMP_SET_LOCK(vol%lock)
|
||||||
|
CALL vol%listPart_in%add(part)
|
||||||
|
vol%totalWeight = vol%totalWeight + part%weight
|
||||||
|
CALL OMP_UNSET_LOCK(vol%lock)
|
||||||
|
found = .TRUE.
|
||||||
|
|
||||||
|
ELSE
|
||||||
|
CALL vol%nextElement(xii, nextElement)
|
||||||
|
SELECT TYPE(nextElement)
|
||||||
|
CLASS IS(meshVol)
|
||||||
|
!Try next element
|
||||||
|
vol => nextElement
|
||||||
|
|
||||||
|
CLASS DEFAULT
|
||||||
|
!Should never happend, but just in case, stops loops
|
||||||
|
found = .TRUE.
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END DO
|
||||||
|
|
||||||
|
END SUBROUTINE findCellCollMesh
|
||||||
|
|
||||||
|
!Returns index of volume associated to a position (if any)
|
||||||
|
!If no voulme is found, returns 0
|
||||||
|
!WARNING: This function is slow and should only be used in initialization phase
|
||||||
|
FUNCTION findCellBrute(self, r) RESULT(nVol)
|
||||||
|
USE moduleSpecies
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
CLASS(meshGeneric), INTENT(in):: self
|
||||||
|
REAL(8), DIMENSION(1:3), INTENT(in):: r
|
||||||
|
INTEGER:: nVol
|
||||||
|
INTEGER:: e
|
||||||
|
REAL(8), DIMENSION(1:3):: xii
|
||||||
|
|
||||||
|
!Inits RESULT
|
||||||
|
nVol = 0
|
||||||
|
|
||||||
|
DO e = 1, self%numVols
|
||||||
|
xii = self%vols(e)%obj%phy2log(r)
|
||||||
|
IF(self%vols(e)%obj%inside(xii)) THEN
|
||||||
|
nVol = self%vols(e)%obj%n
|
||||||
|
EXIT
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END DO
|
||||||
|
|
||||||
|
END FUNCTION findCellBrute
|
||||||
|
|
||||||
!Computes collisions in element
|
!Computes collisions in element
|
||||||
SUBROUTINE collision(self)
|
SUBROUTINE doCollisions(self)
|
||||||
USE moduleCollisions
|
USE moduleCollisions
|
||||||
USE moduleSpecies
|
USE moduleSpecies
|
||||||
USE moduleList
|
USE moduleList
|
||||||
|
|
@ -405,7 +596,9 @@ MODULE moduleMesh
|
||||||
USE moduleRandom
|
USE moduleRandom
|
||||||
IMPLICIT NONE
|
IMPLICIT NONE
|
||||||
|
|
||||||
CLASS(meshVol), INTENT(inout):: self
|
CLASS(meshGeneric), INTENT(inout), TARGET:: self
|
||||||
|
INTEGER:: e
|
||||||
|
CLASS(meshVol), POINTER:: vol
|
||||||
INTEGER:: nPart !Number of particles inside the cell
|
INTEGER:: nPart !Number of particles inside the cell
|
||||||
REAL(8):: pMax !Maximum probability of collision
|
REAL(8):: pMax !Maximum probability of collision
|
||||||
INTEGER:: rnd !random index
|
INTEGER:: rnd !random index
|
||||||
|
|
@ -415,237 +608,57 @@ MODULE moduleMesh
|
||||||
REAL(8):: sigmaVrelMaxNew
|
REAL(8):: sigmaVrelMaxNew
|
||||||
TYPE(pointerArray), ALLOCATABLE:: partTemp(:)
|
TYPE(pointerArray), ALLOCATABLE:: partTemp(:)
|
||||||
|
|
||||||
nPart = self%listPart_in%amount
|
!$OMP DO SCHEDULE(DYNAMIC)
|
||||||
|
DO e=1, self%numVols
|
||||||
|
vol => self%vols(e)%obj
|
||||||
|
nPart = vol%listPart_in%amount
|
||||||
!Computes iterations if there is more than one particle in the cell
|
!Computes iterations if there is more than one particle in the cell
|
||||||
IF (nPart > 1) THEN
|
IF (nPart > 1) THEN
|
||||||
!Probability of collision
|
!Probability of collision
|
||||||
pMax = self%totalWeight*self%sigmaVrelMax*tauMin/self%volume
|
pMax = vol%totalWeight*vol%sigmaVrelMax*tauMin/vol%volume
|
||||||
|
|
||||||
!Increases the collisional fraction of the cell
|
|
||||||
self%collFrac = self%collFrac + REAL(nPart)*pMax*0.5D0
|
|
||||||
|
|
||||||
!Number of collisions in the cell
|
!Number of collisions in the cell
|
||||||
self%nColl = FLOOR(self%collFrac)
|
vol%nColl = NINT(REAL(nPart)*pMax*0.5D0)
|
||||||
|
|
||||||
IF (self%nColl > 0) THEN
|
IF (vol%nColl > 0) THEN
|
||||||
!Converts the list of particles to an array for easy access
|
!Converts the list of particles to an array for easy access
|
||||||
partTemp = self%listPart_in%convert2Array()
|
partTemp = vol%listPart_in%convert2Array()
|
||||||
|
|
||||||
END IF
|
END IF
|
||||||
|
|
||||||
DO n = 1, self%nColl
|
DO n = 1, vol%nColl
|
||||||
!Select random numbers
|
!Select random numbers
|
||||||
rnd = random(1, nPart)
|
rnd = random(1, nPart)
|
||||||
part_i => partTemp(rnd)%part
|
part_i => partTemp(rnd)%part
|
||||||
rnd = random(1, nPart)
|
rnd = random(1, nPart)
|
||||||
part_j => partTemp(rnd)%part
|
part_j => partTemp(rnd)%part
|
||||||
ij = interactionIndex(part_i%sp, part_j%sp)
|
ij = interactionIndex(part_i%species%n, part_j%species%n)
|
||||||
sigmaVrelMaxNew = 0.D0
|
sigmaVrelMaxNew = 0.D0
|
||||||
DO k = 1, interactionMatrix(ij)%amount
|
DO k = 1, interactionMatrix(ij)%amount
|
||||||
CALL interactionMatrix(ij)%collisions(k)%obj%collide(self%sigmaVrelMax, sigmaVrelMaxNew, part_i, part_j)
|
CALL interactionMatrix(ij)%collisions(k)%obj%collide(vol%sigmaVrelMax, sigmaVrelMaxNew, part_i, part_j)
|
||||||
|
|
||||||
END DO
|
END DO
|
||||||
|
|
||||||
!Update maximum cross section*v_rel per each collision
|
!Update maximum cross section*v_rel per each collision
|
||||||
IF (sigmaVrelMaxNew > self%sigmaVrelMax) THEN
|
IF (sigmaVrelMaxNew > vol%sigmaVrelMax) THEN
|
||||||
self%sigmaVrelMax = sigmaVrelMaxNew
|
vol%sigmaVrelMax = sigmaVrelMaxNew
|
||||||
|
|
||||||
END IF
|
END IF
|
||||||
|
|
||||||
!Removes one collision from the collisional fraction
|
|
||||||
self%collFrac = self%collFrac - 1.D0
|
|
||||||
|
|
||||||
END DO
|
END DO
|
||||||
|
|
||||||
END IF
|
END IF
|
||||||
|
|
||||||
END SUBROUTINE collision
|
|
||||||
|
|
||||||
SUBROUTINE printOutputGmsh(self, t)
|
|
||||||
USE moduleRefParam
|
|
||||||
USE moduleSpecies
|
|
||||||
USE moduleOutput
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
CLASS(meshGeneric), INTENT(in):: self
|
|
||||||
INTEGER, INTENT(in):: t
|
|
||||||
INTEGER:: n, i
|
|
||||||
TYPE(outputFormat):: output(1:self%numNodes)
|
|
||||||
REAL(8):: time
|
|
||||||
CHARACTER(:), ALLOCATABLE:: fileName
|
|
||||||
CHARACTER (LEN=iterationDigits):: tstring
|
|
||||||
|
|
||||||
time = DBLE(t)*tauMin*ti_ref
|
|
||||||
|
|
||||||
DO i = 1, nSpecies
|
|
||||||
WRITE(tstring, iterationFormat) t
|
|
||||||
fileName='OUTPUT_' // tstring// '_' // species(i)%obj%name // '.msh'
|
|
||||||
WRITE(*, "(6X,A15,A)") "Creating file: ", fileName
|
|
||||||
OPEN (60, file = path // folder // '/' // fileName)
|
|
||||||
WRITE(60, "(A)") '$MeshFormat'
|
|
||||||
WRITE(60, "(A)") '2.2 0 8'
|
|
||||||
WRITE(60, "(A)") '$EndMeshFormat'
|
|
||||||
WRITE(60, "(A)") '$NodeData'
|
|
||||||
WRITE(60, "(A)") '1'
|
|
||||||
WRITE(60, "(A)") '"Density ' // species(i)%obj%name // ' (m^-3)"'
|
|
||||||
WRITE(60, *) 1
|
|
||||||
WRITE(60, *) time
|
|
||||||
WRITE(60, *) 3
|
|
||||||
WRITE(60, *) t
|
|
||||||
WRITE(60, *) 1
|
|
||||||
WRITE(60, *) self%numNodes
|
|
||||||
DO n=1, self%numNodes
|
|
||||||
CALL calculateOutput(self%nodes(n)%obj%output(i), output(n), self%nodes(n)%obj%v, species(i)%obj)
|
|
||||||
WRITE(60, "(I6,ES20.6E3)") n, output(n)%density
|
|
||||||
END DO
|
END DO
|
||||||
WRITE(60, "(A)") '$EndNodeData'
|
!$OMP END DO
|
||||||
WRITE(60, "(A)") '$NodeData'
|
|
||||||
WRITE(60, "(A)") '1'
|
|
||||||
WRITE(60, "(A)") '"Velocity ' // species(i)%obj%name // ' (m/s)"'
|
|
||||||
WRITE(60, *) 1
|
|
||||||
WRITE(60, *) time
|
|
||||||
WRITE(60, *) 3
|
|
||||||
WRITE(60, *) t
|
|
||||||
WRITE(60, *) 3
|
|
||||||
WRITE(60, *) self%numNodes
|
|
||||||
DO n=1, self%numNodes
|
|
||||||
WRITE(60, "(I6,3(ES20.6E3))") n, output(n)%velocity
|
|
||||||
END DO
|
|
||||||
WRITE(60, "(A)") '$EndNodeData'
|
|
||||||
WRITE(60, "(A)") '$NodeData'
|
|
||||||
WRITE(60, "(A)") '1'
|
|
||||||
WRITE(60, "(A)") '"Pressure ' // species(i)%obj%name // ' (Pa)"'
|
|
||||||
WRITE(60, *) 1
|
|
||||||
WRITE(60, *) time
|
|
||||||
WRITE(60, *) 3
|
|
||||||
WRITE(60, *) t
|
|
||||||
WRITE(60, *) 1
|
|
||||||
WRITE(60, *) self%numNodes
|
|
||||||
DO n=1, self%numNodes
|
|
||||||
WRITE(60, "(I6,3(ES20.6E3))") n, output(n)%pressure
|
|
||||||
END DO
|
|
||||||
WRITE(60, "(A)") '$EndNodeData'
|
|
||||||
WRITE(60, "(A)") '$NodeData'
|
|
||||||
WRITE(60, "(A)") '1'
|
|
||||||
WRITE(60, "(A)") '"Temperature ' // species(i)%obj%name // ' (K)"'
|
|
||||||
WRITE(60, *) 1
|
|
||||||
WRITE(60, *) time
|
|
||||||
WRITE(60, *) 3
|
|
||||||
WRITE(60, *) t
|
|
||||||
WRITE(60, *) 1
|
|
||||||
WRITE(60, *) self%numNodes
|
|
||||||
DO n=1, self%numNodes
|
|
||||||
WRITE(60, "(I6,3(ES20.6E3))") n, output(n)%temperature
|
|
||||||
END DO
|
|
||||||
WRITE(60, "(A)") '$EndNodeData'
|
|
||||||
CLOSE (60)
|
|
||||||
|
|
||||||
END DO
|
END SUBROUTINE doCollisions
|
||||||
|
|
||||||
END SUBROUTINE printOutputGmsh
|
SUBROUTINE doCoulomb(self)
|
||||||
|
IMPORT meshParticles
|
||||||
|
|
||||||
SUBROUTINE printCollGmsh(self, t)
|
CLASS(meshParticles), INTENT(inout):: self
|
||||||
USE moduleRefParam
|
|
||||||
USE moduleCaseParam
|
|
||||||
USE moduleCollisions
|
|
||||||
USE moduleOutput
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
CLASS(meshGeneric), INTENT(in):: self
|
END SUBROUTINE doCoulomb
|
||||||
INTEGER, INTENT(in):: t
|
|
||||||
INTEGER:: n
|
|
||||||
REAL(8):: time
|
|
||||||
CHARACTER(:), ALLOCATABLE:: fileName
|
|
||||||
CHARACTER (LEN=iterationDigits):: tstring
|
|
||||||
|
|
||||||
|
|
||||||
IF (collOutput) THEN
|
|
||||||
time = DBLE(t)*tauMin*ti_ref
|
|
||||||
WRITE(tstring, iterationFormat) t
|
|
||||||
|
|
||||||
fileName='OUTPUT_' // tstring// '_Collisions.msh'
|
|
||||||
WRITE(*, "(6X,A15,A)") "Creating file: ", fileName
|
|
||||||
OPEN (60, file = path // folder // '/' // fileName)
|
|
||||||
WRITE(60, "(A)") '$MeshFormat'
|
|
||||||
WRITE(60, "(A)") '2.2 0 8'
|
|
||||||
WRITE(60, "(A)") '$EndMeshFormat'
|
|
||||||
WRITE(60, "(A)") '$ElementData'
|
|
||||||
WRITE(60, "(A)") '1'
|
|
||||||
WRITE(60, "(A)") '"Collisions"'
|
|
||||||
WRITE(60, *) 1
|
|
||||||
WRITE(60, *) time
|
|
||||||
WRITE(60, *) 3
|
|
||||||
WRITE(60, *) t
|
|
||||||
WRITE(60, *) 1
|
|
||||||
WRITE(60, *) self%numVols
|
|
||||||
DO n=1, self%numVols
|
|
||||||
WRITE(60, "(I6,I10)") n + self%numEdges, self%vols(n)%obj%nColl
|
|
||||||
END DO
|
|
||||||
WRITE(60, "(A)") '$EndElementData'
|
|
||||||
|
|
||||||
CLOSE(60)
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END SUBROUTINE printCollGmsh
|
|
||||||
|
|
||||||
SUBROUTINE printEMGmsh(self, t)
|
|
||||||
USE moduleRefParam
|
|
||||||
USE moduleCaseParam
|
|
||||||
USE moduleOutput
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
CLASS(meshGeneric), INTENT(in):: self
|
|
||||||
INTEGER, INTENT(in):: t
|
|
||||||
INTEGER:: n, e
|
|
||||||
REAL(8):: time
|
|
||||||
CHARACTER(:), ALLOCATABLE:: fileName
|
|
||||||
CHARACTER (LEN=iterationDigits):: tstring
|
|
||||||
REAL(8):: xi(1:3)
|
|
||||||
|
|
||||||
xi = (/ 0.D0, 0.D0, 0.D0 /)
|
|
||||||
|
|
||||||
IF (emOutput) THEN
|
|
||||||
time = DBLE(t)*tauMin*ti_ref
|
|
||||||
WRITE(tstring, iterationFormat) t
|
|
||||||
|
|
||||||
fileName='OUTPUT_' // tstring// '_EMField.msh'
|
|
||||||
WRITE(*, "(6X,A15,A)") "Creating file: ", fileName
|
|
||||||
OPEN (20, file = path // folder // '/' // fileName)
|
|
||||||
WRITE(20, "(A)") '$MeshFormat'
|
|
||||||
WRITE(20, "(A)") '2.2 0 8'
|
|
||||||
WRITE(20, "(A)") '$EndMeshFormat'
|
|
||||||
WRITE(20, "(A)") '$NodeData'
|
|
||||||
WRITE(20, "(A)") '1'
|
|
||||||
WRITE(20, "(A)") '"Potential (V)"'
|
|
||||||
WRITE(20, *) 1
|
|
||||||
WRITE(20, *) time
|
|
||||||
WRITE(20, *) 3
|
|
||||||
WRITE(20, *) t
|
|
||||||
WRITE(20, *) 1
|
|
||||||
WRITE(20, *) self%numNodes
|
|
||||||
DO n=1, self%numNodes
|
|
||||||
WRITE(20, *) n, self%nodes(n)%obj%emData%phi*Volt_ref
|
|
||||||
END DO
|
|
||||||
WRITE(20, "(A)") '$EndNodeData'
|
|
||||||
|
|
||||||
WRITE(20, "(A)") '$ElementData'
|
|
||||||
WRITE(20, "(A)") '1'
|
|
||||||
WRITE(20, "(A)") '"Electric Field (V/m)"'
|
|
||||||
WRITE(20, *) 1
|
|
||||||
WRITE(20, *) time
|
|
||||||
WRITE(20, *) 3
|
|
||||||
WRITE(20, *) t
|
|
||||||
WRITE(20, *) 3
|
|
||||||
WRITE(20, *) self%numVols
|
|
||||||
DO e=1, self%numVols
|
|
||||||
WRITE(20, *) e+self%numEdges, self%vols(e)%obj%gatherEF(xi)*EF_ref
|
|
||||||
END DO
|
|
||||||
WRITE(20, "(A)") '$EndElementData'
|
|
||||||
CLOSE(20)
|
|
||||||
|
|
||||||
END IF
|
|
||||||
|
|
||||||
END SUBROUTINE printEMGmsh
|
|
||||||
|
|
||||||
END MODULE moduleMesh
|
END MODULE moduleMesh
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,6 @@ MODULE moduleMeshBoundary
|
||||||
!rpp = final position of particle
|
!rpp = final position of particle
|
||||||
!vpp = final velocity of particle
|
!vpp = final velocity of particle
|
||||||
REAL(8), DIMENSION(1:3):: rp, vpp
|
REAL(8), DIMENSION(1:3):: rp, vpp
|
||||||
REAL(8):: tI
|
|
||||||
REAL(8):: taup !time step for reflecting process
|
|
||||||
|
|
||||||
!Reflect particle velocity
|
!Reflect particle velocity
|
||||||
vpp = part%v - 2.D0*DOT_PRODUCT(part%v, edge%normal)*edge%normal
|
vpp = part%v - 2.D0*DOT_PRODUCT(part%v, edge%normal)*edge%normal
|
||||||
|
|
@ -91,7 +89,7 @@ MODULE moduleMeshBoundary
|
||||||
INTEGER:: i
|
INTEGER:: i
|
||||||
|
|
||||||
!Modifies particle velocity according to wall temperature
|
!Modifies particle velocity according to wall temperature
|
||||||
SELECT TYPE(bound => edge%boundary%bTypes(part%sp)%obj)
|
SELECT TYPE(bound => edge%boundary%bTypes(part%species%n)%obj)
|
||||||
TYPE IS(boundaryWallTemperature)
|
TYPE IS(boundaryWallTemperature)
|
||||||
DO i = 1, 3
|
DO i = 1, 3
|
||||||
part%v(i) = part%v(i) + bound%vTh*randomMaxwellian()
|
part%v(i) = part%v(i) + bound%vTh*randomMaxwellian()
|
||||||
|
|
@ -123,9 +121,9 @@ MODULE moduleMeshBoundary
|
||||||
TYPE(particle), POINTER:: newElectron
|
TYPE(particle), POINTER:: newElectron
|
||||||
TYPE(particle), POINTER:: newIon
|
TYPE(particle), POINTER:: newIon
|
||||||
|
|
||||||
SELECT TYPE(bound => edge%boundary%bTypes(part%sp)%obj)
|
SELECT TYPE(bound => edge%boundary%bTypes(part%species%n)%obj)
|
||||||
TYPE IS(boundaryIonization)
|
TYPE IS(boundaryIonization)
|
||||||
mRel = (bound%m0*species(part%sp)%obj%m)*(bound%m0+species(part%sp)%obj%m)
|
mRel = (bound%m0*part%species%m)*(bound%m0+part%species%m)
|
||||||
vRel = SUM(DABS(part%v-bound%v0))
|
vRel = SUM(DABS(part%v-bound%v0))
|
||||||
eRel = mRel*vRel**2*5.D-1
|
eRel = mRel*vRel**2*5.D-1
|
||||||
|
|
||||||
|
|
@ -133,7 +131,7 @@ MODULE moduleMeshBoundary
|
||||||
ionizationRate = part%weight*bound%n0*bound%crossSection%get(eRel)*vRel
|
ionizationRate = part%weight*bound%n0*bound%crossSection%get(eRel)*vRel
|
||||||
|
|
||||||
!Rounds the number of particles up
|
!Rounds the number of particles up
|
||||||
ionizationPair = NINT(ionizationRate*bound%effectiveTime/species(bound%sp)%obj%weight)
|
ionizationPair = NINT(ionizationRate*bound%effectiveTime/bound%species%weight)
|
||||||
|
|
||||||
!Create the new pair of particles
|
!Create the new pair of particles
|
||||||
DO p = 1, ionizationPair
|
DO p = 1, ionizationPair
|
||||||
|
|
@ -146,8 +144,8 @@ MODULE moduleMeshBoundary
|
||||||
ALLOCATE(newElectron)
|
ALLOCATE(newElectron)
|
||||||
ALLOCATE(newIon)
|
ALLOCATE(newIon)
|
||||||
|
|
||||||
newElectron%sp = part%sp
|
newElectron%species => part%species
|
||||||
newIon%sp = bound%sp
|
newIon%species => bound%species
|
||||||
|
|
||||||
newElectron%v = v0 + (1.D0 + bound%deltaV*v0/NORM2(v0))
|
newElectron%v = v0 + (1.D0 + bound%deltaV*v0/NORM2(v0))
|
||||||
newIon%v = v0
|
newIon%v = v0
|
||||||
|
|
@ -162,13 +160,13 @@ MODULE moduleMeshBoundary
|
||||||
newIon%xi = newElectron%xi
|
newIon%xi = newElectron%xi
|
||||||
|
|
||||||
newElectron%qm = part%qm
|
newElectron%qm = part%qm
|
||||||
SELECT TYPE(spe => species(bound%sp)%obj)
|
SELECT TYPE(spe => bound%species)
|
||||||
TYPE IS(speciesCharged)
|
TYPE IS(speciesCharged)
|
||||||
newIon%qm = spe%qm
|
newIon%qm = spe%qm
|
||||||
|
|
||||||
END SELECT
|
END SELECT
|
||||||
|
|
||||||
newElectron%weight = species(bound%sp)%obj%weight
|
newElectron%weight = bound%species%weight
|
||||||
newIon%weight = newElectron%weight
|
newIon%weight = newElectron%weight
|
||||||
|
|
||||||
newElectron%n_in = .TRUE.
|
newElectron%n_in = .TRUE.
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
MODULE moduleBoundary
|
MODULE moduleBoundary
|
||||||
USE moduleTable
|
USE moduleTable
|
||||||
|
USE moduleSpecies
|
||||||
|
|
||||||
!Generic type for boundaries
|
!Generic type for boundaries
|
||||||
TYPE, PUBLIC:: boundaryGeneric
|
TYPE, PUBLIC:: boundaryGeneric
|
||||||
|
|
@ -36,12 +37,11 @@ MODULE moduleBoundary
|
||||||
!Ionization boundary
|
!Ionization boundary
|
||||||
TYPE, PUBLIC, EXTENDS(boundaryGeneric):: boundaryIonization
|
TYPE, PUBLIC, EXTENDS(boundaryGeneric):: boundaryIonization
|
||||||
REAL(8):: m0, n0, v0(1:3), vTh !Properties of background neutrals.
|
REAL(8):: m0, n0, v0(1:3), vTh !Properties of background neutrals.
|
||||||
INTEGER:: sp !Ion species
|
CLASS(speciesGeneric), POINTER:: species !Ion species
|
||||||
TYPE(table1D):: crossSection
|
TYPE(table1D):: crossSection
|
||||||
REAL(8):: effectiveTime
|
REAL(8):: effectiveTime
|
||||||
REAL(8):: eThreshold
|
REAL(8):: eThreshold
|
||||||
REAL(8):: deltaV
|
REAL(8):: deltaV
|
||||||
|
|
||||||
CONTAINS
|
CONTAINS
|
||||||
|
|
||||||
END TYPE boundaryIonization
|
END TYPE boundaryIonization
|
||||||
|
|
@ -52,23 +52,26 @@ MODULE moduleBoundary
|
||||||
|
|
||||||
END TYPE boundaryAxis
|
END TYPE boundaryAxis
|
||||||
|
|
||||||
|
!Wrapper for boundary types (one per species)
|
||||||
TYPE:: bTypesCont
|
TYPE:: bTypesCont
|
||||||
CLASS(boundaryGeneric), ALLOCATABLE:: obj
|
CLASS(boundaryGeneric), ALLOCATABLE:: obj
|
||||||
|
CONTAINS
|
||||||
|
|
||||||
END TYPE bTypesCont
|
END TYPE bTypesCont
|
||||||
|
|
||||||
|
!Wrapper for boundary conditions
|
||||||
TYPE:: boundaryCont
|
TYPE:: boundaryCont
|
||||||
INTEGER:: id = 0
|
INTEGER:: n = 0
|
||||||
CHARACTER(:), ALLOCATABLE:: name
|
CHARACTER(:), ALLOCATABLE:: name
|
||||||
INTEGER:: physicalSurface = 0
|
INTEGER:: physicalSurface = 0 !Physical surface as defined in the mesh file
|
||||||
CLASS(bTypesCont), ALLOCATABLE:: bTypes(:)
|
CLASS(bTypesCont), ALLOCATABLE:: bTypes(:) !Array for boundary per species
|
||||||
CONTAINS
|
CONTAINS
|
||||||
|
|
||||||
END TYPE boundaryCont
|
END TYPE boundaryCont
|
||||||
|
|
||||||
!Number of boundaries
|
!Number of boundaries
|
||||||
INTEGER:: nBoundary = 0
|
INTEGER:: nBoundary = 0
|
||||||
!Array for boundary information
|
!Array for boundaries
|
||||||
TYPE(boundaryCont), ALLOCATABLE, TARGET:: boundary(:)
|
TYPE(boundaryCont), ALLOCATABLE, TARGET:: boundary(:)
|
||||||
|
|
||||||
CONTAINS
|
CONTAINS
|
||||||
|
|
@ -81,7 +84,7 @@ MODULE moduleBoundary
|
||||||
|
|
||||||
id = 0
|
id = 0
|
||||||
DO i = 1, nBoundary
|
DO i = 1, nBoundary
|
||||||
IF (physicalSurface == boundary(i)%physicalSurface) id = boundary(i)%id
|
IF (physicalSurface == boundary(i)%physicalSurface) id = boundary(i)%n
|
||||||
|
|
||||||
END DO
|
END DO
|
||||||
|
|
||||||
|
|
@ -123,7 +126,7 @@ MODULE moduleBoundary
|
||||||
boundary%n0 = n0 * Vol_ref
|
boundary%n0 = n0 * Vol_ref
|
||||||
boundary%v0 = v0 / v_ref
|
boundary%v0 = v0 / v_ref
|
||||||
boundary%vTh = DSQRT(kb*T0/m0)/v_ref
|
boundary%vTh = DSQRT(kb*T0/m0)/v_ref
|
||||||
boundary%sp = speciesID
|
boundary%species => species(speciesID)%obj
|
||||||
boundary%effectiveTime = effTime / ti_ref
|
boundary%effectiveTime = effTime / ti_ref
|
||||||
CALL boundary%crossSection%init(crossSection)
|
CALL boundary%crossSection%init(crossSection)
|
||||||
CALL boundary%crossSection%convert(eV2J/(m_ref*v_ref**2), 1.D0/L_ref**2)
|
CALL boundary%crossSection%convert(eV2J/(m_ref*v_ref**2), 1.D0/L_ref**2)
|
||||||
|
|
|
||||||
|
|
@ -199,8 +199,8 @@ MODULE moduleCollisions
|
||||||
sigmaVrel = self%crossSec%get(eRel)*vRel
|
sigmaVrel = self%crossSec%get(eRel)*vRel
|
||||||
sigmaVrelMaxNew = sigmaVrelMaxNew + sigmaVrel
|
sigmaVrelMaxNew = sigmaVrelMaxNew + sigmaVrel
|
||||||
IF (sigmaVrelMaxNew/sigmaVrelMax > random()) THEN
|
IF (sigmaVrelMaxNew/sigmaVrelMax > random()) THEN
|
||||||
m_i = species(part_i%sp)%obj%m
|
m_i = part_i%species%m
|
||||||
m_j = species(part_j%sp)%obj%m
|
m_j = part_j%species%m
|
||||||
!Applies the collision
|
!Applies the collision
|
||||||
vCM = velocityCM(m_i, part_i%v, m_j, part_j%v)
|
vCM = velocityCM(m_i, part_i%v, m_j, part_j%v)
|
||||||
vp = vRel*randomDirectionVHS()
|
vp = vRel*randomDirectionVHS()
|
||||||
|
|
@ -292,11 +292,11 @@ MODULE moduleCollisions
|
||||||
sigmaVrelMaxNew = sigmaVrelMaxNew + sigmaVrel
|
sigmaVrelMaxNew = sigmaVrelMaxNew + sigmaVrel
|
||||||
IF (sigmaVrelMaxNew/sigmaVrelMax > random()) THEN
|
IF (sigmaVrelMaxNew/sigmaVrelMax > random()) THEN
|
||||||
!Find which particle is the ionizing electron
|
!Find which particle is the ionizing electron
|
||||||
IF (part_i%sp == self%electron%sp) THEN
|
IF (ASSOCIATED(part_i%species, self%electron)) THEN
|
||||||
electron => part_i
|
electron => part_i
|
||||||
neutral => part_j
|
neutral => part_j
|
||||||
|
|
||||||
ELSEIF(part_j%sp == self%electron%sp) THEN
|
ELSEIF(ASSOCIATED(part_j%species, self%electron)) THEN
|
||||||
electron => part_j
|
electron => part_j
|
||||||
neutral => part_i
|
neutral => part_i
|
||||||
|
|
||||||
|
|
@ -314,17 +314,18 @@ MODULE moduleCollisions
|
||||||
|
|
||||||
!Creates a new electron from ionization
|
!Creates a new electron from ionization
|
||||||
ALLOCATE(newElectron)
|
ALLOCATE(newElectron)
|
||||||
newElectron%sp = electron%sp
|
newElectron%species => electron%species
|
||||||
newElectron%v = vp_n
|
newElectron%v = vp_n
|
||||||
newElectron%r = neutral%r
|
newElectron%r = neutral%r
|
||||||
newElectron%xi = neutral%xi
|
newElectron%xi = neutral%xi
|
||||||
newElectron%n_in = .TRUE.
|
newElectron%n_in = .TRUE.
|
||||||
newElectron%vol = neutral%vol
|
newElectron%vol = neutral%vol
|
||||||
|
newElectron%volColl = neutral%volColl
|
||||||
newElectron%weight = neutral%weight
|
newElectron%weight = neutral%weight
|
||||||
newElectron%qm = electron%qm
|
newElectron%qm = electron%qm
|
||||||
|
|
||||||
!Ionize neutral particle
|
!Ionize neutral particle
|
||||||
SELECT TYPE(sp => species(neutral%sp)%obj)
|
SELECT TYPE(sp => neutral%species)
|
||||||
TYPE IS(speciesNeutral)
|
TYPE IS(speciesNeutral)
|
||||||
CALL sp%ionize(neutral)
|
CALL sp%ionize(neutral)
|
||||||
|
|
||||||
|
|
@ -421,11 +422,11 @@ MODULE moduleCollisions
|
||||||
sigmaVrelMaxNew = sigmaVrelMaxNew + sigmaVrel
|
sigmaVrelMaxNew = sigmaVrelMaxNew + sigmaVrel
|
||||||
IF (sigmaVrelMaxNew/sigmaVrelMax > random()) THEN
|
IF (sigmaVrelMaxNew/sigmaVrelMax > random()) THEN
|
||||||
!Find which particle is the ionizing electron
|
!Find which particle is the ionizing electron
|
||||||
IF (part_i%sp == self%electron%sp) THEN
|
IF (ASSOCIATED(part_i%species, self%electron)) THEN
|
||||||
electron => part_i
|
electron => part_i
|
||||||
ion => part_j
|
ion => part_j
|
||||||
|
|
||||||
ELSEIF(part_j%sp == self%electron%sp) THEN
|
ELSEIF(ASSOCIATED(part_j%species, self%electron)) THEN
|
||||||
electron => part_j
|
electron => part_j
|
||||||
ion => part_i
|
ion => part_i
|
||||||
|
|
||||||
|
|
@ -442,7 +443,7 @@ MODULE moduleCollisions
|
||||||
electron%n_in = .FALSE.
|
electron%n_in = .FALSE.
|
||||||
|
|
||||||
!Neutralize ion particle
|
!Neutralize ion particle
|
||||||
SELECT TYPE(sp => species(ion%sp)%obj)
|
SELECT TYPE(sp => ion%species)
|
||||||
TYPE IS(speciesCharged)
|
TYPE IS(speciesCharged)
|
||||||
CALL sp%neutralize(ion)
|
CALL sp%neutralize(ion)
|
||||||
|
|
||||||
|
|
@ -501,7 +502,7 @@ MODULE moduleCollisions
|
||||||
sigmaVrel = self%crossSec%get(eRel)*vRel
|
sigmaVrel = self%crossSec%get(eRel)*vRel
|
||||||
sigmaVrelMaxNew = sigmaVrelMaxNew + sigmaVrel
|
sigmaVrelMaxNew = sigmaVrelMaxNew + sigmaVrel
|
||||||
IF (sigmaVrelMaxNew/sigmaVrelMax > random()) THEN
|
IF (sigmaVrelMaxNew/sigmaVrelMax > random()) THEN
|
||||||
SELECT TYPE(sp => species(part_i%sp)%obj)
|
SELECT TYPE(sp => part_i%species)
|
||||||
TYPE IS (speciesNeutral)
|
TYPE IS (speciesNeutral)
|
||||||
!Species i is neutral, ionize particle i
|
!Species i is neutral, ionize particle i
|
||||||
CALL sp%ionize(part_i)
|
CALL sp%ionize(part_i)
|
||||||
|
|
@ -512,7 +513,7 @@ MODULE moduleCollisions
|
||||||
|
|
||||||
END SELECT
|
END SELECT
|
||||||
|
|
||||||
SELECT TYPE(sp => species(part_j%sp)%obj)
|
SELECT TYPE(sp => part_j%species)
|
||||||
TYPE IS (speciesNeutral)
|
TYPE IS (speciesNeutral)
|
||||||
!Species j is neutral, ionize particle j
|
!Species j is neutral, ionize particle j
|
||||||
CALL sp%ionize(part_j)
|
CALL sp%ionize(part_j)
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ MODULE moduleCompTime
|
||||||
REAL(8):: tPush = 0.D0
|
REAL(8):: tPush = 0.D0
|
||||||
REAL(8):: tReset = 0.D0
|
REAL(8):: tReset = 0.D0
|
||||||
REAL(8):: tColl = 0.D0
|
REAL(8):: tColl = 0.D0
|
||||||
|
REAL(8):: tCoul = 0.D0
|
||||||
REAL(8):: tWeight = 0.D0
|
REAL(8):: tWeight = 0.D0
|
||||||
REAL(8):: tEMField = 0.D0
|
REAL(8):: tEMField = 0.D0
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
!injection of particles
|
!injection of particles
|
||||||
MODULE moduleInject
|
MODULE moduleInject
|
||||||
|
USE moduleSpecies
|
||||||
|
|
||||||
!Generic type for velocity distribution function
|
!Generic type for velocity distribution function
|
||||||
TYPE, ABSTRACT:: velDistGeneric
|
TYPE, ABSTRACT:: velDistGeneric
|
||||||
|
|
@ -51,7 +52,7 @@ MODULE moduleInject
|
||||||
REAL(8):: T(1:3) !Temperature
|
REAL(8):: T(1:3) !Temperature
|
||||||
REAL(8):: n(1:3) !Direction of injection
|
REAL(8):: n(1:3) !Direction of injection
|
||||||
INTEGER:: nParticles !Number of particles to introduce each time step
|
INTEGER:: nParticles !Number of particles to introduce each time step
|
||||||
INTEGER:: sp !Species of injection
|
CLASS(speciesGeneric), POINTER:: species !Species of injection
|
||||||
INTEGER:: nEdges
|
INTEGER:: nEdges
|
||||||
INTEGER, ALLOCATABLE:: edges(:) !Array with edges
|
INTEGER, ALLOCATABLE:: edges(:) !Array with edges
|
||||||
REAL(8), ALLOCATABLE:: cumWeight(:) !Array of cummulative probability
|
REAL(8), ALLOCATABLE:: cumWeight(:) !Array of cummulative probability
|
||||||
|
|
@ -85,12 +86,13 @@ MODULE moduleInject
|
||||||
CHARACTER(:), ALLOCATABLE, INTENT(in):: units
|
CHARACTER(:), ALLOCATABLE, INTENT(in):: units
|
||||||
INTEGER:: e, et
|
INTEGER:: e, et
|
||||||
INTEGER:: phSurface(1:mesh%numEdges)
|
INTEGER:: phSurface(1:mesh%numEdges)
|
||||||
|
INTEGER:: nVolColl
|
||||||
|
|
||||||
self%id = i
|
self%id = i
|
||||||
self%vMod = v/v_ref
|
self%vMod = v/v_ref
|
||||||
self%n = n
|
self%n = n
|
||||||
self%T = T/T_ref
|
self%T = T/T_ref
|
||||||
self%sp = sp
|
self%species => species(sp)%obj
|
||||||
SELECT CASE(units)
|
SELECT CASE(units)
|
||||||
CASE ("sccm")
|
CASE ("sccm")
|
||||||
!Standard cubic centimeter per minute
|
!Standard cubic centimeter per minute
|
||||||
|
|
@ -124,6 +126,27 @@ MODULE moduleInject
|
||||||
IF (mesh%edges(e)%obj%physicalSurface == physicalSurface) THEN
|
IF (mesh%edges(e)%obj%physicalSurface == physicalSurface) THEN
|
||||||
et = et + 1
|
et = et + 1
|
||||||
self%edges(et) = mesh%edges(e)%obj%n
|
self%edges(et) = mesh%edges(e)%obj%n
|
||||||
|
!Assign connectivity between injection edge and meshColl volume
|
||||||
|
IF (ASSOCIATED(meshForMCC, meshColl)) THEN
|
||||||
|
nVolColl = findCellBrute(meshColl, mesh%edges(e)%obj%randPos())
|
||||||
|
IF (nVolColl > 0) THEN
|
||||||
|
mesh%edges(e)%obj%eColl => meshColl%vols(nVolColl)%obj
|
||||||
|
|
||||||
|
ELSE
|
||||||
|
CALL criticalError("No connection between edge and meshColl", "initInject")
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
ELSE
|
||||||
|
IF (ASSOCIATED(mesh%edges(e)%obj%e1)) THEN
|
||||||
|
mesh%edges(e)%obj%eColl => mesh%edges(e)%obj%e1
|
||||||
|
|
||||||
|
ELSE
|
||||||
|
mesh%edges(e)%obj%eColl => mesh%edges(e)%obj%e2
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
END IF
|
END IF
|
||||||
|
|
||||||
|
|
@ -224,14 +247,12 @@ MODULE moduleInject
|
||||||
!$OMP SINGLE
|
!$OMP SINGLE
|
||||||
nMin = SUM(inject(1:(self%id-1))%nParticles) + 1
|
nMin = SUM(inject(1:(self%id-1))%nParticles) + 1
|
||||||
nMax = nMin + self%nParticles - 1
|
nMax = nMin + self%nParticles - 1
|
||||||
!Assign particle type
|
|
||||||
partInj(nMin:nMax)%sp = self%sp
|
|
||||||
!Assign weight to particle.
|
!Assign weight to particle.
|
||||||
partInj(nMin:nMax)%weight = species(self%sp)%obj%weight
|
partInj(nMin:nMax)%weight = self%species%weight
|
||||||
!Particle is considered to be outside the domain
|
!Particle is considered to be outside the domain
|
||||||
partInj(nMin:nMax)%n_in = .FALSE.
|
partInj(nMin:nMax)%n_in = .FALSE.
|
||||||
!Assign charge/mass to charged particle.
|
!Assign charge/mass to charged particle.
|
||||||
SELECT TYPE(sp => species(self%sp)%obj)
|
SELECT TYPE(sp => self%species)
|
||||||
TYPE IS(speciesCharged)
|
TYPE IS(speciesCharged)
|
||||||
partInj(nMin:nMax)%qm = sp%qm
|
partInj(nMin:nMax)%qm = sp%qm
|
||||||
|
|
||||||
|
|
@ -256,6 +277,10 @@ MODULE moduleInject
|
||||||
CALL criticalError("No Volume associated to edge", 'addParticles')
|
CALL criticalError("No Volume associated to edge", 'addParticles')
|
||||||
|
|
||||||
END IF
|
END IF
|
||||||
|
partInj(n)%volColl = randomEdge%eColl%n
|
||||||
|
|
||||||
|
!Assign particle type
|
||||||
|
partInj(n)%species => self%species
|
||||||
|
|
||||||
partInj(n)%v = (/ self%v(1)%obj%randomVel(), &
|
partInj(n)%v = (/ self%v(1)%obj%randomVel(), &
|
||||||
self%v(2)%obj%randomVel(), &
|
self%v(2)%obj%randomVel(), &
|
||||||
|
|
@ -264,7 +289,7 @@ MODULE moduleInject
|
||||||
!Obtain natural coordinates of particle in cell
|
!Obtain natural coordinates of particle in cell
|
||||||
partInj(n)%xi = mesh%vols(partInj(n)%vol)%obj%phy2log(partInj(n)%r)
|
partInj(n)%xi = mesh%vols(partInj(n)%vol)%obj%phy2log(partInj(n)%r)
|
||||||
!Push new particle with the minimum time step
|
!Push new particle with the minimum time step
|
||||||
CALL solver%pusher(self%sp)%pushParticle(partInj(n), tauMin)
|
CALL solver%pusher(self%species%n)%pushParticle(partInj(n), tauMin)
|
||||||
!Assign cell to new particle
|
!Assign cell to new particle
|
||||||
CALL solver%updateParticleCell(partInj(n))
|
CALL solver%updateParticleCell(partInj(n))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ MODULE moduleInput
|
||||||
CALL checkStatus(config, "readCase")
|
CALL checkStatus(config, "readCase")
|
||||||
|
|
||||||
!Read injection of particles
|
!Read injection of particles
|
||||||
CALL verboseError('Reading Interactions between species...')
|
CALL verboseError('Reading injection of particles from boundaries...')
|
||||||
CALL readInject(config)
|
CALL readInject(config)
|
||||||
CALL checkStatus(config, "readInject")
|
CALL checkStatus(config, "readInject")
|
||||||
|
|
||||||
|
|
@ -283,7 +283,7 @@ MODULE moduleInput
|
||||||
!Allocate new particles
|
!Allocate new particles
|
||||||
DO p = 1, nNewPart
|
DO p = 1, nNewPart
|
||||||
ALLOCATE(partNew)
|
ALLOCATE(partNew)
|
||||||
partNew%sp = sp
|
partNew%species => species(sp)%obj
|
||||||
partNew%v(1) = velocity(1) + vTh*randomMaxwellian()
|
partNew%v(1) = velocity(1) + vTh*randomMaxwellian()
|
||||||
partNew%v(2) = velocity(2) + vTh*randomMaxwellian()
|
partNew%v(2) = velocity(2) + vTh*randomMaxwellian()
|
||||||
partNew%v(3) = velocity(3) + vTh*randomMaxwellian()
|
partNew%v(3) = velocity(3) + vTh*randomMaxwellian()
|
||||||
|
|
@ -442,7 +442,7 @@ MODULE moduleInput
|
||||||
!Assign shared parameters for all species
|
!Assign shared parameters for all species
|
||||||
CALL config%get(object // '.name', species(i)%obj%name, found)
|
CALL config%get(object // '.name', species(i)%obj%name, found)
|
||||||
CALL config%get(object // '.weight', species(i)%obj%weight, found)
|
CALL config%get(object // '.weight', species(i)%obj%weight, found)
|
||||||
species(i)%obj%sp = i
|
species(i)%obj%n = i
|
||||||
species(i)%obj%m = mass
|
species(i)%obj%m = mass
|
||||||
|
|
||||||
END DO
|
END DO
|
||||||
|
|
@ -483,7 +483,6 @@ MODULE moduleInput
|
||||||
END DO
|
END DO
|
||||||
|
|
||||||
!Set number of particles to 0 for init state
|
!Set number of particles to 0 for init state
|
||||||
!TODO: In a future, this should include the particles from init states
|
|
||||||
nPartOld = 0
|
nPartOld = 0
|
||||||
|
|
||||||
!Initialize the lock for the non-analogue (NA) list of particles
|
!Initialize the lock for the non-analogue (NA) list of particles
|
||||||
|
|
@ -497,6 +496,7 @@ MODULE moduleInput
|
||||||
USE moduleList
|
USE moduleList
|
||||||
USE moduleCollisions
|
USE moduleCollisions
|
||||||
USE moduleErrors
|
USE moduleErrors
|
||||||
|
USE moduleMesh
|
||||||
USE OMP_LIB
|
USE OMP_LIB
|
||||||
USE json_module
|
USE json_module
|
||||||
IMPLICIT NONE
|
IMPLICIT NONE
|
||||||
|
|
@ -515,6 +515,26 @@ MODULE moduleInput
|
||||||
REAL(8):: energyThreshold, energyBinding
|
REAL(8):: energyThreshold, energyBinding
|
||||||
CHARACTER(:), ALLOCATABLE:: electron
|
CHARACTER(:), ALLOCATABLE:: electron
|
||||||
|
|
||||||
|
!Firstly, checks if the object 'interactions' exists
|
||||||
|
CALL config%info('interactions', found)
|
||||||
|
IF (found) THEN
|
||||||
|
!Checks if MC collisions have been defined
|
||||||
|
CALL config%info('interactions.collisions', found)
|
||||||
|
IF (found) THEN
|
||||||
|
!Checks if a mesh for collisions has been defined
|
||||||
|
!The mesh will be initialized and reader in readGeometry
|
||||||
|
CALL config%info('interactions.meshCollisions', found)
|
||||||
|
IF (found) THEN
|
||||||
|
!Points meshForMCC to the specific mesh defined
|
||||||
|
meshForMCC => meshColl
|
||||||
|
|
||||||
|
ELSE
|
||||||
|
!Points the meshForMCC pointer to the Particles Mesh
|
||||||
|
meshForMCC => mesh
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
!Inits the MCC matrix
|
||||||
CALL initInteractionMatrix(interactionMatrix)
|
CALL initInteractionMatrix(interactionMatrix)
|
||||||
|
|
||||||
!Path for collision cross-section data files
|
!Path for collision cross-section data files
|
||||||
|
|
@ -584,6 +604,10 @@ MODULE moduleInput
|
||||||
|
|
||||||
END DO
|
END DO
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
END SUBROUTINE readInteractions
|
END SUBROUTINE readInteractions
|
||||||
|
|
||||||
!Reads boundary conditions for the mesh
|
!Reads boundary conditions for the mesh
|
||||||
|
|
@ -616,7 +640,7 @@ MODULE moduleInput
|
||||||
WRITE(istring, '(i2)') i
|
WRITE(istring, '(i2)') i
|
||||||
object = 'boundary(' // TRIM(istring) // ')'
|
object = 'boundary(' // TRIM(istring) // ')'
|
||||||
|
|
||||||
boundary(i)%id = i
|
boundary(i)%n = i
|
||||||
CALL config%get(object // '.name', boundary(i)%name, found)
|
CALL config%get(object // '.name', boundary(i)%name, found)
|
||||||
CALL config%get(object // '.physicalSurface', boundary(i)%physicalSurface, found)
|
CALL config%get(object // '.physicalSurface', boundary(i)%physicalSurface, found)
|
||||||
CALL config%info(object // '.bTypes', found, n_children = nTypes)
|
CALL config%info(object // '.bTypes', found, n_children = nTypes)
|
||||||
|
|
@ -689,11 +713,12 @@ MODULE moduleInput
|
||||||
!Read the geometry (mesh) for the case
|
!Read the geometry (mesh) for the case
|
||||||
SUBROUTINE readGeometry(config)
|
SUBROUTINE readGeometry(config)
|
||||||
USE moduleMesh
|
USE moduleMesh
|
||||||
USE moduleMesh3DCartRead, ONLY: mesh3DCartGeneric
|
USE moduleMeshInputGmsh2, ONLY: initGmsh2
|
||||||
USE moduleMesh2DCylRead, ONLY: mesh2DCylGeneric
|
USE moduleMesh3DCart, ONLY: connectMesh3DCart
|
||||||
USE moduleMesh2DCartRead, ONLY: mesh2DCartGeneric
|
USE moduleMesh2DCyl, ONLY: connectMesh2DCyl
|
||||||
USE moduleMesh1DCartRead, ONLY: mesh1DCartGeneric
|
USE moduleMesh2DCart, ONLY: connectMesh2DCart
|
||||||
USE moduleMesh1DRadRead, ONLY: mesh1DRadGeneric
|
USE moduleMesh1DRad, ONLY: connectMesh1DRad
|
||||||
|
USE moduleMesh1DCart, ONLY: connectMesh1DCart
|
||||||
USE moduleErrors
|
USE moduleErrors
|
||||||
USE moduleOutput
|
USE moduleOutput
|
||||||
USE json_module
|
USE json_module
|
||||||
|
|
@ -701,44 +726,79 @@ MODULE moduleInput
|
||||||
|
|
||||||
TYPE(json_file), INTENT(inout):: config
|
TYPE(json_file), INTENT(inout):: config
|
||||||
LOGICAL:: found
|
LOGICAL:: found
|
||||||
CHARACTER(:), ALLOCATABLE:: geometryType, meshFormat, meshFile
|
LOGICAL:: doubleMesh
|
||||||
|
CHARACTER(:), ALLOCATABLE:: meshFormat, meshFile
|
||||||
CHARACTER(:), ALLOCATABLE:: fullPath
|
CHARACTER(:), ALLOCATABLE:: fullPath
|
||||||
|
|
||||||
|
!Firstly, indicates if a specific mesh for MC collisions is being use
|
||||||
|
doubleMesh = ASSOCIATED(meshForMCC, meshColl)
|
||||||
|
|
||||||
!Selects the type of geometry.
|
!Selects the type of geometry.
|
||||||
CALL config%get('geometry.type', geometryType, found)
|
CALL config%get('geometry.type', mesh%geometry, found)
|
||||||
SELECT CASE(geometryType)
|
IF (doubleMesh) meshColl%geometry = mesh%geometry
|
||||||
CASE ("3DCart")
|
|
||||||
!Creates a 3D cylindrical mesh
|
|
||||||
ALLOCATE(mesh3DCartGeneric:: mesh)
|
|
||||||
|
|
||||||
CASE ("2DCyl")
|
|
||||||
!Creates a 2D cylindrical mesh
|
|
||||||
ALLOCATE(mesh2DCylGeneric:: mesh)
|
|
||||||
|
|
||||||
CASE ("2DCart")
|
|
||||||
!Creates a 2D cylindrical mesh
|
|
||||||
ALLOCATE(mesh2DCartGeneric:: mesh)
|
|
||||||
|
|
||||||
CASE ("1DCart")
|
|
||||||
!Creates a 1D cartesian mesh
|
|
||||||
ALLOCATE(mesh1DCartGeneric:: mesh)
|
|
||||||
|
|
||||||
CASE ("1DRad")
|
|
||||||
!Creates a 1D cartesian mesh
|
|
||||||
ALLOCATE(mesh1DRadGeneric:: mesh)
|
|
||||||
|
|
||||||
CASE DEFAULT
|
|
||||||
CALL criticalError("Geometry type " // geometryType // " not supported.", "readGeometry")
|
|
||||||
|
|
||||||
END SELECT
|
|
||||||
|
|
||||||
!Gets the type of mesh
|
!Gets the type of mesh
|
||||||
CALL config%get('geometry.meshType', meshFormat, found)
|
CALL config%get('geometry.meshType', meshFormat, found)
|
||||||
CALL mesh%init(meshFormat)
|
SELECT CASE(meshFormat)
|
||||||
!Reads the mesh
|
CASE ("gmsh2")
|
||||||
|
CALL initGmsh2(mesh)
|
||||||
|
IF (doubleMesh) CALL initGmsh2(meshColl)
|
||||||
|
|
||||||
|
CASE DEFAULT
|
||||||
|
CALL criticalError("Mesh format " // meshFormat // " not recogniced", "readGeometry")
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
!Reads the mesh file
|
||||||
CALL config%get('geometry.meshFile', meshFile, found)
|
CALL config%get('geometry.meshFile', meshFile, found)
|
||||||
fullpath = path // meshFile
|
fullpath = path // meshFile
|
||||||
CALL mesh%readMesh(fullPath)
|
CALL mesh%readMesh(fullPath)
|
||||||
|
DEALLOCATE(fullPath, meshFile)
|
||||||
|
IF (doubleMesh) THEN
|
||||||
|
!Reads the mesh file for collisions
|
||||||
|
CALL config%get('interactions.meshCollisions', meshFile, found)
|
||||||
|
fullpath = path // meshFile
|
||||||
|
CALL meshColl%readMesh(fullPath)
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
!Creates the connectivity between elements
|
||||||
|
SELECT CASE(mesh%geometry)
|
||||||
|
CASE("3DCart")
|
||||||
|
mesh%connectMesh => connectMesh3DCart
|
||||||
|
|
||||||
|
CASE("2DCyl")
|
||||||
|
mesh%connectMesh => connectMesh2DCyl
|
||||||
|
|
||||||
|
CASE("2DCart")
|
||||||
|
mesh%connectMesh => connectMesh2DCart
|
||||||
|
|
||||||
|
CASE("1DRad")
|
||||||
|
mesh%connectMesh => connectMesh1DRad
|
||||||
|
|
||||||
|
CASE("1DCart")
|
||||||
|
mesh%connectMesh => connectMesh1DCart
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
CALL mesh%connectMesh
|
||||||
|
|
||||||
|
IF (doubleMesh) THEN
|
||||||
|
meshColl%connectMesh => mesh%connectMesh
|
||||||
|
CALL meshColl%connectMesh
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
!Builds the K matrix for the Particles mesh
|
||||||
|
CALL mesh%constructGlobalK()
|
||||||
|
|
||||||
|
!Assign the procedure to find a volume for meshColl
|
||||||
|
IF (doubleMesh) THEN
|
||||||
|
findCellColl => findCellCollMesh
|
||||||
|
|
||||||
|
ELSE
|
||||||
|
findCellColl => findCellSameMesh
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
END SUBROUTINE readGeometry
|
END SUBROUTINE readGeometry
|
||||||
|
|
||||||
|
|
@ -894,7 +954,7 @@ MODULE moduleInput
|
||||||
REAL(8):: v, T, m
|
REAL(8):: v, T, m
|
||||||
|
|
||||||
!Reads species mass
|
!Reads species mass
|
||||||
m = species(inj%sp)%obj%m
|
m = inj%species%m
|
||||||
!Reads distribution functions for velocity
|
!Reads distribution functions for velocity
|
||||||
DO i = 1, 3
|
DO i = 1, 3
|
||||||
WRITE(istring, '(i2)') i
|
WRITE(istring, '(i2)') i
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ MODULE moduleList
|
||||||
END TYPE lNode
|
END TYPE lNode
|
||||||
|
|
||||||
TYPE listNode
|
TYPE listNode
|
||||||
INTEGER:: amount = 0!TODO: Make private
|
INTEGER:: amount = 0
|
||||||
TYPE(lNode),POINTER:: head => NULL()
|
TYPE(lNode),POINTER:: head => NULL()
|
||||||
TYPE(lNode),POINTER:: tail => NULL()
|
TYPE(lNode),POINTER:: tail => NULL()
|
||||||
CONTAINS
|
CONTAINS
|
||||||
|
|
|
||||||
|
|
@ -39,4 +39,14 @@ MODULE moduleMath
|
||||||
|
|
||||||
END FUNCTION normalize
|
END FUNCTION normalize
|
||||||
|
|
||||||
|
!Norm 1 of vector
|
||||||
|
PURE FUNCTION norm1(a) RESULT(b)
|
||||||
|
IMPLICIT NONE
|
||||||
|
REAL(8), DIMENSION(:), INTENT(in):: a
|
||||||
|
REAL(8):: b
|
||||||
|
|
||||||
|
b = SUM(DABS(a))
|
||||||
|
|
||||||
|
END FUNCTION norm1
|
||||||
|
|
||||||
END MODULE moduleMath
|
END MODULE moduleMath
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,7 @@ MODULE moduleOutput
|
||||||
|
|
||||||
END IF
|
END IF
|
||||||
|
|
||||||
WRITE (20, "(I10, I10, 6(ES20.6E3))") t, nPartOld, tStep, tPush, tReset, tColl, tWeight, tEMField
|
WRITE (20, "(I10, I10, 7(ES20.6E3))") t, nPartOld, tStep, tPush, tReset, tColl, tCoul, tWeight, tEMField
|
||||||
|
|
||||||
CLOSE(20)
|
CLOSE(20)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -154,7 +154,7 @@ MODULE moduleSolver
|
||||||
!$OMP DO
|
!$OMP DO
|
||||||
DO n=1, nPartOld
|
DO n=1, nPartOld
|
||||||
!Select species type
|
!Select species type
|
||||||
sp = partOld(n)%sp
|
sp = partOld(n)%species%n
|
||||||
!Checks if the species sp is update this iteration
|
!Checks if the species sp is update this iteration
|
||||||
IF (solver%pusher(sp)%pushSpecies) THEN
|
IF (solver%pusher(sp)%pushSpecies) THEN
|
||||||
!Push particle
|
!Push particle
|
||||||
|
|
@ -483,21 +483,6 @@ MODULE moduleSolver
|
||||||
|
|
||||||
END SUBROUTINE push1DRadCharged
|
END SUBROUTINE push1DRadCharged
|
||||||
|
|
||||||
!Do the collisions in all the cells
|
|
||||||
SUBROUTINE doCollisions()
|
|
||||||
USE moduleMesh
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
INTEGER:: e
|
|
||||||
|
|
||||||
!$OMP DO SCHEDULE(DYNAMIC)
|
|
||||||
DO e=1, mesh%numVols
|
|
||||||
CALL mesh%vols(e)%obj%collision()
|
|
||||||
END DO
|
|
||||||
!$OMP END DO
|
|
||||||
|
|
||||||
END SUBROUTINE doCollisions
|
|
||||||
|
|
||||||
SUBROUTINE doReset()
|
SUBROUTINE doReset()
|
||||||
USE moduleSpecies
|
USE moduleSpecies
|
||||||
USE moduleMesh
|
USE moduleMesh
|
||||||
|
|
@ -623,6 +608,14 @@ MODULE moduleSolver
|
||||||
|
|
||||||
END DO
|
END DO
|
||||||
|
|
||||||
|
!$OMP SECTION
|
||||||
|
!Erase the list of particles inside the cell in coll mesh
|
||||||
|
DO e = 1, meshColl%numVols
|
||||||
|
meshColl%vols(e)%obj%totalWeight = 0.D0
|
||||||
|
CALL meshColl%vols(e)%obj%listPart_in%erase()
|
||||||
|
|
||||||
|
END DO
|
||||||
|
|
||||||
!$OMP END SECTIONS
|
!$OMP END SECTIONS
|
||||||
|
|
||||||
!$OMP SINGLE
|
!$OMP SINGLE
|
||||||
|
|
@ -722,7 +715,7 @@ MODULE moduleSolver
|
||||||
|
|
||||||
part%weight = part%weight * fractionVolume
|
part%weight = part%weight * fractionVolume
|
||||||
|
|
||||||
fractionWeight = part%weight / species(part%sp)%obj%weight
|
fractionWeight = part%weight / part%species%weight
|
||||||
|
|
||||||
IF (fractionWeight >= 2.D0) THEN
|
IF (fractionWeight >= 2.D0) THEN
|
||||||
nSplit = FLOOR(fractionWeight)
|
nSplit = FLOOR(fractionWeight)
|
||||||
|
|
@ -788,6 +781,7 @@ MODULE moduleSolver
|
||||||
|
|
||||||
volOld => mesh%vols(part%vol)%obj
|
volOld => mesh%vols(part%vol)%obj
|
||||||
CALL volOld%findCell(part)
|
CALL volOld%findCell(part)
|
||||||
|
CALL findCellColl(part)
|
||||||
volNew => mesh%vols(part%vol)%obj
|
volNew => mesh%vols(part%vol)%obj
|
||||||
!Call the NA shcme
|
!Call the NA shcme
|
||||||
IF (ASSOCIATED(self%weightingScheme)) THEN
|
IF (ASSOCIATED(self%weightingScheme)) THEN
|
||||||
|
|
@ -831,7 +825,7 @@ MODULE moduleSolver
|
||||||
counterOutput=0
|
counterOutput=0
|
||||||
|
|
||||||
CALL mesh%printOutput(t)
|
CALL mesh%printOutput(t)
|
||||||
CALL mesh%printColl(t)
|
IF (ASSOCIATED(meshForMCC)) CALL meshForMCC%printColl(t)
|
||||||
CALL mesh%printEM(t)
|
CALL mesh%printEM(t)
|
||||||
WRITE(*, "(5X,A21,I10,A1,I10)") "t/tmax: ", t, "/", tmax
|
WRITE(*, "(5X,A21,I10,A1,I10)") "t/tmax: ", t, "/", tmax
|
||||||
WRITE(*, "(5X,A21,I10)") "Particles: ", nPartOld
|
WRITE(*, "(5X,A21,I10)") "Particles: ", nPartOld
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ MODULE moduleSpecies
|
||||||
TYPE, ABSTRACT:: speciesGeneric
|
TYPE, ABSTRACT:: speciesGeneric
|
||||||
CHARACTER(:), ALLOCATABLE:: name
|
CHARACTER(:), ALLOCATABLE:: name
|
||||||
REAL(8):: m=0.D0, weight=0.D0
|
REAL(8):: m=0.D0, weight=0.D0
|
||||||
INTEGER:: sp=0
|
INTEGER:: n=0
|
||||||
END TYPE speciesGeneric
|
END TYPE speciesGeneric
|
||||||
|
|
||||||
TYPE, EXTENDS(speciesGeneric):: speciesNeutral
|
TYPE, EXTENDS(speciesGeneric):: speciesNeutral
|
||||||
|
|
@ -37,8 +37,9 @@ MODULE moduleSpecies
|
||||||
TYPE particle
|
TYPE particle
|
||||||
REAL(8):: r(1:3) !Position
|
REAL(8):: r(1:3) !Position
|
||||||
REAL(8):: v(1:3) !Velocity
|
REAL(8):: v(1:3) !Velocity
|
||||||
INTEGER:: sp !Particle species id
|
CLASS(speciesGeneric), POINTER:: species !Pointer to species associated with this particle
|
||||||
INTEGER:: vol !Index of element in which the particle is located
|
INTEGER:: vol !Index of element in which the particle is located
|
||||||
|
INTEGER:: volColl !Index of element in which the particle is located in the Collision Mesh
|
||||||
REAL(8):: xi(1:3) !Logical coordinates of particle in element e_p.
|
REAL(8):: xi(1:3) !Logical coordinates of particle in element e_p.
|
||||||
LOGICAL:: n_in !Flag that indicates if a particle is in the domain
|
LOGICAL:: n_in !Flag that indicates if a particle is in the domain
|
||||||
REAL(8):: weight=0.D0 !weight of particle
|
REAL(8):: weight=0.D0 !weight of particle
|
||||||
|
|
@ -48,6 +49,7 @@ MODULE moduleSpecies
|
||||||
|
|
||||||
!Number of old particles
|
!Number of old particles
|
||||||
INTEGER:: nPartOld
|
INTEGER:: nPartOld
|
||||||
|
!Number of injected particles
|
||||||
INTEGER:: nPartInj
|
INTEGER:: nPartInj
|
||||||
!Arrays that contain the particles
|
!Arrays that contain the particles
|
||||||
TYPE(particle), ALLOCATABLE, DIMENSION(:), TARGET:: partOld !array of particles from previous iteration
|
TYPE(particle), ALLOCATABLE, DIMENSION(:), TARGET:: partOld !array of particles from previous iteration
|
||||||
|
|
@ -60,15 +62,18 @@ MODULE moduleSpecies
|
||||||
|
|
||||||
CHARACTER(:), ALLOCATABLE:: speciesName
|
CHARACTER(:), ALLOCATABLE:: speciesName
|
||||||
INTEGER:: sp
|
INTEGER:: sp
|
||||||
INTEGER:: n
|
INTEGER:: s
|
||||||
|
|
||||||
sp = 0
|
sp = 0
|
||||||
DO n = 1, nSpecies
|
DO s = 1, nSpecies
|
||||||
IF (speciesName == species(n)%obj%name) THEN
|
IF (speciesName == species(s)%obj%name) THEN
|
||||||
sp = species(n)%obj%sp
|
sp = species(s)%obj%n
|
||||||
EXIT
|
EXIT !If a species is found, exit the loop
|
||||||
|
|
||||||
END IF
|
END IF
|
||||||
|
|
||||||
END DO
|
END DO
|
||||||
|
|
||||||
!If no species is found, call a critical error
|
!If no species is found, call a critical error
|
||||||
IF (sp == 0) CALL criticalError('Species ' // speciesName // ' not found.', 'speciesName2Index')
|
IF (sp == 0) CALL criticalError('Species ' // speciesName // ' not found.', 'speciesName2Index')
|
||||||
|
|
||||||
|
|
@ -83,7 +88,7 @@ MODULE moduleSpecies
|
||||||
TYPE(particle), INTENT(inout):: part
|
TYPE(particle), INTENT(inout):: part
|
||||||
|
|
||||||
IF (ASSOCIATED(self%ion)) THEN
|
IF (ASSOCIATED(self%ion)) THEN
|
||||||
part%sp = self%ion%sp
|
part%species => self%ion
|
||||||
|
|
||||||
ELSE
|
ELSE
|
||||||
CALL criticalError('No ion defined for species' // self%name, 'ionizeNeutral')
|
CALL criticalError('No ion defined for species' // self%name, 'ionizeNeutral')
|
||||||
|
|
@ -101,7 +106,7 @@ MODULE moduleSpecies
|
||||||
TYPE(particle), INTENT(inout):: part
|
TYPE(particle), INTENT(inout):: part
|
||||||
|
|
||||||
IF (ASSOCIATED(self%ion)) THEN
|
IF (ASSOCIATED(self%ion)) THEN
|
||||||
part%sp = self%ion%sp
|
part%species => self%ion
|
||||||
|
|
||||||
ELSE
|
ELSE
|
||||||
CALL criticalError('No ion defined for species' // self%name, 'ionizeCharged')
|
CALL criticalError('No ion defined for species' // self%name, 'ionizeCharged')
|
||||||
|
|
@ -119,7 +124,7 @@ MODULE moduleSpecies
|
||||||
TYPE(particle), INTENT(inout):: part
|
TYPE(particle), INTENT(inout):: part
|
||||||
|
|
||||||
IF (ASSOCIATED(self%neutral)) THEN
|
IF (ASSOCIATED(self%neutral)) THEN
|
||||||
part%sp = self%neutral%sp
|
part%species => self%neutral
|
||||||
|
|
||||||
ELSE
|
ELSE
|
||||||
CALL criticalError('No neutral defined for species' // self%name, 'neutralizeCharged')
|
CALL criticalError('No neutral defined for species' // self%name, 'neutralizeCharged')
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue