00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "Electrodes.hpp"
00030 #include "DistributedTetrahedralMesh.hpp"
00031
00032 template<unsigned DIM>
00033 Electrodes<DIM>::Electrodes(AbstractTetrahedralMesh<DIM,DIM>& rMesh,
00034 bool groundSecondElectrode,
00035 unsigned index,
00036 double lowerValue,
00037 double upperValue,
00038 double magnitude,
00039 double startTime,
00040 double duration)
00041 : mStartTime(startTime),
00042 mpMesh(&rMesh),
00043 mLeftElectrodeArea(0.0),
00044 mRightElectrodeArea(0.0)
00045 {
00046 assert(index < DIM);
00047 mGroundSecondElectrode = groundSecondElectrode;
00048 assert(duration > 0);
00049 mEndTime = mStartTime + duration;
00050 mAreActive = false;
00051
00052
00053 double local_min = DBL_MAX;
00054 double local_max = -DBL_MAX;
00055
00056 for (typename AbstractTetrahedralMesh<DIM,DIM>::NodeIterator iter=mpMesh->GetNodeIteratorBegin();
00057 iter != mpMesh->GetNodeIteratorEnd();
00058 ++iter)
00059 {
00060 double value = (*iter).rGetLocation()[index];
00061 if (value < local_min)
00062 {
00063 local_min = value;
00064 }
00065 if (value > local_max)
00066 {
00067 local_max = value;
00068 }
00069 }
00070
00071 double global_min;
00072 double global_max;
00073
00074 int mpi_ret = MPI_Allreduce(&local_min, &global_min, 1, MPI_DOUBLE, MPI_MIN, PETSC_COMM_WORLD);
00075 assert(mpi_ret == MPI_SUCCESS);
00076 mpi_ret = MPI_Allreduce(&local_max, &global_max, 1, MPI_DOUBLE, MPI_MAX, PETSC_COMM_WORLD);
00077 assert(mpi_ret == MPI_SUCCESS);
00078
00079 if (fabs(global_min - lowerValue) > 1e-6)
00080 {
00081 EXCEPTION("Minimum value of coordinate is not the value given");
00082 }
00083 if (fabs(global_max - upperValue) > 1e-6)
00084 {
00085 EXCEPTION("Maximum value of coordinate is not the value given");
00086 }
00087
00088 mpBoundaryConditionsContainer.reset(new BoundaryConditionsContainer<DIM,DIM,2>);
00089
00090
00091 double input_flux;
00092 double output_flux;
00093
00094 try
00095 {
00096 ComputeElectrodesAreasAndCheckEquality(index, lowerValue, upperValue);
00097 input_flux = magnitude;
00098 output_flux = -input_flux;
00099
00100 }
00101 catch (Exception& e)
00102 {
00103
00104 input_flux = magnitude;
00105 output_flux = -input_flux*mLeftElectrodeArea/mRightElectrodeArea;
00106
00107
00108 assert( ! std::isnan(output_flux));
00109 assert( output_flux != 0.0);
00110 }
00111
00112 ConstBoundaryCondition<DIM>* p_bc_flux_in = new ConstBoundaryCondition<DIM>(input_flux);
00113 ConstBoundaryCondition<DIM>* p_bc_flux_out = new ConstBoundaryCondition<DIM>(output_flux);
00114
00115
00116
00117 for (typename AbstractTetrahedralMesh<DIM,DIM>::BoundaryElementIterator iter
00118 = mpMesh->GetBoundaryElementIteratorBegin();
00119 iter != mpMesh->GetBoundaryElementIteratorEnd();
00120 iter++)
00121 {
00122 if (fabs((*iter)->CalculateCentroid()[index] - lowerValue) < 1e-6)
00123 {
00124 mpBoundaryConditionsContainer->AddNeumannBoundaryCondition(*iter, p_bc_flux_in, 1);
00125 }
00126
00127 if (!mGroundSecondElectrode)
00128 {
00129 if (fabs((*iter)->CalculateCentroid()[index] - upperValue) < 1e-6)
00130 {
00131 mpBoundaryConditionsContainer->AddNeumannBoundaryCondition(*iter, p_bc_flux_out, 1);
00132 }
00133 }
00134 }
00135
00136
00137
00138 if (mGroundSecondElectrode)
00139 {
00140 ConstBoundaryCondition<DIM>* p_zero_bc = new ConstBoundaryCondition<DIM>(0.0);
00141
00142 this->mpBoundaryConditionsContainer->ResetDirichletCommunication();
00143
00144 for (typename AbstractTetrahedralMesh<DIM,DIM>::NodeIterator iter=mpMesh->GetNodeIteratorBegin();
00145 iter != mpMesh->GetNodeIteratorEnd();
00146 ++iter)
00147 {
00148 if (fabs((*iter).rGetLocation()[index]-upperValue) < 1e-6)
00149 {
00150 mpBoundaryConditionsContainer->AddDirichletBoundaryCondition(&(*iter), p_zero_bc, 1);
00151 }
00152 }
00153
00154
00155 delete p_bc_flux_out;
00156 }
00157 }
00158
00159
00160 template<unsigned DIM>
00161 boost::shared_ptr<BoundaryConditionsContainer<DIM,DIM,2> > Electrodes<DIM>::GetBoundaryConditionsContainer()
00162 {
00163
00164 return mpBoundaryConditionsContainer;
00165 }
00166
00167
00168 template<unsigned DIM>
00169 bool Electrodes<DIM>::SwitchOff(double time)
00170 {
00171
00172 double smidge = 1e-10;
00173 if (mAreActive && time>mEndTime-smidge)
00174 {
00175 mAreActive = false;
00176 return true;
00177 }
00178
00179 return false;
00180 }
00181
00182 template<unsigned DIM>
00183 bool Electrodes<DIM>::SwitchOn(double time)
00184 {
00185
00186 double smidge = 1e-10;
00187 if (!mAreActive && time>=mStartTime && time<=mEndTime - smidge)
00188 {
00189 mAreActive = true;
00190 return true;
00191 }
00192
00193 return false;
00194 }
00195
00196 template<unsigned DIM>
00197 void Electrodes<DIM>::ComputeElectrodesAreasAndCheckEquality(unsigned dimensionIndex, double lowerValue, double upperValue)
00198 {
00199
00200
00201
00202 double local_left_area = 0.0;
00203 double local_right_area = 0.0;
00204
00205 c_vector<double,DIM> weighted_direction;
00206 double jacobian_determinant;
00207
00208
00209 for (typename AbstractTetrahedralMesh<DIM,DIM>::BoundaryElementIterator iter
00210 = mpMesh->GetBoundaryElementIteratorBegin();
00211 iter != mpMesh->GetBoundaryElementIteratorEnd();
00212 iter++)
00213 {
00214 if ( mpMesh->CalculateDesignatedOwnershipOfBoundaryElement( (*iter)->GetIndex() ))
00215 {
00216 if (fabs((*iter)->CalculateCentroid()[dimensionIndex] - lowerValue) < 1e-6)
00217 {
00218 mpMesh->GetWeightedDirectionForBoundaryElement((*iter)->GetIndex(), weighted_direction, jacobian_determinant);
00219 local_left_area += jacobian_determinant;
00220 }
00221
00222 if (fabs((*iter)->CalculateCentroid()[dimensionIndex] - upperValue) < 1e-6)
00223 {
00224 mpMesh->GetWeightedDirectionForBoundaryElement((*iter)->GetIndex(), weighted_direction, jacobian_determinant);
00225 local_right_area += jacobian_determinant;
00226 }
00227 }
00228 }
00229
00230 if(DIM==3)
00231 {
00232
00233
00234
00235
00236
00237
00238
00239 local_left_area /= 2.0;
00240 local_right_area /= 2.0;
00241 }
00242
00243 int mpi_ret = MPI_Allreduce(&local_left_area, &mLeftElectrodeArea, 1, MPI_DOUBLE, MPI_SUM, PETSC_COMM_WORLD);
00244 assert(mpi_ret == MPI_SUCCESS);
00245
00246 mpi_ret = MPI_Allreduce(&local_right_area, &mRightElectrodeArea, 1, MPI_DOUBLE, MPI_SUM, PETSC_COMM_WORLD);
00247 assert(mpi_ret == MPI_SUCCESS);
00248
00249 if (mLeftElectrodeArea != mRightElectrodeArea)
00250 {
00251 EXCEPTION("Electrodes have different area");
00252 }
00253 }
00254
00255
00257
00259
00260 template class Electrodes<1>;
00261 template class Electrodes<2>;
00262 template class Electrodes<3>;
00263
00264
00265
00266 #include "SerializationExportWrapperForCpp.hpp"
00267 EXPORT_TEMPLATE_CLASS_SAME_DIMS(Electrodes);